@event4u/agent-config 1.14.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/.agent-src/commands/agent-handoff.md +1 -1
  2. package/.agent-src/commands/bug-fix.md +2 -2
  3. package/.agent-src/commands/chat-history-checkpoint.md +2 -2
  4. package/.agent-src/commands/chat-history-clear.md +1 -1
  5. package/.agent-src/commands/chat-history-resume.md +2 -2
  6. package/.agent-src/commands/chat-history.md +2 -2
  7. package/.agent-src/commands/check-current-md.md +43 -32
  8. package/.agent-src/commands/commit-in-chunks.md +43 -23
  9. package/.agent-src/commands/compress.md +34 -2
  10. package/.agent-src/commands/feature-roadmap.md +2 -2
  11. package/.agent-src/commands/fix-portability.md +2 -2
  12. package/.agent-src/commands/onboard.md +14 -5
  13. package/.agent-src/commands/optimize-augmentignore.md +9 -0
  14. package/.agent-src/commands/refine-ticket.md +9 -7
  15. package/.agent-src/commands/review-changes.md +35 -8
  16. package/.agent-src/commands/roadmap-create.md +13 -2
  17. package/.agent-src/commands/roadmap-execute.md +9 -7
  18. package/.agent-src/commands/set-cost-profile.md +8 -0
  19. package/.agent-src/commands/sync-agent-settings.md +9 -0
  20. package/.agent-src/commands/tests-execute.md +2 -3
  21. package/.agent-src/rules/artifact-engagement-recording.md +1 -1
  22. package/.agent-src/rules/augment-portability.md +56 -37
  23. package/.agent-src/rules/chat-history-cadence.md +109 -0
  24. package/.agent-src/rules/chat-history-ownership.md +123 -0
  25. package/.agent-src/rules/chat-history-visibility.md +96 -0
  26. package/.agent-src/rules/cli-output-handling.md +1 -1
  27. package/.agent-src/rules/command-suggestion.md +3 -2
  28. package/.agent-src/rules/commit-policy.md +44 -34
  29. package/.agent-src/rules/direct-answers.md +1 -1
  30. package/.agent-src/rules/language-and-tone.md +19 -15
  31. package/.agent-src/rules/non-destructive-by-default.md +18 -18
  32. package/.agent-src/rules/roadmap-progress-sync.md +133 -74
  33. package/.agent-src/rules/role-mode-adherence.md +1 -1
  34. package/.agent-src/rules/size-enforcement.md +2 -1
  35. package/.agent-src/rules/user-interaction.md +28 -4
  36. package/.agent-src/scripts/update_roadmap_progress.py +56 -4
  37. package/.agent-src/skills/blade-ui/SKILL.md +29 -10
  38. package/.agent-src/skills/command-writing/SKILL.md +15 -4
  39. package/.agent-src/skills/existing-ui-audit/SKILL.md +24 -9
  40. package/.agent-src/skills/fe-design/SKILL.md +20 -15
  41. package/.agent-src/skills/file-editor/SKILL.md +9 -0
  42. package/.agent-src/skills/livewire/SKILL.md +26 -7
  43. package/.agent-src/skills/refine-ticket/SKILL.md +30 -24
  44. package/.agent-src/skills/roadmap-management/SKILL.md +22 -16
  45. package/.agent-src/skills/skill-writing/SKILL.md +3 -3
  46. package/.agent-src/skills/upstream-contribute/SKILL.md +2 -2
  47. package/.agent-src/templates/agent-settings.md +1 -1
  48. package/.agent-src/templates/roadmaps.md +9 -8
  49. package/.agent-src/templates/scripts/memory_lookup.py +1 -1
  50. package/.agent-src/templates/scripts/work_engine/__init__.py +2 -2
  51. package/.agent-src/templates/scripts/work_engine/cli.py +64 -461
  52. package/.agent-src/templates/scripts/work_engine/cli_args.py +116 -0
  53. package/.agent-src/templates/scripts/work_engine/delivery_state.py +3 -3
  54. package/.agent-src/templates/scripts/work_engine/directives/backend/__init__.py +1 -1
  55. package/.agent-src/templates/scripts/work_engine/directives/backend/implement.py +1 -1
  56. package/.agent-src/templates/scripts/work_engine/directives/backend/memory.py +1 -1
  57. package/.agent-src/templates/scripts/work_engine/directives/backend/plan.py +1 -1
  58. package/.agent-src/templates/scripts/work_engine/directives/backend/report.py +1 -1
  59. package/.agent-src/templates/scripts/work_engine/dispatcher.py +1 -1
  60. package/.agent-src/templates/scripts/work_engine/emitters.py +43 -0
  61. package/.agent-src/templates/scripts/work_engine/errors.py +19 -0
  62. package/.agent-src/templates/scripts/work_engine/hook_bootstrap.py +76 -0
  63. package/.agent-src/templates/scripts/work_engine/input_builders.py +163 -0
  64. package/.agent-src/templates/scripts/work_engine/migration/v0_to_v1.py +34 -2
  65. package/.agent-src/templates/scripts/work_engine/persona_policy.py +1 -1
  66. package/.agent-src/templates/scripts/work_engine/resolvers/prompt.py +1 -1
  67. package/.agent-src/templates/scripts/work_engine/state_io.py +202 -0
  68. package/.claude-plugin/marketplace.json +1 -1
  69. package/AGENTS.md +6 -4
  70. package/CHANGELOG.md +83 -8
  71. package/README.md +24 -23
  72. package/docs/MIGRATION.md +122 -0
  73. package/docs/architecture.md +83 -34
  74. package/docs/contracts/STABILITY.md +95 -0
  75. package/docs/contracts/adr-chat-history-split.md +132 -0
  76. package/docs/contracts/adr-command-suggestion.md +146 -0
  77. package/docs/contracts/adr-implement-ticket-runtime.md +122 -0
  78. package/docs/contracts/adr-product-ui-track.md +384 -0
  79. package/docs/contracts/adr-prompt-driven-execution.md +187 -0
  80. package/docs/contracts/agent-memory-contract.md +149 -0
  81. package/docs/contracts/artifact-engagement-flow.md +262 -0
  82. package/docs/contracts/command-clusters.md +126 -0
  83. package/docs/contracts/command-suggestion-flow.md +148 -0
  84. package/docs/contracts/implement-ticket-flow.md +628 -0
  85. package/docs/contracts/linear-ai-rules-inclusion.md +143 -0
  86. package/docs/contracts/linear-ai-three-layers.md +131 -0
  87. package/docs/contracts/rule-interactions.md +107 -0
  88. package/docs/contracts/rule-interactions.yml +142 -0
  89. package/docs/contracts/ui-stack-extension.md +236 -0
  90. package/docs/contracts/ui-track-flow.md +338 -0
  91. package/docs/getting-started.md +2 -2
  92. package/docs/installation.md +42 -6
  93. package/docs/migrations/commands-1.15.0.md +112 -0
  94. package/docs/ui-track-mental-model.md +121 -0
  95. package/package.json +1 -1
  96. package/scripts/build_linear_digest.py +4 -4
  97. package/scripts/check_portability.py +2 -0
  98. package/scripts/check_public_links.py +185 -0
  99. package/scripts/check_references.py +1 -0
  100. package/scripts/lint_no_new_atomic_commands.py +179 -0
  101. package/scripts/lint_rule_interactions.py +149 -0
  102. package/scripts/memory_lookup.py +1 -1
  103. package/scripts/release.py +297 -64
  104. package/scripts/skill_linter.py +14 -0
  105. package/scripts/update_counts.py +10 -0
  106. package/.agent-src/rules/chat-history.md +0 -200
