mcpField
D
doc-bdd-fixer

doc-bdd-fixer

github.com/vladm3105Testing & quality1736 installsUpdated 1d ago
Repository

About doc-bdd-fixer

A skill for repairing BDD suites from `doc-bdd-audit` reports, applying fixes in defined phases. It supports team validation or single-pass remediation and produces a fix report.

Key features

  1. 01Address BDD issues from audit reports
  2. 02Fix structure, links, IDs, and content in phases
  3. 03Validate blocking fixes in team mode
  4. 04Revert patches that cause regressions
  5. 05Produce fix reports and update the saga

Use cases

  1. 01Repair a suite after a failed BDD audit
  2. 02Correct BDD structure and relative links
  3. 03Restore traceability and metadata
  4. 04Validate blocking fixes and record results

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/vladm3105/aidoc-flow-framework --skill doc-bdd-fixer

After installing, type/doc-bdd-fixerin Claude Code to confirm it loaded.

Details

From the project README

doc-bdd-fixer

Purpose

Read the latest audit report and apply fixes to a BDD suite, bridging ../doc-bdd-audit/SKILL.md and a passing BDD so the audit↔fix cycle can converge.

Layer: 4 (BDD quality improvement). Upstream: the BDD document + .aidoc/audit/04_BDD-audit.md. Downstream: the fixed BDD + BDD-NN.F_fix_report_vNNN.md.

When to Use

After doc-bdd-audit returns FAIL, as part of an Audit → Fix → Audit loop. Do not use without an audit report (run the audit first) or to create a new BDD (use ../doc-bdd/SKILL.md / ../doc-bdd-autopilot/SKILL.md).

Input Contract

Consume the .aidoc/audit/04_BDD-audit.md report. Back up the BDD before editing (tmp/backup/BDD-NN_<ts>/); on error, restore. Element-ID standards come from ${CLAUDE_PLUGIN_ROOT}/framework/governance/ID_NAMING_STANDARDS.md; structure and the YAML scenario schema from ${CLAUDE_PLUGIN_ROOT}/framework/layers/04_BDD/BDD-TEMPLATE.yaml and README.md.

Remediate Mode

Resolve review_mode from .aidoc/profile.yaml; if unset, fall through to the framework default team per the precedence chain in ${CLAUDE_PLUGIN_ROOT}/framework/governance/ADAPTATION.md. Same fallback applies to other adaptation knobs (section_toggles).

