--- name: mockup-feedback-patch description: "Use when a triage file exists for a feedback session and you need to author diffs for each annotation. Produces patches/.json + patches/.review.md (LLM for change; templated for add/remove/question). Third skill in the mockup-feedback cluster." metadata: version: "0.1.0" tags: [mockup-feedback, patch, diff, review] stage: alpha artifacts: requires: - id: feedback-triage gate: hard produces: - id: feedback-patches - id: feedback-patches-review prerequisites: files: - path: "_concept/_feedback/triage/" gate: hard description: "triage/.json from mockup-feedback-triage" min_entries: 1 produces: - path: "_concept/_feedback/patches/.json" description: "Machine-readable patch list" - path: "_concept/_feedback/patches/.review.md" description: "Human-editable checklist; tick boxes before running apply" --- # mockup-feedback-patch ## Overview For each `(file, annotations)` group in `triage/.json`: 1. Read the target `_concept/` file (frontmatter + body). 2. For each annotation, author a **section-anchored unified diff** in the target file's prose voice. 3. For annotations on provisional elements, also emit a `kind: "provisional-promotion"` diff. 4. For annotations that express **navigation intent** on an element whose `elements:` entry has no `target:` yet, also emit a `kind: "target-promotion"` diff (see *Target promotion* below). 5. For annotations that change **testable behavior** (see *Test impact* below), author a one-line suggested test scenario. 6. Write `patches/.json` (machine-readable) and `patches/.review.md` (human checklist, all auto-items pre-checked). Each patch entry in `patches/.json` must include a `body` field copied verbatim from `annotation.body`. This preserves the annotation's original text in the committed `applied/.json` audit trail (D6), since `sessions/` is gitignored and rotates. Run after `mockup-feedback-triage`. Run `mockup-feedback-apply` after the user reviews and edits `review.md`. --- ## Diff format All diffs use section-anchored headers, NOT line-number offsets: ``` @@ ## Section Name @@ - line to remove (full content including any markdown bullet) + line to add ``` For frontmatter edits: ``` @@ frontmatter:elements @@ - - id: - provisional: true + - id: + provisional: false ``` The `apply.py` script parses these headers. Do not use standard `git diff` format (no `@@` with line numbers). --- ## Category templates ### `category=change` LLM call: read the section the annotation's element appears in, rewrite to incorporate the annotation's intent. Output a unified diff of that section. Scope the diff to the relevant lines only. ### `category=add` Append `- ` under the most appropriate section (typically `## States` for state additions, `## Behavior` for behavior additions). If the section is absent, use `kind: "create-section"` and include `+## ` as the first add line. Template: ``` @@ ## States @@ + - ``` ### `category=remove` Strikethrough the matching line: Template: ``` @@ ##
@@ - - + - ~~~~ ``` ### `category=question` Append to `## Open Questions` (create section if absent): Template: ``` @@ ## Open Questions @@ + - ``` --- ## Provisional promotion When `specRef.provisional=true` for an annotation that produces a content diff, also emit a second patch with `kind: "provisional-promotion"`: ```json { "id": "p--promotion", "annotationId": "", "file": "", "section": "frontmatter:elements", "kind": "provisional-promotion", "category": null, "diff": "@@ frontmatter:elements @@\n- - id: \n- provisional: true\n+ - id: \n+ provisional: false\n" } ``` Read the file's `elements:` frontmatter block to get the exact indentation. If frontmatter is missing or unparseable, skip the promotion patch and print a warning — do not abort. --- ## Target promotion When an annotation's body clearly asks for an element to become a navigation target ("this should link to…", "clicking this should open…", "make this go to the X screen") and the element's `elements:` frontmatter entry has no `target:` field, resolve the intended destination to a `screen_id` (using the manifest's screen list / rendered_html mapping) and emit a second patch with `kind: "target-promotion"` adding the field. If the destination cannot be resolved with confidence, skip the promotion patch and emit a `needs_manual` entry instead (reason: "navigation intent unresolved — no matching screen"). ```json { "id": "p--target", "annotationId": "", "file": "", "section": "frontmatter:elements", "kind": "target-promotion", "category": null, "diff": "@@ frontmatter:elements @@\n- - id: \n+ - id: \n+ target: \n" } ``` --- ## Test impact A patch changes **testable behavior** when: - the target is a **feature** file and the diff touches `## Requirements`, `## Error States`, `## Success Criteria`, or `## Permissions`, or - the target is a **screen** file and the diff touches `## Behavior` or `## States`, or - `category=add` introduces a new state, behavior, or error case. For each such patch, author a single suggested test scenario tagged with its category (Happy / Error / Edge / Permissions) and, where the target feature has `story_refs:`, the relevant `story-id`. These are **suggestions for `test-plan`**, not diffs — they are not applied to concept files and never carry a checkbox. Collect them under `## Test impact` in `review.md` (see format below). They close the feedback→test loop: after `mockup-feedback-apply` lands the spec edits, re-running `impl-quality-test-plan` regenerates scenarios from the updated features/screens, and these suggestions flag what to confirm got covered. Purely cosmetic patches (copy, tokens, layout, provisional-promotion, target-promotion) have no test impact — omit them. --- ## Handling unautomatable annotations If an annotation cannot be patched (empty body, contradictory intent, unrecoverable target), emit a `needs_manual` entry instead of a patch: ```json { "annotationId": "", "reason": "" } ``` Do NOT add a checklist item in `review.md` for this annotation. DO add a bullet under `## Needs manual review` in `review.md`: ```markdown ## Needs manual review - annotation `` — ``` --- ## review.md format ```markdown # Review patches for session (N patches across M files) ## Needs manual review (omit this section when needs_manual is empty) - annotation `` — ## - [x] **** · category= · annotation: "" ```diff ``` - [x] **** · provisional ID promotion for `` ```diff ``` ## Test impact (omit this section when no patch changes testable behavior) Re-run `impl-quality-test-plan` after applying — these spec changes affect coverage: - `` — : (AC: ) ``` All auto-generated patches start as `- [x]` (checked). Users toggle `[x]` → `[ ]` to skip a patch, or hand-edit the diff in-place. The `## Test impact` bullets are advisory notes, **not** patches — they carry no checkbox and `apply.py` ignores them. --- ## Output After writing both files, print: ``` mockup-feedback-patch complete: N patches authored across M files K needs_manual (see review.md preamble) T test-impact scenarios suggested (see review.md ## Test impact) review at: _concept/_feedback/patches/.review.md Next: edit review.md as needed, then run mockup-feedback-apply (if T > 0, re-run impl-quality-test-plan after apply) ``` --- ## Inputs | Name | Type | Default | |---|---|---| | `session_id` | string | (all unpatched sessions) | | `concept_root` | path | `_concept/` | ## Outputs | Path | Description | |---|---| | `_concept/_feedback/patches/.json` | Patch list (machine-readable) | | `_concept/_feedback/patches/.review.md` | Checklist for human review | ## References - `contracts/elements_block.md` — `elements:` frontmatter schema, provisional ID rules (4-space indent) - `mockup-feedback/schemas/patches.schema.json` — output shape - `docs/devlog/2026-05-09-3B-mockup-feedback-triage-patch-apply-design.md` D2, D4, D5