@@ -0,0 +1,236 @@
1
+ ---
2
+ stability: beta
3
+ ---
4
+
5
+ # UI Stack Extension — adding a new frontend stack to the UI track
6
+
7
+ > **Audience:** maintainers adding a new stack (Svelte, SolidJS, Astro,
8
+ > Qwik, …) to the UI directive set. Consumers of the package never run
9
+ > this; they get the stacks shipped here.
10
+ > **Source of truth:** [`ui-track-flow.md`](ui-track-flow.md) for the
11
+ > contract; [`adr-product-ui-track.md`](adr-product-ui-track.md) for
12
+ > the rationale.
13
+ > **Status:** recipe only — R3 ships four stacks
14
+ > (`blade-livewire-flux`, `react-shadcn`, `vue`, `plain`); no
15
+ > additional stacks are scheduled. Add one only when a real consumer
16
+ > project asks for it.
17
+
18
+ ## What "adding a stack" actually means
19
+
20
+ Three artefacts plus a Golden fixture. The engine's directive set is
21
+ fixed; only the dispatch tables and the implementation skill bundles
22
+ change.
23
+
24
+ | Artefact | File | Change |
25
+ |---|---|---|
26
+ | Stack label | [`scripts/work_engine/stack/detect.py`](../../.agent-src.uncompressed/templates/scripts/work_engine/stack/detect.py) | New entry in `KNOWN_STACKS` + a heuristic in `detect_stack` |
27
+ | Apply skill | `.agent-src.uncompressed/skills/ui-apply-<stack>/SKILL.md` | New skill bundle |
28
+ | Review skill | `.agent-src.uncompressed/skills/ui-design-review-<stack>/SKILL.md` | New skill bundle |
29
+ | Polish skill | `.agent-src.uncompressed/skills/ui-polish-<stack>/SKILL.md` | New skill bundle |
30
+ | Dispatch tables | `directives/ui/{apply,review,polish}.py` | New row in each `STACK_DIRECTIVES` map |
31
+ | Golden fixture | `tests/golden/sandbox/recipes/gt_u<NN>_<stack>_*.py` | One happy-path baseline at minimum |
32
+
33
+ Skill names are not free — they are read by the dispatcher as
34
+ `ui-apply-<stack>`, `ui-design-review-<stack>`, `ui-polish-<stack>`.
35
+ A typo is silently handled by the `DEFAULT_DIRECTIVE` fallback
36
+ (`ui-apply-plain` / `ui-design-review-plain` / `ui-polish-plain`),
37
+ which is recoverable but probably not what the maintainer intended.
38
+
39
+ ## Step 1 — pick the label
40
+
41
+ Convention: lowercase, hyphenated, framework-only (no version pin).
42
+
43
+ | Good | Bad | Why |
44
+ |---|---|---|
45
+ | `svelte` | `svelte5` | Major-version drift handled by the audit's version-anchor warning, not by splitting the stack. |
46
+ | `solid` | `solid-js` | Match the package name developers say out loud. |
47
+ | `astro` | `astro-content` | Sub-modes (Astro components vs MDX) live inside the apply skill, not in the label. |
48
+
49
+ Add the label to `KNOWN_STACKS` (the frozenset is exported and used by
50
+ state validation; missing it makes detection silent-fail back to
51
+ `plain`).
52
+
53
+ ## Step 2 — heuristic in `detect_stack`
54
+
55
+ The detector reads `composer.json` and `package.json` once and applies
56
+ heuristics in **priority order** — first match wins. The order matters:
57
+ a Laravel + React project must hit `blade-livewire-flux` only when
58
+ Livewire and Flux are present, otherwise `react-shadcn`.
59
+
60
+ Insert the new heuristic **before** the `plain` fallback and **after**
61
+ any stack that could legitimately co-exist with yours. For Svelte:
62
+
63
+ ```python
64
+ def _has_svelte(package: dict[str, object]) -> bool:
65
+ deps = _all_dependencies(
66
+ package,
67
+ "dependencies",
68
+ "devDependencies",
69
+ "peerDependencies",
70
+ "optionalDependencies",
71
+ )
72
+ return "svelte" in deps
73
+ ```
74
+
75
+ ```python
76
+ # inside detect_stack(), before the `plain` fallback
77
+ if _has_svelte(package):
78
+ return StackResult(frontend="svelte", mtime=mtime)
79
+ ```
80
+
81
+ **Failure mode to watch.** A heuristic that overlaps with an existing
82
+ stack (Astro lists `react` as a peer dep when used with React adapters)
83
+ must be ordered carefully. Test against real fixtures, not hand-edited
84
+ JSON.
85
+
86
+ ## Step 3 — three skills, one shape
87
+
88
+ Each skill is a SKILL.md bundle with frontmatter and prose. The
89
+ contract for each:
90
+
91
+ ### `ui-apply-<stack>`
92
+
93
+ Reads `state.ui_design.brief` and `state.ui_audit.components_found`.
94
+ Writes a populated `state.ticket["ui_apply"]` envelope:
95
+
96
+ ```yaml
97
+ ui_apply:
98
+ files: ["resources/components/UserCard.svelte"]
99
+ rendered: # full text per file, microcopy-locked
100
+ "resources/components/UserCard.svelte": |
101
+ <script>...</script>
102
+ ...
103
+ components_added: ["UserCard"]
104
+ components_reused: ["Button", "Card"] # from audit
105
+ microcopy_lock: true # affirms strings come from brief verbatim
106
+ ```
107
+
108
+ **Hard rule:** strings in `rendered` must not contain
109
+ `PLACEHOLDER_PATTERNS` (`<placeholder>`, `lorem`, `todo:`, `tbd`,
110
+ `xxx`). The dispatcher rejects on producer side; the skill must reject
111
+ on consumer side too.
112
+
113
+ ### `ui-design-review-<stack>`
114
+
115
+ Reads `state.ui_apply` + `state.ui_design.brief`. Writes
116
+ `state.ui_review` with `findings: list` and `review_clean: bool`.
117
+ Findings are tagged `kind` ∈ `{token_violation, microcopy_drift,
118
+ a11y_gap, layout_break, prop_misuse, …}` — extend the kind set
119
+ sparingly. Token violations carry `category` and `value` so polish
120
+ can route them through token extraction.
121
+
122
+ ### `ui-polish-<stack>`
123
+
124
+ Reads `state.ui_review.findings` + `state.ui_audit.design_tokens`.
125
+ Writes a fix envelope and increments `state.ui_polish.rounds`. Hard
126
+ ceiling at `POLISH_CEILING = 2` is enforced by the dispatcher;
127
+ the skill does **not** check the ceiling itself but must respect
128
+ `token_repeat_threshold = 2` for unmatched-token extraction.
129
+
130
+ ## Step 4 — wire dispatch tables
131
+
132
+ Three identical edits in
133
+ [`directives/ui/apply.py`](../../.agent-src.uncompressed/templates/scripts/work_engine/directives/ui/apply.py),
134
+ [`directives/ui/review.py`](../../.agent-src.uncompressed/templates/scripts/work_engine/directives/ui/review.py),
135
+ and [`directives/ui/polish.py`](../../.agent-src.uncompressed/templates/scripts/work_engine/directives/ui/polish.py):
136
+
137
+ ```python
138
+ STACK_DIRECTIVES: dict[str, str] = {
139
+ "blade-livewire-flux": "ui-apply-blade-livewire-flux",
140
+ "react-shadcn": "ui-apply-react-shadcn",
141
+ "vue": "ui-apply-vue",
142
+ "plain": "ui-apply-plain",
143
+ "svelte": "ui-apply-svelte", # ← new row
144
+ }
145
+ ```
146
+
147
+ Same shape in `review.py` (`ui-design-review-svelte`) and `polish.py`
148
+ (`ui-polish-svelte`). The dispatcher does not validate that the skill
149
+ actually exists — it emits the `@agent-directive` and trusts the agent
150
+ loader. A typo or missing skill manifests as a halt loop the maintainer
151
+ notices on first replay.
152
+
153
+ ## Step 5 — version anchor in skill frontmatter
154
+
155
+ Every stack-specific skill declares the upstream library version it
156
+ was tested against, in frontmatter:
157
+
158
+ ```yaml
159
+ tested_against:
160
+ svelte: "5.x"
161
+ svelte_kit: "2.x" # if applicable
162
+ ```
163
+
164
+ The audit step reads installed versions from `package.json` and
165
+ compares against the anchor. A mismatch warns but does not block;
166
+ the user picks whether to proceed or pin. Forgetting the anchor
167
+ fails CI (`task lint-skills` enforces presence on `ui-apply-*`,
168
+ `ui-design-review-*`, `ui-polish-*`).
169
+
170
+ ## Step 6 — Golden fixture
171
+
172
+ Add at least one happy-path Golden that exercises the full UI flow
173
+ on the new stack. Recipe lives at
174
+ `tests/golden/sandbox/recipes/gt_u<NN>_<stack>_happy.py` and follows
175
+ the pattern of `gt_u11_high_confidence.py`:
176
+
177
+ 1. Seed state with a clear `ui-build` prompt and an audit that finds
178
+ exactly one strong match (so `audit_path = "high_confidence"`).
179
+ 2. Pin the halt budget — high-confidence happy path is **1 halt**
180
+ (design-brief sign-off only).
181
+ 3. Capture under `tests/golden/baseline/GT-U<NN>/` via `task golden-capture`.
182
+ 4. The replay harness (`tests/golden/test_replay.py`) auto-discovers
183
+ the new baseline; no Taskfile change needed.
184
+
185
+ For a complete pair, also add an `ambiguous` fixture — `2 halts max`,
186
+ matching `gt_u12_ambiguous.py`'s shape. Skip the greenfield branch
187
+ unless the stack has a meaningful difference there.
188
+
189
+ See [`tests/golden/CAPTURING.md`](../../tests/golden/CAPTURING.md)
190
+ for capture mechanics.
191
+
192
+ ## Step 7 — verify end-to-end
193
+
194
+ ```bash
195
+ task sync # propagate detect.py + skill changes
196
+ task generate-tools # refresh .claude/, .cursor/, etc.
197
+ task lint-skills # checks frontmatter + version anchor
198
+ task golden-replay # runs all R1+R2+R3 baselines
199
+ task ci # full pipeline
200
+ ```
201
+
202
+ If `golden-replay` regresses on a non-`<stack>` baseline, your
203
+ detector heuristic is over-matching — re-order the priority chain.
204
+
205
+ ## What you do **not** add
206
+
207
+ - **A new directive set.** UI / UI-trivial / mixed are exhaustive for
208
+ R3. A stack-specific directive set means you've reached for a hammer
209
+ the engine doesn't have.
210
+ - **A new entrypoint command.** `/work` and `/implement-ticket` route
211
+ through `directive_set` and `state.stack.frontend`; a `/build-svelte`
212
+ command would create a UX divergence the engine's intent classifier
213
+ is supposed to prevent.
214
+ - **`fe-design` content.** That skill is the framework-agnostic
215
+ reference; new stack-specific heuristics live in the apply skill,
216
+ not in `fe-design`.
217
+ - **Visual review.** Roadmap 4's headless-browser pipeline is the
218
+ destination for screenshot capture and a11y tooling. Stack
219
+ extensions don't need to wait on it.
220
+
221
+ ## When NOT to add a stack
222
+
223
+ Defer the work and stay on `plain` if any apply:
224
+
225
+ - Only one consumer project asks; the cost of maintaining the apply
226
+ skill exceeds the value.
227
+ - The framework's idiom is close enough to an existing stack that
228
+ the existing apply skill produces acceptable output (Preact ≈
229
+ `react-shadcn` for most components).
230
+ - The framework is in beta or pre-1.0 — the version anchor will drift
231
+ faster than you can re-capture goldens.
232
+
233
+ The audit gate is the safety net: even on `plain`, the audit finds
234
+ existing components and the design step uses them. The cost of
235
+ **not** adding a stack is generally lower than the cost of adding
236
+ one prematurely.
@@ -0,0 +1,338 @@
1
+ ---
2
+ stability: beta
3
+ ---
4
+
5
+ # UI Track — Flow Contract
6
+
7
+ > Technical contracts for the UI directive sets shipped under
8
+ > [`road-to-product-ui-track.md`](../../agents/roadmaps/road-to-product-ui-track.md).
9
+ > Sibling of [`implement-ticket-flow.md`](implement-ticket-flow.md) — that
10
+ > doc covers `backend`; this one covers `ui`, `ui-trivial`, and the
11
+ > `mixed` set that stitches both.
12
+ >
13
+ > - **Created:** 2026-05-01
14
+ > - **Status:** Phase 1–6 shipped — audit / design / apply / review /
15
+ > polish handlers live under
16
+ > [`.agent-src.uncompressed/templates/scripts/work_engine/directives/ui/`](../../.agent-src.uncompressed/templates/scripts/work_engine/directives/ui/).
17
+ > Mixed (Phase 4) under `directives/mixed/`. `ui-trivial` (Phase 2 Step 6)
18
+ > under `directives/ui_trivial/`. R4 (Visual Review Loop) added the
19
+ > a11y gate, the preview envelope, and a polish-termination rewrite
20
+ > that splits subjective ceilings from objective a11y blocks — see
21
+ > [`road-to-visual-review-loop.md`](../../agents/roadmaps/road-to-visual-review-loop.md).
22
+ > Golden Transcripts GT-U1..U4, U7, U8, U9..U12 plus GT-U5 (mixed
23
+ > flow), GT-U6A/B (stack dispatch), and R4's GT-U13..U15 (a11y polish,
24
+ > a11y ceiling, preview render failure) pin happy-path, ambiguity,
25
+ > mixed orchestration, stack dispatch, trivial happy path, and the
26
+ > visual-review gates.
27
+ > - **Runtime:** Python 3.10+. Same `DeliveryState` envelope, same
28
+ > eight-slot dispatcher as the backend track — only the slot handlers
29
+ > differ.
30
+
31
+ ## What this doc is
32
+
33
+ The **shape** of the four UI-related directive sets: which slot runs
34
+ which handler, what each handler reads / writes on `DeliveryState`, the
35
+ hard thresholds (similarity, polish ceiling, trivial limits), and the
36
+ sentinels that release each gate.
37
+
38
+ ## What this doc is *not*
39
+
40
+ - A skill spec — `existing-ui-audit`, `ui-design-brief`, the stack
41
+ apply / review / polish skills are documented in their own
42
+ `SKILL.md` files.
43
+ - A migration guide for the schema — see
44
+ [`implement-ticket-flow.md`](implement-ticket-flow.md#state-schema-v1).
45
+ - A roadmap — phased delivery lives in
46
+ [`road-to-product-ui-track.md`](../../agents/roadmaps/road-to-product-ui-track.md).
47
+
48
+ ## The four directive sets
49
+
50
+ | Set | When picked | Slot 1–8 |
51
+ |---|---|---|
52
+ | `backend` | Default — no UI keywords, no UI envelope | `refine → memory → analyze → plan → implement → test → verify → report` (see sibling doc) |
53
+ | `ui` | UI keywords, `improve` envelope, or refine routing to UI | `audit → ⊘ → design → ⊘ → apply → review → polish → report` |
54
+ | `ui-trivial` | Phase-1 classifier hits "single-line tweak" pattern | `refine → ⊘ → ⊘ → ⊘ → apply → test → ⊘ → report` |
55
+ | `mixed` | Backend + UI in one input | `refine → memory → analyze → contract → ui → stitch → verify → report` |
56
+
57
+ `⊘` = `_passthrough.run` (or `_skipped.run` in `ui-trivial`). The slot
58
+ exists so the dispatcher's completeness check is satisfied; no logic
59
+ runs and no state is touched.
60
+
61
+ Source of truth for slot wiring:
62
+ [`directives/ui/__init__.py`](../../.agent-src.uncompressed/templates/scripts/work_engine/directives/ui/__init__.py),
63
+ [`directives/mixed/__init__.py`](../../.agent-src.uncompressed/templates/scripts/work_engine/directives/mixed/__init__.py),
64
+ [`directives/ui_trivial/__init__.py`](../../.agent-src.uncompressed/templates/scripts/work_engine/directives/ui_trivial/__init__.py).
65
+
66
+ ## The `ui` set — slot-by-slot
67
+
68
+ ### `refine` → audit
69
+
70
+ Mandatory pre-step. Routes on `state.ui_audit` shape:
71
+
72
+ | State | Outcome | Handler |
73
+ |---|---|---|
74
+ | `None` / empty / non-dict | `BLOCKED` + `@agent-directive: existing-ui-audit` | First-pass delegation |
75
+ | `greenfield=True`, no `greenfield_decision` | `BLOCKED` numbered options | User picks `scaffold` / `bare` / `external_reference` |
76
+ | `shadcn_inventory.version` major ≠ `TESTED_AGAINST_SHADCN_MAJOR` (`2`) and no `version_mismatch_decision` | `BLOCKED` soft halt | "Cautious composition / abort" |
77
+ | Confidence `high` + ≥1 match with similarity ≥ `STRONG_SIMILARITY` (`0.7`) and no runner-up within `TIE_GAP` (`0.05`) | `SUCCESS`, `audit_path = "high_confidence"` | Design folds findings into brief |
78
+ | Anything else populated | `BLOCKED` numbered options | User picks candidate to extend (or "build new"); records `audit_path = "ambiguous"` + `candidate_pick` |
79
+
80
+ Constants live in
81
+ [`directives/ui/audit.py`](../../.agent-src.uncompressed/templates/scripts/work_engine/directives/ui/audit.py):
82
+ `STRONG_SIMILARITY = 0.7`, `TIE_GAP = 0.05`,
83
+ `TESTED_AGAINST_SHADCN_MAJOR = 2`. Idempotent re-entry: once
84
+ `audit_path` is set the step round-trips through `SUCCESS` without
85
+ re-emitting.
86
+
87
+ ### `analyze` → design
88
+
89
+ Produces the **locked design brief**. `apply` consumes microcopy
90
+ verbatim — that's the lock.
91
+
92
+ Required brief keys (`REQUIRED_BRIEF_KEYS`): `layout`, `components`,
93
+ `states`, `microcopy`, `a11y`. Required state coverage
94
+ (`REQUIRED_STATE_KEYS`): `empty`, `loading`, `error`, `success`,
95
+ `disabled`.
96
+
97
+ Microcopy is rejected when any string matches `PLACEHOLDER_PATTERNS`:
98
+ `<placeholder>`, `lorem`, `todo:`, `tbd`, `xxx` (case-insensitive
99
+ substring). The same tuple is re-imported by `apply` so the rejection
100
+ fires at the producer first, at the consumer as defense-in-depth.
101
+
102
+ Sentinel: `state.ui_design.design_confirmed`. Without it the brief
103
+ halt fires every pass; with it the step round-trips through `SUCCESS`.
104
+
105
+ ### `implement` → apply
106
+
107
+ Stack-dispatched. Routes on `state.stack.frontend`:
108
+
109
+ | `state.stack.frontend` | Directive | Skill bundle |
110
+ |---|---|---|
111
+ | `blade-livewire-flux` | `ui-apply-blade-livewire-flux` | `flux` + `livewire` + `blade-ui` |
112
+ | `react-shadcn` | `ui-apply-react-shadcn` | `react-shadcn-ui` |
113
+ | `vue` | `ui-apply-vue` | `ui-apply-vue` |
114
+ | `plain` (or unknown — `DEFAULT_DIRECTIVE`) | `ui-apply-plain` | `blade-ui` + Tailwind base |
115
+
116
+ Apply does **not** re-validate the brief — it validates *output* against
117
+ `PLACEHOLDER_PATTERNS`. A hallucinated `<placeholder>` string in the
118
+ rendered envelope triggers
119
+ `apply_placeholders_in_output` and forces re-render with the locked
120
+ microcopy. Once `state.ticket["ui_apply"]` is well-formed, apply records
121
+ changes and returns `SUCCESS`.
122
+
123
+ ### `test` → review
124
+
125
+ Stack-dispatched design-review pass. Same dispatch table shape as
126
+ apply, prefix `ui-design-review-`. Writes
127
+ `state.ui_review.findings` (list) + `state.ui_review.review_clean`
128
+ (bool). The step does **not** enforce
129
+ `review_clean == (len(findings) == 0)` — that would block the
130
+ legitimate "ship as-is with open findings" replay path. Honesty of the
131
+ flag is the producer's contract; review only validates shape.
132
+
133
+ **R4 — a11y gate** (after the basic clean/findings gates pass).
134
+ `_apply_a11y_gate` reads `state.ui_review.a11y.violations`, filters
135
+ out entries already in `state.ui_audit.a11y_baseline` (pre-existing
136
+ violations stay informational, never block), drops anything below
137
+ `severity_floor` (default `moderate`; unknown severities default to
138
+ `moderate` so a malformed envelope cannot weaken the gate), and
139
+ filters entries listed in `state.ui_review.a11y.accepted_violations`
140
+ (idempotent re-entry after the polish-ceiling Accept choice).
141
+ Surviving violations are synthesised as
142
+ `{kind: "a11y_violation", rule, selector, severity}` findings (deduped
143
+ by `(rule, selector)`) and `review_clean` is forced to `False`
144
+ engine-side. Opt-in: when `state.ui_audit.a11y_baseline` exists but
145
+ `state.ui_review.a11y` is missing, the step halts with
146
+ `review_a11y_pending` so the skill writes the envelope on the next
147
+ pass; pre-R4 envelopes without a baseline bypass the gate entirely.
148
+
149
+ **R4 — preview envelope** (the engine never renders).
150
+ `_apply_preview_gate` reads `state.ui_review.preview`. Shape:
151
+ `render_ok: bool`, optional `screenshot_path`, `dom_dump_path`,
152
+ `error`, `skipped`. `render_ok: False` halts with
153
+ `preview_render_failed` so the user picks retry / skip / abort; Skip
154
+ flips `state.ui_review.preview.skipped = true` and the gate becomes a
155
+ no-op on re-entry. `render_ok: True` with `screenshot_path` set
156
+ threads the path into the delivery report's `artifacts` list. The
157
+ gate is independent of the a11y gate; both can fire on the same pass.
158
+
159
+ ### `verify` → polish
160
+
161
+ Bounded fix loop. Base ceiling: `POLISH_CEILING = 2` rounds. R4
162
+ splits termination into **subjective** and **objective** branches:
163
+ the subjective `polish_ceiling_reached` halt only fires when the
164
+ remaining findings are non-a11y; objective a11y violations take the
165
+ explicit `polish_a11y_blocking` branch with its own option set.
166
+
167
+ | `review_clean` | `rounds` | Remaining findings | Behaviour |
168
+ |---|---|---|---|
169
+ | `True` | any | — | `SUCCESS` — advance to report |
170
+ | `False` | `< effective_ceiling` | any | `BLOCKED` + `@agent-directive: ui-polish-<stack>`; skill applies fixes, re-runs review, increments `rounds` |
171
+ | `False` | `== effective_ceiling` | contains `a11y_violation` | `BLOCKED` numbered options: extend (one extra round, sets `extension_used = True`; option disappears once spent) / accept (appends rule ids to `state.ui_review.a11y.accepted_violations`, then continues) / abort |
172
+ | `False` | `== effective_ceiling` | non-a11y only | `BLOCKED` numbered options: ship as-is / abort / hand off |
173
+
174
+ `effective_ceiling = POLISH_CEILING + 1` once
175
+ `state.ui_polish.extension_used` is set; the schema validator widens
176
+ the upper bound from `[0, 2]` to `[0, 3]` only when the flag is
177
+ `True`, so the ceiling holds across in-memory state, on-disk state,
178
+ and the dispatcher. `rounds > 3` is rejected unconditionally, even
179
+ with the extension flag.
180
+
181
+ **Idempotent re-entry on Accept.** A `state.ui_review.a11y.accepted_violations`
182
+ list with rule ids matching the remaining a11y findings round-trips
183
+ through `SUCCESS` because the review gate's `_apply_a11y_gate`
184
+ filters accepted entries before synthesising `a11y_violation`
185
+ findings. The Accept branch and the Ship-as-is branch are therefore
186
+ asymmetric: Ship-as-is flips `review_clean` directly; Accept records
187
+ explicit rule ids so replay reproduces the same gate decision.
188
+
189
+ **Token-violation extraction.** Findings with
190
+ `kind == "token_violation"` carry `category` and `value`. Polish
191
+ classifies them against `state.ui_audit.design_tokens`:
192
+
193
+ - Matched value → fix uses the named token; counted as a regular round.
194
+ - Unmatched value repeated `> TOKEN_REPEAT_THRESHOLD` (`2`) times →
195
+ emits `polish_token_extraction_pending`: extract the value to a new
196
+ token before the next round runs. One-off unmatched values stay
197
+ inline.
198
+
199
+ Stack-directive table mirrors apply / review with prefix
200
+ `ui-polish-`. `DEFAULT_DIRECTIVE = "ui-polish-plain"`.
201
+
202
+ ### `report` → backend renderer
203
+
204
+ Re-export of
205
+ [`directives.backend.report.run`](../../.agent-src.uncompressed/templates/scripts/work_engine/directives/backend/report.py).
206
+ The renderer is pure and state-driven; the same Markdown contract
207
+ serves both tracks.
208
+
209
+ ## Halt budget — happy path
210
+
211
+ `ui` set, fresh state, audit + design pass cleanly:
212
+
213
+ 1. **Audit pick** — first-pass `existing-ui-audit` directive halt.
214
+ 2. **Design sign-off** — `design_confirmed` numbered-options halt.
215
+
216
+ Two user halts. Apply / review / polish all run silently when their
217
+ producers write clean envelopes on the first attempt. GT-U1..U4 pin
218
+ this budget.
219
+
220
+ Additional halts surface only on real ambiguity:
221
+ greenfield-undecided (+1), shadcn-version-mismatch (+1), audit-ambiguous
222
+ (+1), placeholder rejection (+N until microcopy is fixed),
223
+ polish round (+1 per dirty review, capped at the effective ceiling),
224
+ polish ceiling — subjective (+1 when both rounds fail and remaining
225
+ findings are non-a11y) **or** a11y-blocking (+1 when remaining
226
+ findings include `a11y_violation` entries; the Extend option grants
227
+ one extra round, then disappears),
228
+ preview render failure (+1 when `state.ui_review.preview.render_ok`
229
+ is `False`; user picks retry / skip / abort),
230
+ review a11y pending (+1 when an `a11y_baseline` exists but the review
231
+ skill has not yet written `state.ui_review.a11y`).
232
+
233
+ ## The `ui-trivial` set — short-circuit path
234
+
235
+ For provably bounded edits (single class swap, copy tweak, one-prop
236
+ adjustment). Phase-1 intent classifier writes
237
+ `directive_set = "ui-trivial"`.
238
+
239
+ Hard preconditions in
240
+ [`directives/ui_trivial/apply.py`](../../.agent-src.uncompressed/templates/scripts/work_engine/directives/ui_trivial/apply.py):
241
+
242
+ - `MAX_FILES = 1` — exactly one file touched.
243
+ - `MAX_LINES_CHANGED = 5` — diff stays under five changed lines.
244
+
245
+ Violation flips `state.directive_set` to `ui` (the full audit gate)
246
+ and the dispatcher restarts. The trivial path **never** silently
247
+ swallows scope creep.
248
+
249
+ Skipped slots (`memory`, `analyze`, `plan`, `verify`) share
250
+ `_skipped.run` — they record `success` without work so the dispatcher
251
+ completeness check is satisfied. `report` renders a one-line summary
252
+ instead of the full delivery report.
253
+
254
+ ## The `mixed` set — contract + UI + stitch
255
+
256
+ Used when a single input touches both layers. Slot mapping:
257
+
258
+ | Slot | Handler | Purpose |
259
+ |---|---|---|
260
+ | `refine`, `memory`, `analyze`, `verify`, `report` | reused from `backend` | Same handlers, by reference |
261
+ | `plan` | `mixed.contract` | Lock `data_model` + `api_surface` |
262
+ | `implement` | `mixed.ui` | Delegate to UI sub-flow |
263
+ | `test` | `mixed.stitch` | End-to-end smoke scenarios |
264
+
265
+ **Sentinels** that release each mixed gate:
266
+
267
+ - `state.contract.contract_confirmed = True` — UI sub-flow refuses to
268
+ start without it (defense-in-depth even if `outcomes["plan"] ==
269
+ "success"`). Required keys: `data_model`, `api_surface`
270
+ (`REQUIRED_CONTRACT_KEYS`).
271
+ - `state.ui_review.review_clean = True` — mixed `ui` step's success
272
+ condition. Polish-ceiling semantics live in the UI track; if the
273
+ user reaches mixed.ui's "ship as-is / hand off / abort" halt, the
274
+ UI track has already given up.
275
+ - `state.stitch.verdict = "success"` — stitch's success condition.
276
+ `blocked` / `partial` halts with three numbered options unless
277
+ `state.stitch.integration_confirmed = True` (explicit user override).
278
+
279
+ `stitch` emits `@agent-directive: integration-test` so an
280
+ agent-side handler runs the end-to-end smokes; `mixed.ui` emits
281
+ `@agent-directive: ui-track` to delegate the visible-surface work
282
+ back into the full UI directive set.
283
+
284
+ ## Idempotency and replay
285
+
286
+ Every UI step is idempotent on its sentinel:
287
+
288
+ | Step | Sentinel | Effect on replay |
289
+ |---|---|---|
290
+ | audit | `audit_path` ∈ `{"high_confidence", "ambiguous", "greenfield"}` | `SUCCESS` without halt |
291
+ | design | `design_confirmed = True` | `SUCCESS` without halt |
292
+ | apply | `state.ticket["ui_apply"]` well-formed, no placeholders | `SUCCESS`, changes recorded once |
293
+ | review | well-formed envelope (`findings` list + `review_clean` bool) | `SUCCESS` |
294
+ | polish | `review_clean = True` (any round count) | `SUCCESS` |
295
+ | contract | `contract_confirmed = True` | `SUCCESS` |
296
+ | stitch | `verdict = "success"` OR `integration_confirmed = True` | `SUCCESS` |
297
+
298
+ The dispatcher walks the same eight slots on every replay; sentinels
299
+ are the only thing keeping a re-run from re-asking a question the
300
+ user already answered. Replay coverage is locked by the
301
+ Golden-Transcript suite under `tests/golden/baseline/GT-U*/`.
302
+
303
+ ## Declared ambiguity surfaces
304
+
305
+ Each step re-exports an `AMBIGUITIES: tuple[dict[str, str], ...]`
306
+ constant. The
307
+ [`test_ambiguity_coverage.py`](../../tests/implement_ticket/test_ambiguity_coverage.py)
308
+ suite asserts every `BLOCKED` path has a matching declaration.
309
+
310
+ | Step | Codes |
311
+ |---|---|
312
+ | `audit` | `audit_missing`, `greenfield_undecided`, `shadcn_version_mismatch`, `audit_ambiguous` |
313
+ | `design` | `design_missing`, `design_placeholders`, `design_unconfirmed` |
314
+ | `apply` | `apply_envelope_missing`, `apply_placeholders_in_output` |
315
+ | `review` | `review_envelope_missing`, `review_findings_missing`, `review_clean_missing`, `review_a11y_pending`, `preview_render_failed` |
316
+ | `polish` | `polish_round_pending`, `polish_ceiling_reached`, `polish_a11y_blocking`, `polish_token_extraction_pending` |
317
+ | `contract` (mixed) | `upstream_analyze_failed`, `contract_missing`, `contract_incomplete`, `contract_unconfirmed` |
318
+ | `mixed.ui` | `contract_sentinel_missing`, `ui_subflow_missing`, `ui_subflow_dirty` |
319
+ | `stitch` | `upstream_ui_failed`, `stitch_missing`, `stitch_malformed`, `stitch_verdict_unsuccessful` |
320
+
321
+ ## See also
322
+
323
+ - [`implement-ticket-flow.md`](implement-ticket-flow.md) — sibling
324
+ contract for the `backend` set; covers `DeliveryState`, schema v1,
325
+ hooks, persona policies, replay protocol.
326
+ - [`road-to-product-ui-track.md`](../../agents/roadmaps/road-to-product-ui-track.md)
327
+ — phased delivery and Golden-Transcript matrix.
328
+ - [`road-to-product-ui-track-followup.md`](../../agents/roadmaps/archive/road-to-product-ui-track-followup.md)
329
+ — pinned GT-U5 (mixed flow), GT-U6A/B (stack dispatch), GT-U7
330
+ (trivial happy path), GT-U8 (trivial reclassification).
331
+ - [`road-to-visual-review-loop.md`](../../agents/roadmaps/road-to-visual-review-loop.md)
332
+ — R4 contract: a11y gate, preview envelope, polish-termination
333
+ rewrite. Pinned by GT-U13 (a11y polish), GT-U14 (a11y ceiling),
334
+ GT-U15 (preview render failure).
335
+ - [`existing-ui-audit` SKILL](../../.agent-src.uncompressed/skills/existing-ui-audit/SKILL.md)
336
+ — producer of `state.ui_audit`.
337
+ - [`ui-audit-before-build` rule](../../.agent-src.uncompressed/rules/ui-audit-before-build.md)
338
+ — the always-on rule that mirrors the audit gate at the agent layer.
@@ -99,7 +99,7 @@ Your agent is now:
99
99
  - **Respecting your codebase** — no conflicting patterns
100
100
  - **Following standards** — consistent code quality
101
101
 
102
- This is enforced automatically by 53 rules. No configuration needed.
102
+ This is enforced automatically by 55 rules. No configuration needed.
103
103
 
104
104
  ---
105
105
 
@@ -165,7 +165,7 @@ Run `/chat-history-resume` to walk through the prompts explicitly, or
165
165
  let the agent ask on the first turn of a new chat. All merge/replace/
166
166
  resume paths read the on-disk entries into context before any write.
167
167
 
168
- See the [`chat-history` rule](../.agent-src/rules/chat-history.md) and
168
+ See the [`chat-history` rule](../.agent-src/rules/chat-history-ownership.md) and
169
169
  [`scripts/chat_history.py`](../scripts/chat_history.py) for the mechanics.
170
170
 
171
171
  ---
@@ -23,6 +23,23 @@ No Task, no Make, no build tools required for installation.
23
23
  | **Project-installed** (recommended) | Teams, shared standards | Repository-wide |
24
24
  | **Plugin-installed** | Individual users, global use | User-wide |
25
25
 
26
+ > **All paths on this page are still supported.** The labels
27
+ > (`advanced` / `experimental` / `staged`) describe how prominent the
28
+ > path is in our recommendation order, not its support status.
29
+ > Composer + npm are the default; everything else stays shipped and
30
+ > tested. Nothing on this page is being removed in 1.15.0 — the
31
+ > reorder simply marks which paths get the most maintenance attention
32
+ > and which we keep as fallbacks. See R9 in
33
+ > [`agents/roadmaps/archive/road-to-post-pr29-optimize.md`](../agents/roadmaps/archive/road-to-post-pr29-optimize.md)
34
+ > for the rationale.
35
+
36
+ | Label | Meaning | Examples |
37
+ |---|---|---|
38
+ | (no label) | Primary path — first-class, fully supported | Composer, npm, Augment / Claude Code / Copilot CLI plugins |
39
+ | `advanced` | Supported fallback — works, expects familiarity with the toolchain | Git submodule, manual clone, VS Code Git URL |
40
+ | `experimental` | Shipped but evolving — interface may shift between minor releases | Claude.ai Web Skills UI |
41
+ | `staged` | Shipped, narrow surface area — kept for users who already use the platform | Linear AI workspace guidance |
42
+
26
43
  ---
27
44
 
28
45
  ## Project-installed mode (recommended for teams)
@@ -210,7 +227,16 @@ These channels are **additional** to project- and plugin-installed
210
227
  modes; use them when the agent loop runs on the platform's servers,
211
228
  not on your machine.
212
229
 
213
- ### Claude.ai Web (Skills UI)
230
+ > Both cloud channels remain shipped and tested. The labels reflect
231
+ > recommendation prominence, not support status — see the label table
232
+ > at the top of this page.
233
+
234
+ ### Claude.ai Web (Skills UI) — `experimental`
235
+
236
+ > `experimental` — shipped, still tested, but the upload surface and
237
+ > bundle format may shift between minor releases as Claude.ai's Skills
238
+ > UI evolves. Pin to a release tag if you depend on a specific bundle
239
+ > shape.
214
240
 
215
241
  Claude.ai Web supports Skills via manual ZIP upload through the Skills
216
242
  UI. The package builds one ZIP per cloud-eligible skill.
@@ -238,7 +264,12 @@ UI. The package builds one ZIP per cloud-eligible skill.
238
264
  3. **Verify** — open a fresh Claude.ai conversation and confirm the
239
265
  skill appears in the Skills picker.
240
266
 
241
- ### Linear AI (Codegen, Charlie, …)
267
+ ### Linear AI (Codegen, Charlie, …) — `staged`
268
+
269
+ > `staged` — shipped, narrow surface area, kept primarily for users
270
+ > already operating inside Linear. Iteration cadence is slower than
271
+ > the project- and plugin-installed paths; major changes land first
272
+ > on Composer + npm and propagate to the Linear digest in a follow-up.
242
273
 
243
274
  Linear AI agents read free-form guidance from Linear's workspace
244
275
  settings; there is no plugin or upload mechanism. The package ships
@@ -264,16 +295,21 @@ the matching Linear field.
264
295
  - Leave `personal.md` empty unless you have personal overrides
265
296
 
266
297
  3. **Per-layer rationale** — see
267
- [`agents/contexts/linear-ai-three-layers.md`](../agents/contexts/linear-ai-three-layers.md)
298
+ [`docs/contracts/linear-ai-three-layers.md`](contracts/linear-ai-three-layers.md)
268
299
  for the split rationale and
269
- [`agents/contexts/linear-ai-rules-inclusion.md`](../agents/contexts/linear-ai-rules-inclusion.md)
300
+ [`docs/contracts/linear-ai-rules-inclusion.md`](contracts/linear-ai-rules-inclusion.md)
270
301
  for which rules go where.
271
302
 
272
303
  ---
273
304
 
274
- ## Alternative install methods
305
+ ## Alternative install methods — `advanced`
275
306
 
276
- These are fallbacks when the recommended paths above don't work.
307
+ > `advanced` supported fallbacks for users comfortable driving the
308
+ > orchestrator directly. They share the same `scripts/install` entry
309
+ > point as Composer and npm; the only difference is how the package
310
+ > source ends up on disk. Pick these when you cannot use Composer or
311
+ > npm (e.g. a polyglot repo without either, or a CI runner that
312
+ > already vendors the package via submodule).
277
313
 
278
314
  ### Git Submodule
279
315