team mode (per REVIEW_TEAM.md §Operations §Remediate)
  1. Read the audit report at .aidoc/audit/04_BDD-audit.md AND, when present, the per-persona slots under .aidoc/review/04_BDD/<BDD-id>/ (where <BDD-id> is the short artifact ID, e.g. BDD-01).

    • Prefer the per-persona slots for the structured findings — stable ids, priorities, locations, recommendations.
    • Slots are optional — when absent (e.g. single_pass run produced no synthesizer output), fall back to parsing the audit report's Findings sections directly.
  2. Resolve responsible lenses per finding. Each blocking finding (P0 + P1) carries a personas array in the synthesizer's reduced form OR can be inferred from per-lens slot membership. Dispatch rules:

    • Single-lens finding (1 persona): dispatch that lens.
    • Multi-lens finding (2+ personas): dispatch all listed lenses in parallel. Each writes its own <persona>.fix_<N>.json slot. The fix is accepted only when every dispatched lens returns no new P0/P1 (any one lens regressing reverts the patch).
    • No-persona / orphan finding (empty or missing personas): dispatch the BDD crew's author lens (per REVIEW_CREWS.yaml: qa_lead for BDD) as the default responsible reviewer.

    Lens → agent map for BDD:

    LensAgent
    qa_leadaidoc-flow:test-architect
    tech_leadaidoc-flow:solutions-architect
    chaos_engineeraidoc-flow:chaos-engineer
    security_engineeraidoc-flow:security-engineer
    operatoraidoc-flow:devops-release-engineer
    auditoraidoc-flow:traceability-auditor

    BDD crew weights: {qa_lead: 35, tech_lead: 25, chaos_engineer: 14, security_engineer: 6, operator: 10, auditor: 10}.

    P2/P3 are advisory — apply deterministically without lens validation.

  3. Propose and apply a patch per blocking finding. Fix Phases 0–7 below describe the patch shapes; the catalogue is the same in both modes. Back up first per the existing Input Contract.

  4. Validate non-regression. For each responsible lens identified in step 2, dispatch one Task subagent in patch-validation mode: subagent_type=<mapped agent>; brief = the patched region + the original finding + the patch diff; the lens MUST NOT read, cite, or weight any author self-assessment score (*_ready_score/*_score/ readiness_score/audit_score) when forming its lens_score (REVIEW_TEAM.md GD-05); output = a fresh persona-output record (lens_score for the patched region + any new findings). Persist each lens's output as .aidoc/review/04_BDD/<BDD-id>/<persona>.fix_<N>.json (<N> = sequential fix-iteration counter, starting at 1). Multi-lens findings produce one slot file per responsible lens for the same <N>.

  5. Revert regressions. If any lens returns new P0/P1 on the patch, revert that patch and flag manual_required for the original finding. Never silently keep a regressing fix.

  6. Dispatch the synthesizer once (subagent_type=aidoc-flow:synthesizer), after all patches are validated, to emit the unified fix report. Persist BDD-NN.F_fix_report_vNNN.md with both the Fixes Applied table AND a Validation Slots index.

single_pass mode (fallback)

Apply Phase 0–7 directly, single-handed, no lens validation. Unchanged legacy behaviour — required when the profile says so, when Task subagent dispatch is unavailable, or when no slots are present.

In both modes, P2/P3 advisory findings are applied without lens validation; only blocking findings (P0/P1) go through the patch-validation loop in team mode.

Saga interaction

When invoked by doc-bdd-autopilot (or directly), this skill reads and updates the saga journal at .aidoc/review/04_BDD/<BDD-id>/saga.json per ${CLAUDE_PLUGIN_ROOT}/framework/governance/REVIEW_SAGA.md. The fixer acts as the remediation stage of the saga: it transitions branches to BRANCH_COMPENSATING during patch validation, then back to BRANCH_COMPLETED (validated) or BRANCH_FAILED (regression detected).

On entry

At entry, write the fixer's start epoch:

Bash: mkdir -p .aidoc/review/04_BDD/<BDD-id>/ && date +%s > .aidoc/review/04_BDD/<BDD-id>/.skill-start.fixer

If .aidoc/review/04_BDD/<BDD-id>/saga.json exists, read it. Validate that current saga status is FANIN_REDUCED (post-audit) or BRANCH_FAILED (re-entering after a prior fixer regression). If status is something else, log a warning and proceed.

During patch validation (team mode)

For each blocking finding (P0/P1) that requires lens validation:

  1. Before dispatching the responsible lens validator(s): for each lens in the finding's personas[] list, append a transition: {"ts": "<now>", "from": "BRANCH_COMPLETED", "to": "BRANCH_COMPENSATING", "scope": "branch:<lens>"}. Update branches[<lens>].status to "BRANCH_COMPENSATING". Append an entry to compensation_actions[]: {"ts": "<now>", "branch": "<lens>", "reason": "<finding_id>: <message>", "action": "retry"}.
  2. After the validation Task subagent returns:
    • If patch validated (no regression): transition back to BRANCH_COMPLETED. Update compensation_actions[] last entry with the validation result.
    • If patch regresses (lens flags new P0/P1 on patched region): transition to BRANCH_FAILED. Set compensation_actions[] last entry's action to "escalate". The finding becomes manual_required.
Before synthesizer dispatch

Per REVIEW_SAGA.md §"Break-circuit policy" — the fixer's checkpoint boundary is between multi-lens validation dispatches (each blocking finding's per-lens validation is one boundary). Before dispatching the next validation:

Bash: echo $(( $(date +%s) - $(cat .aidoc/review/04_BDD/<BDD-id>/.skill-start.fixer) ))

If elapsed > SOFT_DEADLINE (1500s):

  • Append transition: {"ts": "<now>", "from": "BRANCH_COMPENSATING", "to": "PARTIAL_TIMEOUT", "scope": "run"}.
  • Set saga status: "PARTIAL_TIMEOUT". Preserve all completed validations (their fix_N.json slots remain durable). Set current_phase: "fixer" so the resume invocation knows to continue the remaining validations.
  • Update updated_at. Write saga.json. Exit cleanly.

The remaining validations resume on next invocation per doc-bdd-autopilot's §3.4 resume logic.

After synthesizer reduce
  • Append transition: {"ts": "<now>", "from": "BRANCH_COMPENSATING", "to": "BRANCH_COMPLETED", "scope": "run"} (run-level: fixer pass complete).
  • Update saga status: "BRANCH_COMPLETED" (autopilot's next phase will be re-review).
  • Update updated_at. Write saga.json.
When invoked standalone (no saga.json on entry)

If .aidoc/review/04_BDD/<BDD-id>/saga.json does NOT exist (user runs /aidoc-flow:doc-bdd-fixer directly outside the autopilot loop), do NOT initialize the full saga schema. Log saga.json not present; running fixer without saga journal (standalone mode). Run the fix phases as usual; write the fix report; skip all saga.json transitions. Backward-compatible with direct skill invocation.

When invoked in single_pass mode

If review_mode: single_pass is active, the fixer applies patches deterministically without lens validation and without writing saga.json. Existing behavior preserved.

Break-circuit policy

Per ${CLAUDE_PLUGIN_ROOT}/framework/governance/REVIEW_SAGA.md §"Break-circuit policy", this skill checks elapsed wall-clock at one checkpoint boundary: after all per-finding patches return and before invoking the synthesizer. The SOFT_DEADLINE is 1500s (ORCHESTRATOR_TIMEOUT=1800s minus 300s buffer).

If the soft deadline has been crossed, exit cleanly with saga status: "PARTIAL_TIMEOUT" per §"Before synthesizer dispatch" above. The fixer's partial progress (fix_N.json slots already written) is durable; resumed invocation continues from where the break-circuit fired.

Fix Phases

Run in order; later phases assume the earlier ones succeeded.

PhaseScopeRepresentative actions
0 — Structurefolder/index rulemove BDD into docs/04_BDD/BDD-NN_{slug}/; rename folder to match ID; ensure index present; fix relative links after the move
1 — Missing filesreferenced-but-absentcreate glossary / index placeholders from templates
2 — Linksbroken/abs pathsrecompute relative paths; convert absolute → relative
3 — Element IDslegacy/invalid IDsre-derive BDD.NN.SS.xxxx (section + content hash); drop legacy BDD.NN.xxxx, numeric type-codes, SCEN-XXX/STEP-XXX prefixes
4 — Contentplaceholders, fields, thresholdsfill template dates; add missing scenario fields (type/priority/ears/id); add inline WITHIN @threshold:; flag [TODO]/[TBD] and missing given/when/then phase lists (BDD-SCHEMA-001) for manual completion
5 — Referencestraceabilityensure each scenario carries an element-level ears: list (BDD's required_tags per LAYER_REGISTRY.yaml necessary-upstream contract); fix cross-doc paths; add/repair spec_trace; update the traceability matrix
6 — Upstreammetadata + driftfix deliverable_type/document_type/upstream_mode; when upstream EARS drifts, apply tiered drift merge (below)
7 — StyleSTY01 banned phrases, STY02/03 oversized prose, FM01 frontmatter mismatchsubstitute filler; replace flagged superlatives; collapse paragraph (≥ 3 banned phrases in one section) to bullets; reconcile frontmatter ↔ Document Control rows; STY02/03 — split oversized Scenario blocks at category boundaries, or mark manual_required. Authority: ${CLAUDE_PLUGIN_ROOT}/framework/governance/AUTHORING_STYLE.md

Element ID re-derivation: BDD.{doc_id}.{section_id}.{hash} — assign a stable 4-hex-char identifier, distinct within its section (HASH01), extending to 8 on collision. Do not compute SHA-256 here: the hash form is the canonicalization TARGET produced by a deterministic tool pass, and byte-exact field extraction is defined for BRD §7 only (Phase 2+ for BDD). Preserve an existing valid ID — re-deriving one breaks every downstream citation. Authority: framework/governance/ID_NAMING_STANDARDS.md. Document-level refs (SPEC-NN, ADR-NN, IPLAN-NN) stay in dash form; scenarios live in section 03.

Content-preservation: never modify scenario step text (given/when/then) or examples data; only add missing fields/metadata and replace hardcoded values with inline @threshold: references. Missing fields/structure are flagged, not invented. On migration from Gherkin, copy each @scenario-id verbatim into the scenario id: — never recompute the hash (keeps downstream @bdd: stable).

Tiered upstream drift (EARS changed since BDD): <5% change → Tier 1 auto-merge new scenarios (patch bump); 5–15% → Tier 2 auto-merge + detailed changelog, mark modified-source scenarios for review (minor bump); >15% → Tier 3 archive current + regenerate via autopilot (major bump). Never delete upstream-removed scenarios — mark @deprecated and retain for traceability. Record results in .drift_cache.json.

Confidence Classification

Tag every applied fix and surface counts in the report:

ConfidenceMeaning
auto-safedeterministic, low semantic risk (link/path, tag relocation, ID conversion, threshold substitution)
auto-assistedtemplate insertion with partial assumptions (scaffolded scenarios/sections, default priority tags)
manual-requireddomain content cannot be inferred (unresolved TODO/TBD, missing Given-When-Then, step semantics)

Content-Preservation Rules

  • Never delete existing scenario content; insert template blocks only where a section or scenario is missing or below minimum structure.
  • Carry scenario upstream trace as ears: list fields (not @-tags); never duplicate.
  • Renumber/restructure only within the same document; flag if a cross-reference anchor would break.

Fix Report Format

Table-pipe escape (MD056)

When emitting markdown table cells that contain code spans with shell pipes (e.g. `docker compose ps | grep 'Up'`), the unescaped | inside the code span is parsed by markdownlint as a column separator, tripping MD056 (column-count mismatch). Two fixes:

  • Preferred: escape the pipe inside the code span as \| — renders as | in markdown viewers but doesn't break the table. Example row: | OP-02 | ... | `docker compose ps \| grep 'Up'` | ... |
  • Alternative: move the code span out of the table cell and reference it as a footnote or paragraph below the table. The cell then carries plain prose like "shell readiness gate (see below)".

Apply to every report row that emits a shell-pipe code span inside a table cell. Cascade-output that trips MD056 is a SKILL bug, not a markdownlint over-strictness — fix here, not by lint-ignoring.

Write BDD-NN.F_fix_report_vNNN.md with: Summary (issues in / fixed / remaining; files created / modified) · Fixes Applied (code, issue, fix, file, confidence) · Manual-Review Queue · Validation After Fix (score/errors/warnings before→after) · Cleanup Summary (delete superseded fix reports) · Next Steps (re-run doc-bdd-audit). Loop until score ≥ threshold or max iterations reached.

Adaptation

Before applying fixes, read the project adaptation profile (.aidoc/profile.yaml). Honor section_toggles: do not reintroduce an optional section the project has toggled off. Ignore any unknown or out-of-surface key. Authority: ${CLAUDE_PLUGIN_ROOT}/framework/governance/ADAPTATION.md.

Related Resources

  • Audit (input): ../doc-bdd-audit/SKILL.md · Create: ../doc-bdd/SKILL.md
  • Orchestration: ../doc-bdd-autopilot/SKILL.md · IDs: ../doc-naming/SKILL.md
  • Authority: ${CLAUDE_PLUGIN_ROOT}/framework/layers/04_BDD/BDD-TEMPLATE.yaml, ${CLAUDE_PLUGIN_ROOT}/framework/governance/ID_NAMING_STANDARDS.md

Comments

Markdown supported