Infer the product's ISO 25010:2023 quality-profile.yaml (characteristic-level targets, security profile, risk register) from scan-index.json during /codify, grounding every characteristic level and every risk entry in concrete scan-index signals and tagging source_type=inferred_from_code. Used exclusively by test-engineer in the /codify play.
Scanned 9/10/2026
Install to Claude Code
npx -y skills add kapilvirenahuja/garura --skill infer-quality-profile-from-code --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Infer Quality Profile From Code?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/kapilvirenahuja-infer-quality-profile-from-code)More formats (shields.io, HTML) on the badges page.
---
name: infer-quality-profile-from-code
description: Infer the product's ISO 25010:2023 quality-profile.yaml (characteristic-level targets, security profile, risk register) from scan-index.json during /codify, grounding every characteristic level and every risk entry in concrete scan-index signals and tagging source_type=inferred_from_code. Used exclusively by test-engineer in the /codify play.
version: 0.1.0
user-invocable: false
model: sonnet
allowed-tools: Read, Write, Grep, Glob
deprecated: true
deprecated_note: '#434 ProductOS realignment — superseded by the command model; retained for Phase E reference, not installed'
---
# infer-quality-profile-from-code
Called by `test-engineer` during /codify. Produces `specification/quality-profile.yaml` at `{stm_base}/{issue}/evidence/codify/proposals/specification/quality-profile.yaml`.
## Purpose
During /codify (brownfield bootstrap), the quality-profile artifact that /specify normally derives from intent epics must be reverse-engineered from the existing codebase's tooling posture. This skill consumes `scan-index.json` (produced by `scan-codebase`) and emits a proposal quality-profile whose ISO 25010:2023 characteristic levels, security profile, and risk register are all grounded in scan-index signals. The greenfield peer for this artifact is `derive-quality-profile-from-epics` (specify Stage 6). The output schema MUST round-trip with that peer: it uses ISO 25010:2023 (9 characteristics — `functional_suitability`, `performance_efficiency`, `compatibility`, `interaction_capability`, `reliability`, `security`, `maintainability`, `flexibility`, `safety`) and the reference instance at `.garura/product/specification/quality-profile.yaml` is the shape-of-record.
The task-brief signal list names `usability` and `portability` (ISO 25010:2011 nomenclature); this skill maps `usability → interaction_capability` and `portability → flexibility`, and adds a `safety` bucket whose relevance is inferred from the code (default: `low`, matching the reference, unless safety-critical signals surface).
## Input
Receive from test-engineer via JSON contract.
- `scan_index_path` (path, required) — `scan-index.json` produced by scan-codebase.
- `stm_base` (path, required) — STM root resolved from `.garura/core/config.yaml` `stm.base-path`.
- `issue` (str, required) — issue number driving /codify.
- `output_path` (path, required) — `{stm_base}/{issue}/evidence/codify/proposals/specification/quality-profile.yaml`.
- `decision_manifest_path` (path, required) — `decision-manifest-infer-quality-profile-from-code.yaml` alongside the artifact.
- `ltm_context` (block, required) — `{product_base, core_base, query_domains, locked_artifacts}`. Presence triggers the Resolution Protocol.
- `resolution_trace_path` (path, required) — where `resolution-trace.yaml` is written.
## Process
1. **Validate inputs.** Confirm `scan_index_path` exists and parses as JSON. Confirm `stm_base` exists. Confirm output parent directories exist or create them. Missing scan-index → structured failure `scan_index_missing`.
2. **Check scan status.** Read `scan_status`. If `budget_exhausted`, proceed but cap every characteristic's `confidence` at `low` and record a top-level `meta.scan_status_warning`.
3. **Execute LTM Resolution Protocol** per `core/components/memory/standards/rules/resolution.md` (R1 → R2 → R3 → R4). R3 domains: `quality`, `testing`, `iso-25010`, `security-posture`, `reliability-patterns`. R3 MUST consult `core/components/memory/` for the canonical ISO 25010:2023 taxonomy reference. Write the trace to `resolution_trace_path`. R3 failure → structured failure `ltm_resolution_failed`.
4. **Score each ISO 25010 characteristic.** For each characteristic, resolve a `target_level` (integer 1-5) and a `relevance` (`low`/`mid`/`high`) using the deterministic rubric in the "Signal → Level Rubric" section below. Record, per characteristic, the scan-index JSON paths consulted as `evidence`.
5. **Build the risk register.** Map known tool-posture gaps to risk entries per the "Risk Inference Rules" section. Each risk cites the scan-index path(s) that surfaced it and a severity (high/medium/low) fixed by the rule, not by epic-citation count (that's the greenfield aggregator's job).
6. **Compose `security_profile`** from security-related scan signals per the "Security Profile Derivation" section.
7. **Emit decision manifest first** (DSD). One entry per inferred decision: one per characteristic (`D-iqpc-char-<name>`), one per risk (`D-iqpc-risk-<n>`), one per security_profile slot (`D-iqpc-sec-<slot>`). `grounding_source.kind` is `scan_index | kb_path | none`; `ref` is `scan-index.json#/<path>` or `ltm:<file>`. `tier` is `high` only when the rubric row was matched by a direct scan-index path AND the R3 KB reference resolved; `mid` when only one source held; `low` when neither was conclusive. Every decision carries ≥1 `alternatives_considered` entry.
8. **Write the artifact.** Meta block first, then `quality_profile` body. Meta `evidence` is the deduplicated union of every scan-index path cited across all characteristics, risks, and security slots. Meta `confidence` is the floor of per-characteristic confidence values.
## Signal → Level Rubric
Each row maps scan-index paths to a deterministic `(target_level, relevance)`. Ties break toward the lower level. If every path in a row is empty, score `level: 1, relevance: low` and flag the characteristic `insufficient_signal` in the decision manifest.
- `functional_suitability`
- paths: `patterns.framework_idioms`, `entry_points`, `manifests[*].dependencies`
- rule: framework_idiom count + entry_point count; ≥3 frameworks and ≥2 entry points → level 4 / high; 1 framework + entry points → level 3 / high; entry points only → level 2 / mid; no idioms and no entry points → level 1 / low.
- `performance_efficiency`
- paths: `manifests[*].dependencies`, `config_files.infra`, `config_files.deploy`
- rule: rate-limit middleware OR caching lib (`redis`, `memcached`, `ioredis`, `cache-manager`) OR CDN/edge config in infra → level 4 / mid; any performance-adjacent dep (`compression`, `etag`) only → level 3 / mid; nothing → level 2 / low.
- `compatibility`
- paths: `config_files.docker`, `config_files.ci`, `manifests[*].engines`
- rule: multiple Dockerfile variants OR CI platform/runtime matrix (`strategy.matrix` in workflows) → level 4 / mid; single Dockerfile OR single CI workflow → level 3 / mid; none → level 2 / low.
- `interaction_capability` (maps task's `usability`)
- paths: `frontend_detection`, `manifests[*].dependencies`
- rule: frontend present AND a11y deps (`@axe-core/*`, `eslint-plugin-jsx-a11y`, `aria-*`, `react-aria`) → level 4 / high; frontend present without a11y deps → level 2 / mid; no frontend → `relevance: low`, level 1 (non-applicable).
- `reliability`
- paths: `config_files.ci`, `config_files.test`, `manifests[*].dependencies`, `patterns.test_framework_signals`
- rule: CI with mandatory test stage AND retry/circuit-breaker libs (`p-retry`, `axios-retry`, `opossum`, `resilience4j`, `tenacity`) AND error-monitoring dep (`sentry`, `datadog`, `rollbar`, `bugsnag`) → level 5 / high; CI with mandatory tests → level 4 / high; tests present but not wired in CI → level 2 / mid; no tests → level 1 / low.
- `security`
- paths: `manifests[*].dependencies`, `config_files.ci`, `config_files.lint`
- rule: auth lib (`passport`, `next-auth`, `authlib`, `devise`, `omniauth`) AND (`helmet` OR CSRF middleware) AND secret-scanner in CI (`gitleaks`, `trufflehog`, `detect-secrets`) → level 5 / high; auth lib + one hardening signal → level 4 / high; auth lib only OR hardening only → level 3 / mid; none → level 2 / low.
- `maintainability`
- paths: `config_files.lint`, `config_files.type`, `config_files.test`, `patterns.naming_suffix_counts`
- rule: type-checker config with strict mode (`tsconfig.json strict:true`, `mypy strict`, `pyright strict`) AND lint config AND test config → level 5 / high; type + lint present → level 4 / high; lint only → level 3 / mid; none → level 1 / low.
- `flexibility` (maps task's `portability`)
- paths: `config_files.docker`, `manifests[*]`, `config_files.infra`
- rule: container present AND env-driven config pattern (`.env.example`, `dotenv` dep, `config_files.infra` with env templating) → level 4 / mid; container only → level 3 / mid; none → level 2 / low.
- `safety`
- paths: `manifests[*].dependencies`, `docs.readme_preview`, `config_files.ci`
- rule: safety-critical libs (`iec-61508`, medical/automotive keywords in readme) OR explicit hazard docs → level 3 / mid; otherwise → level 1 / `relevance: low` (matches reference baseline for developer-tooling products).
## Risk Inference Rules
Fixed severity per rule (greenfield derives severity from epic-citation counts; /codify has no epics, so severity is rule-assigned).
| risk_id | trigger (scan-index) | description | severity |
|---------|----------------------|-------------|----------|
| RISK-001 | `config_files.test` empty AND `patterns.test_framework_signals` empty | No test framework detected — reliability/regression risk | high |
| RISK-002 | `config_files.ci` empty | No CI detected — quality gates cannot enforce pre-merge | high |
| RISK-003 | `config_files.lint` empty | No lint configuration — maintainability/style drift risk | medium |
| RISK-004 | `config_files.type` empty on a typed-language manifest (TS/Py/Go) | Type-checker not configured on a typed stack — maintainability risk | medium |
| RISK-005 | auth lib absent AND `frontend_detection` non-empty | User-facing surface with no auth library — security risk | high |
| RISK-006 | secret-scanner absent from CI | No secrets-in-CI guard — credential exposure risk | medium |
| RISK-007 | `manifests[*].dependencies` empty OR malformed | Degenerate manifest — broad signal gap | low |
| RISK-008 | `config_files.docker` empty AND `config_files.deploy` empty | No container or deploy config — portability/flexibility risk | low |
Walk each rule; emit a risk entry only when the trigger fires. Each entry cites the scan-index path that surfaced it under `evidence`.
## Security Profile Derivation
- `authentication.method`: from detected auth lib; else `not_detected`.
- `authorization.model`: `flat` by default; upgrade to `rbac` if `casbin`, `casl`, `oso`, or role-schema files present.
- `data_at_rest.encryption`: `not_detected_v1` unless KMS/crypto libs (`aws-sdk/kms`, `cryptography`, `@aws-crypto/*`) found.
- `data_in_transit.encryption`: `TLS` if any HTTPS-enforcing middleware or ingress TLS config surfaces in `config_files.infra`; else `not_explicitly_mandated`.
- `secrets_management.approach`: `environment-variables` if `.env` / dotenv dep present; `secrets-manager` if `@aws-sdk/client-secrets-manager`, `hashicorp/vault`, or GCP secret-manager deps; else `not_detected`.
- `audit_trail.coverage`: `none` unless monitoring/logging libs present (`winston`, `pino`, `bunyan`, `structlog`) — then `basic`.
- `compliance_mandates`: keyword-scan `docs.readme_preview` + `docs.adrs` for HIPAA/PCI/GDPR/SOC2/ISO-27001/FedRAMP; each hit → entry with `status: declared_in_docs`, `enforcement: not_verified_from_code`.
## Output
Primary artifact at `output_path`:
```yaml
meta:
source_type: "inferred_from_code"
evidence:
- "scan-index.json#/config_files/ci"
- "scan-index.json#/config_files/lint"
- "scan-index.json#/config_files/type"
- "scan-index.json#/config_files/test"
- "scan-index.json#/manifests"
- "scan-index.json#/patterns/framework_idioms"
- "scan-index.json#/frontend_detection"
confidence: "high" | "medium" | "low"
learning_category: "quality"
sub_category: "testing"
tier: 2
scan_status_warning: null
quality_profile:
slug: "{product-slug}"
status: DRAFT
iso_25010:
functional_suitability: { level: <1-5>, relevance: low|mid|high, evidence: [...], confidence: high|medium|low }
performance_efficiency: { ... }
compatibility: { ... }
interaction_capability: { ... }
reliability: { ... }
security: { ... }
maintainability: { ... }
flexibility: { ... }
safety: { ... }
security_profile:
authentication: { method, rationale }
authorization: { model, rationale }
data_at_rest: { encryption, rationale }
data_in_transit: { encryption, coverage }
secrets_management: { approach, rationale }
audit_trail: { coverage, mechanisms }
compliance_mandates: [ { category, status, enforcement, source } ]
compliance_flags: [ "HIPAA" | "PCI" | "GDPR" | "SOC2" | "ISO-27001" | "FedRAMP" ]
risk_register:
- id: RISK-001
description: "{from rule table}"
evidence: [ "scan-index.json#/<path>" ]
severity: high | medium | low
mitigation: "{standard mitigation per risk rule}"
```
Decision manifest at `decision_manifest_path` (DSD-compliant, `D-iqpc-` prefix):
```yaml
schema_version: "1.0"
skill: "infer-quality-profile-from-code"
generated_at: "{ISO8601}"
decisions:
- decision_id: "D-iqpc-char-reliability"
decision_type: "characteristic-level-inference"
tier: high | mid | low
grounding_source: { kind: scan_index | kb_path | none, ref: "...", excerpt: "..." }
recommendation: "{level + relevance with rubric-row citation}"
alternatives_considered: [ { alt: "...", why_not: "..." } ]
agent_reasoning_summary: "..."
user_response: null
user_response_detail: null
# one per characteristic; one per risk (D-iqpc-risk-<n>); one per security slot (D-iqpc-sec-<slot>)
```
Resolution trace at `resolution_trace_path` per resolution.md schema.
No product LTM writes. All output is under STM.
## Failure Modes
- `scan_index_missing` — `scan_index_path` does not exist or is not valid JSON.
- `scan_status_exhausted` — scan-index has `scan_status: budget_exhausted`; skill proceeds, caps confidence at `low`, records `meta.scan_status_warning`.
- `ltm_resolution_failed` — Resolution Protocol R3 raised an error; skill halts and returns the trace path for triage.
- `insufficient_signal` — `config_files` completely empty AND `manifests` empty (degenerate repo); emit the artifact with every characteristic at `level: 1, relevance: low`, `meta.confidence: "low"`, and risk_register populated only with RISK-007.
- `output_parent_missing` — `output_path` parent cannot be created; return structured failure.
## Boundaries
- Read-only against the codebase. The scan-index is the sole input — this skill does NOT open source files directly.
- Signals not listed in the Signal → Level Rubric or Risk Inference Rules MUST NOT be invented; absence of a signal lowers confidence, never fabricates a value.
- Severity in /codify risk register is rule-assigned, NOT epic-citation-aggregated (that is the greenfield peer's job).
- No writes outside `{stm_base}/{issue}/evidence/codify/proposals/specification/` and the two companion files (decision manifest, resolution trace).
- Never commit a characteristic level or risk entry to the primary artifact without a matching decision-manifest entry written first (DSD).
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!