@event4u/agent-config 10.3.0 → 10.4.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 (47) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +78 -0
  3. package/README.md +1 -1
  4. package/dist/agent-src/commands/analyze.md +2 -1
  5. package/dist/agent-src/commands/design-system/capture.md +44 -0
  6. package/dist/agent-src/commands/design-system/generate.md +53 -0
  7. package/dist/agent-src/commands/design-system/import.md +63 -0
  8. package/dist/agent-src/commands/design-system.md +66 -0
  9. package/dist/agent-src/skills/design-system-capture/SKILL.md +9 -0
  10. package/dist/agent-src/skills/design-system-capture/references/design-system-json.md +70 -0
  11. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  12. package/dist/agent-src/templates/scripts/work_engine/directives/ui/design.ts +4 -1
  13. package/dist/cli-delegate/chunk-RLN73PR5.js +157 -0
  14. package/dist/cli-delegate/{chunk-I5EAFRII.js → chunk-ZPSXJTLI.js} +2 -154
  15. package/dist/cli-delegate/cmd_conformance.js +671 -213
  16. package/dist/cli-delegate/cmd_handoff.js +8 -6
  17. package/dist/cli-delegate/cmd_session_recycle.js +5 -3
  18. package/dist/discovery/deprecation-report.md +1 -1
  19. package/dist/discovery/discovery-manifest.json +116 -11
  20. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  21. package/dist/discovery/discovery-manifest.summary.md +3 -3
  22. package/dist/discovery/dormancy-report.md +1 -1
  23. package/dist/discovery/orphan-report.md +1 -1
  24. package/dist/discovery/packs.json +9 -5
  25. package/dist/discovery/trust-report.md +2 -2
  26. package/dist/discovery/workspaces.json +8 -4
  27. package/dist/hooks/dispatch.js +940 -387
  28. package/dist/mcp/registry-manifest.json +2 -2
  29. package/dist/mcp/server.json +2 -2
  30. package/dist/mcp/server.mjs +1102 -592
  31. package/package.json +1 -1
  32. package/src/agent-src/templates/scripts/work_engine/directives/ui/design.ts +4 -1
  33. package/src/config/gate-coverage.yml +23 -2
  34. package/src/config/gate-violation-baselines.json +2 -2
  35. package/src/scripts/_lib/design_system_import.ts +987 -0
  36. package/src/scripts/design_system_import.ts +264 -0
  37. package/src/scripts/hook_manifest.yaml +71 -2
  38. package/src/scripts/hooks/concern_registry.ts +4 -0
  39. package/src/scripts/hooks/dispatch_hook.ts +10 -0
  40. package/src/scripts/hooks/host_semantics.ts +2 -0
  41. package/src/scripts/hooks/spawn_guard_shadow_hook.ts +212 -0
  42. package/src/scripts/hooks/subagent_ledger_hook.ts +723 -0
  43. package/src/scripts/hooks/turn_end_gate_hook.ts +39 -2
  44. package/src/scripts/lint_hook_manifest.ts +2 -0
  45. package/src/scripts/lint_rule_skill_pack_reach.ts +194 -13
  46. package/tests/fixtures/hooks/subagent_start.json +7 -0
  47. package/tests/fixtures/hooks/subagent_stop.json +8 -0
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Bootstrap shim for the event4u agent-config suite. This plugin ships ONLY the dispatcher hooks plus one install-pointer skill — ALL content (skills, rules, commands) is installed via `npx -y @event4u/agent-config init`, which writes the file projection AND registers the same hooks in ~/.claude/settings.json. DEPRECATED as a content channel; kept so the marketplace listing stays discoverable and existing installs keep working hooks.",
9
- "version": "10.3.0",
9
+ "version": "10.4.0",
10
10
  "keywords": [
11
11
  "agent-config",
12
12
  "skills",
package/CHANGELOG.md CHANGED
@@ -348,6 +348,84 @@ Entry-shape contract: [`docs/contracts/CHANGELOG-conventions.md`](docs/contracts
348
348
  > that forces a new era split (`# Era: 10.4.x`, etc.) — see
349
349
  > [`docs/contracts/CHANGELOG-conventions.md § Era splits`](docs/contracts/CHANGELOG-conventions.md).
350
350
 
351
+ ## [10.4.0](https://github.com/event4u-app/agent-config/compare/10.3.0...10.4.0) (2026-08-13)
352
+
353
+ ### Release highlights
354
+
355
+ <!-- Curated head: fill before merge, keep it under 10 lines, and leave `_none_` where it is genuinely the answer. The generated log below is unchanged. -->
356
+ - **Behaviour changes:** _none_
357
+ - **Default changes + migration:** _none_
358
+ - **Security and correctness:** _none_
359
+ - **Honest nulls:** _auto-derived, rewrite before merge:_ commits carrying an honest-null marker in 5a9f530.
360
+ - **Known limitations:** _none_
361
+
362
+ ### Features
363
+
364
+ * **commands:** /design-system cluster — three doors onto machinery that already ships ([e56eaf4](https://github.com/event4u-app/agent-config/commit/e56eaf4a5496bed575e421df997ad60bd2cfac08))
365
+ * **scripts:** three-lane adapter into the design-system.json contract ([d1dd006](https://github.com/event4u-app/agent-config/commit/d1dd00610d4c2c97aa5adf0fa7baa120167b6aa2))
366
+ * **hooks:** an open subagent dispatch is an explicit turn-end allow ([39daf4e](https://github.com/event4u-app/agent-config/commit/39daf4e2c3ba70fa4e43b57fc82bc1bf9eb5b613))
367
+ * **hooks:** ship Phase 3 runaway containment in shadow posture ([b9efa4e](https://github.com/event4u-app/agent-config/commit/b9efa4ec618b3f26c1c07a8eb335866545c4274c))
368
+ * **hooks:** register subagent lifecycle events and bind the ledger ([a6a4023](https://github.com/event4u-app/agent-config/commit/a6a4023529074069f03f8542d0513ee77f3adfde))
369
+ * **hooks:** add the capture-only subagent-ledger concern ([f393ec4](https://github.com/event4u-app/agent-config/commit/f393ec4686422d247bc5862cf13e04459d64ace5))
370
+ * **gates:** adopt the self-test harness in lint_rule_skill_pack_reach ([a758153](https://github.com/event4u-app/agent-config/commit/a7581533b8d5ed8672f985337dc87d21508fa451))
371
+
372
+ ### Bug Fixes
373
+
374
+ * **design-system:** drop maintainer-only invocations from shipped surfaces ([122760a](https://github.com/event4u-app/agent-config/commit/122760aad5f2a6f4a19c7571da5fcfb732e5e1a8))
375
+ * **scripts:** close nine silent-loss paths in the design-system import adapter ([ed4c7e3](https://github.com/event4u-app/agent-config/commit/ed4c7e39ad3bd732b034c24952460332bb7cb503))
376
+ * **docs:** regenerate proof.md after the command-count change ([c5cb075](https://github.com/event4u-app/agent-config/commit/c5cb07529d8e1903ad15bbf300ce4156fb5a11b2))
377
+ * **ci:** wire check_gate_coverage locally too, and correct three numbers ([a62745c](https://github.com/event4u-app/agent-config/commit/a62745cea249ace8e89a453e9f5950e7179721ce))
378
+ * **ci:** wire the two meta-gates, re-anchor the parity floor ([ea13fc7](https://github.com/event4u-app/agent-config/commit/ea13fc77f2cceecc127933b7f56a5fbcc5a07709))
379
+ * **commands:** register analyze:conformance in the table it already belonged in ([2c307f3](https://github.com/event4u-app/agent-config/commit/2c307f392061eb4ff24a15b1c29b7ddc5c162b71))
380
+ * **hooks:** close the round-2 completion-review findings ([a3de33b](https://github.com/event4u-app/agent-config/commit/a3de33beacff72725b48e4ebdd0bb58b4258bee1))
381
+ * **contracts:** drop the roadmap link from the activation policy ([4d49029](https://github.com/event4u-app/agent-config/commit/4d49029266a04d8d025e110be0a574553634acea))
382
+ * **roadmap:** sync the Phase 2 record with the shipped floors, and own the red ([f98d9d5](https://github.com/event4u-app/agent-config/commit/f98d9d52998c016ad865334ffdf3964b4e01a8e3))
383
+ * **hooks:** close the twelve R2 completion-review findings in the subagent ledger ([4415ff5](https://github.com/event4u-app/agent-config/commit/4415ff54c2e8f47375aeeada5e5d9776eccefa86))
384
+ * **gates:** emit a parseable scan line, and refuse a valueless --root ([8ec2334](https://github.com/event4u-app/agent-config/commit/8ec2334a526572dd549b571f40bf9a24928dbd35))
385
+ * **refs:** re-point the archived roadmap and record a two-gate contradiction ([9671002](https://github.com/event4u-app/agent-config/commit/9671002114d27fcbd112d3f77d79dfaacc94c821))
386
+ * **roadmap:** tag the corpus-scoping roadmap lightweight, not standard ([b6676b0](https://github.com/event4u-app/agent-config/commit/b6676b09f87c48aa083feb98f2ff7343c837bd18))
387
+
388
+ ### Documentation
389
+
390
+ * **review:** re-bind the findings artefact after the consumer-path fix ([fcb8ab4](https://github.com/event4u-app/agent-config/commit/fcb8ab408c9b2fbfd51d98e261ead5c572e5cf7a))
391
+ * **review:** re-bind the findings artefact after the second main merge ([cfd2695](https://github.com/event4u-app/agent-config/commit/cfd2695162708c3db80b699667dbc7108c9e057c))
392
+ * **review:** re-bind the findings artefact to the post-fix scope ([2674827](https://github.com/event4u-app/agent-config/commit/267482700c5d00db465722005888f823d50acc4c))
393
+ * **review:** re-bind the skip declaration to the merged scope ([6518a6a](https://github.com/event4u-app/agent-config/commit/6518a6a12a69bc640c70febcf36d176ae05b8992))
394
+ * **design-system:** correct two claims the review showed were too broad ([49b6e47](https://github.com/event4u-app/agent-config/commit/49b6e4741aa21a18c72c3f51f9775981f980bb1f))
395
+ * **review:** bind the R2 completion-review findings for feat-design-system-onramp ([3be0b77](https://github.com/event4u-app/agent-config/commit/3be0b771bf99816ab4b0a7d9d69c51ea8e41a848))
396
+ * **roadmap:** close road-to-local-only-gate-reds and archive it ([cfeeacc](https://github.com/event4u-app/agent-config/commit/cfeeacc81c2b09f18d7e5fcfd7a312b05dd0b209))
397
+ * **roadmap:** archive road-to-august-program on its own falsifier ([3fd5a77](https://github.com/event4u-app/agent-config/commit/3fd5a776750447e6967137be31ee76a6e1c7b4b4))
398
+ * **roadmap:** resolve the three release-integrity blockers and archive it ([9d66d73](https://github.com/event4u-app/agent-config/commit/9d66d73f45b28ed8c17b842ca0f730cf11ca614d))
399
+ * **contract:** publish the curated-head recurrence rate, (b) stands ([310b49b](https://github.com/event4u-app/agent-config/commit/310b49b1d4b5f8fe7a12d6199c84429257cc4e0c))
400
+ * **adr:** ADR-228 — the global install does not emit paths: ([d9bcbf5](https://github.com/event4u-app/agent-config/commit/d9bcbf5c46e7d4c100f1bceabe429c0df6b42990))
401
+ * **adr:** accept ADR-221, the host-native-first ladder ([a55a37f](https://github.com/event4u-app/agent-config/commit/a55a37f6f88eb08326d56a0562c22324fa1746dc))
402
+ * **review:** re-bind the round-2 findings after the fix pass ([f1403f1](https://github.com/event4u-app/agent-config/commit/f1403f1896b4570b6eb83c9ac0f1c28b1d504914))
403
+ * **review:** bind round 2 of the completion review, and keep round 1 ([7914694](https://github.com/event4u-app/agent-config/commit/7914694b9055c4b47caf5c01c49699cb1aa77f01))
404
+ * **design-system:** name the supply path where the contract is refused ([0bef92d](https://github.com/event4u-app/agent-config/commit/0bef92d6314c82978bce578effaff7e43e24ea6c))
405
+ * **roadmap:** record the Phase 3 council pass and flip its three steps ([e1c99ad](https://github.com/event4u-app/agent-config/commit/e1c99ad25ece149cd80c0879957b01702148cc00))
406
+ * **contracts:** write the concern activation policy three roadmaps cited and none wrote ([130a9d9](https://github.com/event4u-app/agent-config/commit/130a9d98ad691888a3d41bec71f170e8e6d853c3))
407
+ * **review:** re-bind the round-2 artefact to the fixed scope ([1cba2b1](https://github.com/event4u-app/agent-config/commit/1cba2b111a3759d565ec0071ee1607c7c0d6bbec))
408
+ * **review:** round 2 of the completion review, over the merged scope ([57e4fc5](https://github.com/event4u-app/agent-config/commit/57e4fc58491b80ce70f994963fbcaa6fbe972be4))
409
+ * **review:** re-bind the findings artefact after the fix pass ([b58fcd5](https://github.com/event4u-app/agent-config/commit/b58fcd59ea10b899d6feaa1b7afa632c437f3d77))
410
+ * **review:** bind the R2 completion-review findings for feat-subagent-lifecycle-integrity ([79b7c8e](https://github.com/event4u-app/agent-config/commit/79b7c8eb27f114ae6d40d6c168fa5c992be1b650))
411
+ * **review:** re-bind the completion-review artefact to the fixed scope ([c714668](https://github.com/event4u-app/agent-config/commit/c71466897e1053bc28387d3da1240a3773534a0b))
412
+ * **review:** R2 completion review for feat-local-only-gate-reds ([3c87378](https://github.com/event4u-app/agent-config/commit/3c87378c83b36da10a82af729ffa224d506716a8))
413
+ * **roadmap:** record the Phase 0/1/5 findings and the Phase 3 stop ([3fc4332](https://github.com/event4u-app/agent-config/commit/3fc433269cc36520bb10e5f08f302cdfdffc5d5a))
414
+ * **review:** declare the completion-review skip for a zero-code-path branch ([ac92f16](https://github.com/event4u-app/agent-config/commit/ac92f1686a44ca8d52cf652fb3c35ec71224d800))
415
+ * **adr:** record that paths scoping is saturated, not a corpus lever ([6c062d9](https://github.com/event4u-app/agent-config/commit/6c062d9d57e290a50b0eb544448e83b8ec03c396))
416
+ * **roadmap:** record the four closed steps, and a fifth red the repair left ([637c009](https://github.com/event4u-app/agent-config/commit/637c00913b9936d5ceb8fe5cdffa8eddd610ef47))
417
+
418
+ ### Chores
419
+
420
+ * **dist:** re-project the design-system doc and halt-text changes ([070f4ce](https://github.com/event4u-app/agent-config/commit/070f4ce7b48ca0f206b6fae413a8f529d3f5bf0b))
421
+ * **roadmap:** regenerate the dashboard after the main merge ([54250e3](https://github.com/event4u-app/agent-config/commit/54250e3f6de110ba8881386e6e8c95be38b9b8d4))
422
+ * **roadmap:** close design-system-onramp Phases 1, 2 and 4; file two blockers ([80573dd](https://github.com/event4u-app/agent-config/commit/80573dd7d75ab27d026138e54ef06119daec59e8))
423
+ * **roadmaps:** regenerate the dashboard after the main merge ([d54aba9](https://github.com/event4u-app/agent-config/commit/d54aba956229302c3bc7323ddf8cafd7bd4ccb3c))
424
+ * **roadmap:** regenerate the dashboard after the second main merge ([b1a283b](https://github.com/event4u-app/agent-config/commit/b1a283bb04d9a881aa13495c28f0779557792670))
425
+ * **roadmap:** close always-loaded-corpus-scoping on its honest null ([5a9f530](https://github.com/event4u-app/agent-config/commit/5a9f53009a920ff16b9cc92e39167497a51d92ab))
426
+
427
+ Tests: 13768 (+89 since 10.3.0)
428
+
351
429
  ## [10.3.0](https://github.com/event4u-app/agent-config/compare/10.2.0...10.3.0) (2026-08-13)
352
430
 
353
431
  ### Release highlights
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  [![Smoke](https://github.com/event4u-app/agent-config/actions/workflows/smoke.yml/badge.svg)](https://github.com/event4u-app/agent-config/actions/workflows/smoke.yml) [![Public install smoke (3 OS × 2 Node)](https://github.com/event4u-app/agent-config/actions/workflows/smoke-public-install.yml/badge.svg)](https://github.com/event4u-app/agent-config/actions/workflows/smoke-public-install.yml) [![npm](https://img.shields.io/npm/v/@event4u/agent-config?style=flat-square&label=npm&color=orange)](https://www.npmjs.com/package/@event4u/agent-config) [![agent-config MCP server](https://glama.ai/mcp/servers/event4u-app/agent-config/badges/score.svg)](https://glama.ai/mcp/servers/event4u-app/agent-config) [![MCP Toplist](https://mcptoplist.com/badge/glama%2Fevent4u-app%2Fagent-config.svg)](https://mcptoplist.com/server/glama%2Fevent4u-app%2Fagent-config)
6
6
 
7
- [![Skills](https://img.shields.io/badge/Skills-289-orange?style=flat-square)](dist/agent-src/skills/) [![Rules](https://img.shields.io/badge/Rules-116-orange?style=flat-square)](dist/agent-src/rules/) [![Commands](https://img.shields.io/badge/Commands-196-orange?style=flat-square)](dist/agent-src/commands/) [![Guidelines](https://img.shields.io/badge/Guidelines-105-orange?style=flat-square)](docs/guidelines/) [![Personas](https://img.shields.io/badge/Personas-29-orange?style=flat-square)](dist/agent-src/personas/) [![Advisors](https://img.shields.io/badge/Advisors-5-orange?style=flat-square)](dist/agent-src/personas/advisors/)
7
+ [![Skills](https://img.shields.io/badge/Skills-289-orange?style=flat-square)](dist/agent-src/skills/) [![Rules](https://img.shields.io/badge/Rules-116-orange?style=flat-square)](dist/agent-src/rules/) [![Commands](https://img.shields.io/badge/Commands-200-orange?style=flat-square)](dist/agent-src/commands/) [![Guidelines](https://img.shields.io/badge/Guidelines-105-orange?style=flat-square)](docs/guidelines/) [![Personas](https://img.shields.io/badge/Personas-29-orange?style=flat-square)](dist/agent-src/personas/) [![Advisors](https://img.shields.io/badge/Advisors-5-orange?style=flat-square)](dist/agent-src/personas/advisors/)
8
8
 
9
9
  **Try it in 30 seconds** — drop one read-only subagent into any repo and watch it gate "done": `@production-validator check this branch is actually done`. No wizard, no lock-in, nothing else installed — the [30-second wedge ↓](#quickstart) is the whole first step. Start at the proof, not the catalog: **[event4u-app.github.io/agent-config/proof/](https://event4u-app.github.io/agent-config/proof/)**.
10
10
 
@@ -5,7 +5,7 @@ disable-model-invocation: true
5
5
  argument-hint: "[postmortem|premortem|decision|near-miss|incident|reference-repo|inbox] [subject]"
6
6
  pack: analysis-workbench
7
7
  intent: "Analysis dispatcher — classify input by keywords, propose a weighted framework path, let the user pick"
8
- routes_to: [analyze-postmortem, analyze-premortem, analyze-decision, analyze-near-miss, analyze-incident, analyze-reference-repo, analyze-inbox]
8
+ routes_to: [analyze-postmortem, analyze-premortem, analyze-decision, analyze-near-miss, analyze-incident, analyze-reference-repo, analyze-inbox, analyze-conformance]
9
9
  replaces: []
10
10
  tier: 1
11
11
  visibility: advanced
@@ -40,6 +40,7 @@ to the chosen sub-command. Never auto-selects silently.
40
40
  | `/analyze:incident` | `analyze/incident/command.md` | Full incident flow: commander → RCA → post-mortem → memory candidate |
41
41
  | `/analyze:reference-repo` | `analyze/reference-repo/command.md` | Deep-dive an external reference repo (competitor, inspiration, peer) → structured comparison + adoption plan |
42
42
  | `/analyze:inbox` | `analyze/inbox/command.md` | Deep-dive a LOCAL artifact dropped in `agents/tmp/` (review, prompt, spec, transcript) → claim verification against the current tree + artefact mapping + roadmap |
43
+ | `/analyze:conformance` | `analyze/conformance/command.md` | Audit recent local sessions for rule violations → deterministic scan + subagent passes, root-caused per class, and a roadmap for what is mechanisable |
43
44
 
44
45
  ## Dispatch
45
46
 
@@ -0,0 +1,44 @@
1
+ ---
2
+ model_tier: medium
3
+ name: design-system-capture
4
+ pack: engineering-base
5
+ tier: 2
6
+ visibility: internal
7
+ cluster: design-system
8
+ sub: capture
9
+ skills: [existing-ui-audit, design-system-capture]
10
+ description: Inventory this repo's own components and tokens and emit them in the design-system.json shape, so the import path is identical to an external extraction.
11
+ argument-hint: "[path]"
12
+ suggestion:
13
+ eligible: false
14
+ rationale: "Cluster sub-command — reached via its cluster head's routing or its explicit /cluster:sub name; not independently suggested (surface-consolidation)."
15
+ workspaces:
16
+ - engineering
17
+ packs:
18
+ - frontend-design
19
+ ---
20
+
21
+ # /design-system:capture
22
+
23
+ Run [`existing-ui-audit`](../../skills/existing-ui-audit/SKILL.md) over the
24
+ current repo and emit its inventory as a `design-system.json` artifact — the
25
+ same shape an external extraction tool produces, so the import path is identical
26
+ either way. Args: optional `[path]` to narrow the scan.
27
+
28
+ Two sources, one shape: use this for **this** repo, and
29
+ [`/design-system:import`](../import/command.md) for a site or repo you do not
30
+ own.
31
+
32
+ ## Then hand it over
33
+
34
+ Pass the emitted artifact to [`design-system-capture`](../../skills/design-system-capture/SKILL.md)'s
35
+ import step, which confirms it per field into `DESIGN.md`.
36
+
37
+ ## Rules
38
+
39
+ - **Set `source` honestly** — `kind: dir`, `ref` = the scanned path,
40
+ `captured_at` = now. An artifact with no provenance is rejected downstream.
41
+ - **Observation is not a token.** Anything the audit *noticed* rather than
42
+ *decided* belongs under `_meta`, per the contract's field rules.
43
+ - **The audit's own grouping is not the contract's shape.** Map it deliberately;
44
+ do not rename the audit's output keys and call it done.
@@ -0,0 +1,53 @@
1
+ ---
2
+ model_tier: high
3
+ name: design-system-generate
4
+ pack: engineering-base
5
+ tier: 2
6
+ visibility: internal
7
+ cluster: design-system
8
+ sub: generate
9
+ skills: [corpus-grounding, design-intelligence, design-system-capture]
10
+ description: Ground a design system in the curated design corpus from a product or industry brief, then optionally persist it as MASTER.md or seed DESIGN.md.
11
+ argument-hint: "<product / industry / keywords>"
12
+ suggestion:
13
+ eligible: false
14
+ rationale: "Cluster sub-command — reached via its cluster head's routing or its explicit /cluster:sub name; not independently suggested (surface-consolidation)."
15
+ workspaces:
16
+ - engineering
17
+ packs:
18
+ - frontend-design
19
+ ---
20
+
21
+ # /design-system:generate
22
+
23
+ Run the grounded one-shot over the curated corpus and print the full
24
+ recommendation. Args: `"<product / industry / keywords>"`.
25
+
26
+ ```bash
27
+ npx tsx node_modules/@event4u/agent-config/src/skills/corpus-grounding/scripts/ground.ts \
28
+ ground "<query>" \
29
+ --manifest node_modules/@event4u/agent-config/src/skills/design-intelligence/data/manifest.json
30
+ ```
31
+
32
+ Add `--persist <dir> --project-name <name>` to write
33
+ `design-system/<slug>/MASTER.md`, and `--page <name>` for a page-override stub
34
+ alongside it. The engine is read-only without `--persist`.
35
+
36
+ ## After the recommendation
37
+
38
+ Offer both destinations, and let the human pick — they are different artifacts,
39
+ not two spellings of one:
40
+
41
+ - **`MASTER.md` + page overrides** (`--persist`) — the interchange format, good
42
+ for handing a system to another tool or to a designer.
43
+ - **`DESIGN.md`** via [`design-system-capture`](../../skills/design-system-capture/SKILL.md)
44
+ — this package's canonical design memory, the file every later design task
45
+ reads. Seed it when the system is for *this* repo's own work.
46
+
47
+ ## Rules
48
+
49
+ - **Generated output is a proposal.** A provided artifact, registered brand
50
+ tokens, and a confirmed `DESIGN.md` outrank it — never overwrite a confirmed
51
+ decision with a generated default.
52
+ - **Never persist silently.** `--persist` is the human's choice, and `DESIGN.md`
53
+ is seeded per field, not written wholesale.
@@ -0,0 +1,63 @@
1
+ ---
2
+ model_tier: medium
3
+ name: design-system-import
4
+ pack: engineering-base
5
+ tier: 2
6
+ visibility: internal
7
+ cluster: design-system
8
+ sub: import
9
+ skills: [design-system-capture]
10
+ description: Run an extraction tool's output through the three-lane adapter into the design-system.json contract, then hand it to the per-field confirmation import.
11
+ argument-hint: "<file>"
12
+ suggestion:
13
+ eligible: false
14
+ rationale: "Cluster sub-command — reached via its cluster head's routing or its explicit /cluster:sub name; not independently suggested (surface-consolidation)."
15
+ workspaces:
16
+ - engineering
17
+ packs:
18
+ - frontend-design
19
+ ---
20
+
21
+ # /design-system:import
22
+
23
+ Transform an extracted design system into the `design-system.json` contract,
24
+ then import it per field. Args: `<file>`.
25
+
26
+ ```bash
27
+ npx tsx node_modules/@event4u/agent-config/src/scripts/design_system_import.ts <file> \
28
+ [--lane native|dtcg|dembrandt] \
29
+ [--source-kind url|repo|dir --source-ref <ref>] [--captured-at <ISO>] \
30
+ [--format json|summary]
31
+ ```
32
+
33
+ The lane is detected from the file's own shape; `--lane` only forces which
34
+ mapper runs and never reshapes the input. Lane behaviour, the documented
35
+ producers, and the never-force-a-lane degradation are specified in
36
+ [`design-system-json.md`](../../skills/design-system-capture/references/design-system-json.md)
37
+ § Extractor compatibility.
38
+
39
+ ## The easy path, in two lines
40
+
41
+ 1. Connect an extractor once — e.g.
42
+ `claude mcp add --transport stdio dembrandt -- npx -y --package dembrandt dembrandt-mcp`.
43
+ 2. Run `/design-system:import` over its output.
44
+
45
+ No extractor available? Skip step 1 and use
46
+ [`/design-system:generate`](../generate/command.md) from the corpus instead, or
47
+ [`/design-system:capture`](../capture/command.md) for this repo.
48
+
49
+ ## Then hand it over
50
+
51
+ Pass the result to [`design-system-capture`](../../skills/design-system-capture/SKILL.md)'s
52
+ import step. Do not write `DESIGN.md` from here.
53
+
54
+ ## Rules
55
+
56
+ - **Provenance is mandatory.** A file with no `source` and no `--source-ref` is
57
+ rejected — you cannot confirm what you cannot trace. Supplying it by flag is
58
+ recorded as caller-asserted, not extracted.
59
+ - **The artifact is observed, not authoritative.** Every field is confirmed by
60
+ the human; a value conflicting with a registered brand token is flagged, never
61
+ auto-applied.
62
+ - **The adapter is offline.** It reads a file and writes the contract shape — it
63
+ never fetches, crawls, or launches a browser.
@@ -0,0 +1,66 @@
1
+ ---
2
+ model_tier: inherit
3
+ name: design-system
4
+ pack: engineering-base
5
+ tier: 2
6
+ visibility: internal
7
+ cluster: design-system
8
+ type: orchestrator
9
+ description: Design-system onramp — generate one from the corpus, import an extractor's output, or capture the current repo's. Three doors onto machinery that already ships.
10
+ argument-hint: "[generate|import|capture] [args]"
11
+ suggestion:
12
+ eligible: true
13
+ trigger_description: "generate a design system, import extracted design tokens, capture this repo's design system, seed DESIGN.md from a site"
14
+ trigger_context: "user explicitly wants a design system produced, imported, or captured — never suggested for ordinary UI work"
15
+ workspaces:
16
+ - engineering
17
+ packs:
18
+ - frontend-design
19
+ ---
20
+
21
+ # /design-system
22
+
23
+ Three doors onto machinery this package already ships and nothing could reach.
24
+ The grounded generator, its `MASTER.md` persistence, the `design-system.json`
25
+ import contract, and the current-repo inventory all existed before this cluster;
26
+ what was missing was a way in. So every sub-command below is an entry point, not
27
+ a new subsystem.
28
+
29
+ **Optional means invoked or not invoked.** This cluster adds no settings key, no
30
+ always-on rule, and no auto-trigger. It is suggestion-eligible only when a
31
+ design-system question is explicit, and otherwise silent.
32
+
33
+ ## Sub-commands
34
+
35
+ | Sub-command | Routes to | Purpose |
36
+ |---|---|---|
37
+ | `/design-system:generate "<product / industry / keywords>"` | `commands/design-system/generate.md` | Ground a design system in the curated corpus; optionally persist `MASTER.md` + page overrides, or seed `DESIGN.md` |
38
+ | `/design-system:import <file>` | `commands/design-system/import.md` | Run an extractor's output through the three-lane adapter, then the per-field confirmation import |
39
+ | `/design-system:capture` | `commands/design-system/capture.md` | Inventory *this* repo's components and tokens and emit the same `design-system.json` shape |
40
+
41
+ ## Dispatch
42
+
43
+ 1. Parse `/design-system <sub-command> [args]`. Sub-command = first token; match
44
+ against the table's exact names only.
45
+ 2. Look up the sub-command and execute its file verbatim with the remaining args.
46
+ 3. Unknown / missing sub-command → print the table and ask which door to take.
47
+
48
+ ## Rules
49
+
50
+ - **Do NOT commit, push, or open a PR** — subcommands never do this.
51
+ - **Do NOT chain subcommands.** One `/design-system <sub>` per turn.
52
+ - **Generated and imported output is a proposal.** A provided artifact,
53
+ registered brand tokens, and a confirmed `DESIGN.md` all outrank it; a value
54
+ that conflicts with a registered brand token is flagged, never auto-applied
55
+ (per [`brand-source-of-truth`](../rules/brand-source-of-truth.md)).
56
+ - **No crawler, browser runtime, or font-bundler is shipped.** Extraction tools
57
+ are user-installed and user-connected; this package's share is the adapter,
58
+ the instructions, and the validation.
59
+ - **Edit `src/` only.** Generated mirrors regenerate.
60
+
61
+ ## See also
62
+
63
+ - [`design-system-capture`](../../skills/design-system-capture/SKILL.md) — owns `DESIGN.md` and the per-field-confirmation import.
64
+ - [`corpus-grounding`](../../skills/corpus-grounding/SKILL.md) · [`design-intelligence`](../../skills/design-intelligence/SKILL.md) — the grounded generator behind `:generate`.
65
+ - [`existing-ui-audit`](../../skills/existing-ui-audit/SKILL.md) — the current-repo inventory behind `:capture`.
66
+ - [`docs/contracts/command-clusters.md`](../docs/contracts/command-clusters.md) — `design-system` cluster registration.
@@ -202,6 +202,15 @@ auto-installer (out of scope). Full schema is lazy-loaded from
202
202
  [`references/design-system-json.md`](references/design-system-json.md) — read it
203
203
  only when an import is requested.
204
204
 
205
+ **The supply path is real, and it is one command.** Where an extractor's output
206
+ is not already in this shape, run it through the three-lane adapter first —
207
+ `/design-system:import <file>`, which accepts a native artifact, a DTCG token
208
+ file, or an extraction tool's raw JSON and emits the contract. Lanes and
209
+ documented producers:
210
+ [`references/design-system-json.md`](references/design-system-json.md)
211
+ § Extractor compatibility. The adapter is offline and pure — it does not change
212
+ what this skill owns.
213
+
205
214
  **Import procedure:**
206
215
 
207
216
  1. Read `design-system.json`; reject it if `source` (kind + ref + captured_at)
@@ -71,3 +71,73 @@ brand wins). Precedence on import: registered brand tokens > confirmed
71
71
 
72
72
  The package **owns this contract**; it does **not** ship the crawler, the
73
73
  Playwright runtime, or a font-bundler.
74
+
75
+ ## Extractor compatibility — which crawler, and how its output gets here
76
+
77
+ The contract above says what this skill reads. This section says how a real
78
+ tool's output becomes that shape, so the answer to *"which crawler?"* lives in
79
+ the contract rather than in somebody's memory.
80
+
81
+ `src/scripts/design_system_import.ts` is a **pure, offline file transform** with
82
+ three input lanes. It reads a file and writes the contract shape to stdout — no
83
+ network, no browser, no crawl. That is the lock restated as code: a transform
84
+ that fetched would quietly become the crawler this package does not ship.
85
+
86
+ | Lane | Input | What it does |
87
+ |---|---|---|
88
+ | `native` | an existing `design-system.json` | Validates `source`, carries every other key verbatim. Past provenance the validation is **report-only** — a key whose shape contradicts the contract is flagged and kept, never dropped, because the import is a proposal a human reads. |
89
+ | `dtcg` | a W3C DTCG token file (`{$value, $type}` leaves) | Buckets by `$type`, so it works on any authoring tool's layering — **with two stated path exceptions**: `dimension` / `number` is genuinely ambiguous in DTCG (spacing, radius and font size share it), so the path breaks that tie, and a path segment named `dark` files a colour under the dark theme. Both are inferences and both are reported in the notes. Resolves `{alias.references}` to their values. Tokens with no contract bucket land in `_meta.unmapped` — which is why `component.button.paddingX` lands there rather than under spacing. |
90
+ | `dembrandt` | an extraction tool's raw JSON | Matches the documented top-level key names and accepts a small set of shapes per bucket. Motion durations/easings become the `motion` block; per-context profiles, hover deltas, WCAG results and breakpoints are **observation** and land in `_meta`. |
91
+
92
+ ```bash
93
+ # The command is the supported entry point:
94
+ /design-system:import <file>
95
+
96
+ # Or call the transform directly, from an installed package:
97
+ npx tsx node_modules/@event4u/agent-config/src/scripts/design_system_import.ts <file> \
98
+ [--lane native|dtcg|dembrandt] \
99
+ [--source-kind url|repo|dir --source-ref <ref>] [--captured-at <ISO>] \
100
+ [--format json|summary]
101
+ ```
102
+
103
+ **Documented producers.** Two extraction tools are known to emit input this
104
+ adapter consumes, and both are **user-installed and user-connected** — the
105
+ package ships the adapter, the instructions, and the validation, never the tool:
106
+
107
+ - **dembrandt** (MIT, npm) — the richest single source: computed-DOM tokens,
108
+ automatic motion extraction (duration scale, easing curves), component
109
+ observations, WCAG pairs, and a stdio MCP server. Feeds the `dembrandt` lane
110
+ directly, or the `dtcg` lane via its `--dtcg` export.
111
+ - **designlang** (MIT) — DTCG in primitive/semantic/composite layers plus
112
+ interaction states. Feeds the `dtcg` lane. Its own repo-writing feature is not
113
+ invoked; this package owns its projection.
114
+
115
+ A third, **extract-design-system**, emits plain W3C `tokens.json` and feeds the
116
+ same `dtcg` lane. Any other tool that can export DTCG works without a new lane.
117
+
118
+ **Provenance is mandatory on every lane, and its origin is recorded.** DTCG
119
+ carries no `source` block by construction, so the caller supplies one; the
120
+ result then carries `source._meta.provenance_origin: "caller"` rather than
121
+ `"input"`, so a reader can always tell an extracted provenance from an asserted
122
+ one. Neither one present is a rejection, not a default — you cannot confirm what
123
+ you cannot trace.
124
+
125
+ **A lane is never forced.** Where a real sample cannot be mapped without
126
+ inventing values, the adapter emits it as `_meta` observation and says so in a
127
+ note. An import that lands mostly under `_meta` is the designed degradation, not
128
+ a failure — it means the tool's shape moved, and the values are still in front
129
+ of the human instead of silently coerced into tokens.
130
+
131
+ **Parked, not adopted — runtime drift detection.** One documented producer also
132
+ ships a drift gate: `--compare <baseline>` against a captured baseline, with
133
+ distinct exit codes (0 clean · 1 drift · 2 usage · 67 threshold) and a
134
+ machine-readable `drift` key carrying per-token `changes[]`. That is a
135
+ *design-quality CI* capability, not an import one, and nothing in this package
136
+ asks for it today — recorded here as a candidate so the next reader finds it
137
+ already assessed, and taken up only if a design-quality roadmap asks for runtime
138
+ drift detection.
139
+
140
+ The compatibility matrix is committed as tests, not prose:
141
+ `tests/scripts/fixtures/design-system-import/` holds one input/expected pair per
142
+ lane, and that directory's README states which sample is a real capture and
143
+ which is derived from a tool's published output surface.
@@ -39,7 +39,7 @@ schema_version: 1
39
39
  # CI guard: a release bump of `package.json` must update this value
40
40
  # in lockstep — see scripts/check_template_pin_drift.ts (road-to-
41
41
  # portable-runtime-and-update-check P3.3).
42
- agent_config_version: "10.3.0"
42
+ agent_config_version: "10.4.0"
43
43
 
44
44
  # --- Project identity ---
45
45
  project:
@@ -345,7 +345,10 @@ function _halt_provided_without_contract(
345
345
  '> 1. Proceed — port it with those five losses on the record; `apply` ' +
346
346
  'still has to report what it honoured, translated, and flagged',
347
347
  '> 2. Supply a `design-system.json` — its token values are then ' +
348
- 'honoured verbatim instead of re-derived',
348
+ 'honoured verbatim instead of re-derived. Already have an ' +
349
+ "extractor's output in another shape? `/design-system:import " +
350
+ '<file>` maps a DTCG token file or an extraction tool\'s raw JSON ' +
351
+ 'into this contract offline.',
349
352
  '> 3. Abort — drop this UI request',
350
353
  '',
351
354
  '**Recommendation: 2 — Supply the contract** — it is the only option ' +
@@ -0,0 +1,157 @@
1
+ import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
2
+ import {
3
+ git_common_dir
4
+ } from "./chunk-PZWRPRWP.js";
5
+
6
+ // src/scripts/_lib/envelope_grounding.ts
7
+ import { execFileSync } from "node:child_process";
8
+ import * as fs from "node:fs";
9
+ import * as path from "node:path";
10
+
11
+ // src/scripts/_lib/git_env.ts
12
+ var GIT_DISCOVERY_VARS = [
13
+ "GIT_DIR",
14
+ "GIT_WORK_TREE",
15
+ "GIT_INDEX_FILE",
16
+ "GIT_OBJECT_DIRECTORY",
17
+ "GIT_ALTERNATE_OBJECT_DIRECTORIES",
18
+ "GIT_COMMON_DIR",
19
+ "GIT_NAMESPACE",
20
+ "GIT_PREFIX"
21
+ ];
22
+ function gitEnv(base = process.env) {
23
+ const env = { ...base };
24
+ for (const key of GIT_DISCOVERY_VARS) {
25
+ delete env[key];
26
+ }
27
+ return env;
28
+ }
29
+
30
+ // src/scripts/_lib/envelope_grounding.ts
31
+ var MAX_FIELD_CHARS = 200;
32
+ var MAX_PATHS = 40;
33
+ function git(root, args) {
34
+ try {
35
+ return execFileSync("git", args, {
36
+ cwd: root,
37
+ env: gitEnv(),
38
+ encoding: "utf-8",
39
+ stdio: ["ignore", "pipe", "ignore"]
40
+ }).trim();
41
+ } catch {
42
+ return null;
43
+ }
44
+ }
45
+ function canonicalizeRepoIdentity(raw) {
46
+ let s = raw.trim();
47
+ s = s.replace(/^[a-z][a-z0-9+.-]*:\/\//i, "");
48
+ s = s.replace(/^[^/@]+@/, "");
49
+ s = s.replace(/^([^/:]+):(?!\/)/, "$1/");
50
+ s = s.replace(/\/+$/, "");
51
+ s = s.replace(/\.git$/i, "");
52
+ const slash = s.indexOf("/");
53
+ if (slash > 0) {
54
+ s = s.slice(0, slash).toLowerCase() + s.slice(slash);
55
+ } else {
56
+ s = s.toLowerCase();
57
+ }
58
+ return s;
59
+ }
60
+ function collectRepoAnchor(root) {
61
+ const remote = git(root, ["config", "--get", "remote.origin.url"]);
62
+ let identity = null;
63
+ if (remote) {
64
+ identity = canonicalizeRepoIdentity(remote);
65
+ } else {
66
+ const common = git_common_dir(root);
67
+ if (common !== null) {
68
+ try {
69
+ identity = fs.realpathSync(common);
70
+ } catch {
71
+ identity = common;
72
+ }
73
+ }
74
+ }
75
+ return {
76
+ repo_identity: identity ? identity.slice(0, MAX_FIELD_CHARS) : null,
77
+ branch: git(root, ["rev-parse", "--abbrev-ref", "HEAD"]),
78
+ head: git(root, ["rev-parse", "HEAD"])
79
+ };
80
+ }
81
+ var VERIFY_STATE_REL = path.join("agents", "runtime", "state", "verify-before-complete.json");
82
+ function readLastVerify(root) {
83
+ try {
84
+ const raw = fs.readFileSync(path.join(root, VERIFY_STATE_REL), "utf-8");
85
+ const state = JSON.parse(raw);
86
+ const lv = state["last_verification"];
87
+ if (typeof lv !== "object" || lv === null || Array.isArray(lv)) return null;
88
+ const rec = lv;
89
+ const command = typeof rec["command"] === "string" ? rec["command"] : null;
90
+ if (!command) return null;
91
+ const at = typeof rec["at"] === "string" ? rec["at"] : "unknown time";
92
+ return `${command} @ ${at} (no exit status is recorded anywhere)`.slice(0, MAX_FIELD_CHARS);
93
+ } catch {
94
+ return null;
95
+ }
96
+ }
97
+ function collectGrounding(root) {
98
+ const anchor = collectRepoAnchor(root);
99
+ const porcelain = git(root, ["status", "--porcelain"]);
100
+ if (porcelain === null) {
101
+ return { ...anchor, uncommitted_paths: [], status_summary: null, last_verify: readLastVerify(root) };
102
+ }
103
+ const lines = porcelain.split("\n").filter((l) => l.trim().length > 0);
104
+ const paths = lines.map((l) => l.slice(3).trim()).filter((p) => p.length > 0 && p.length <= MAX_FIELD_CHARS).slice(0, MAX_PATHS);
105
+ return {
106
+ ...anchor,
107
+ uncommitted_paths: paths,
108
+ status_summary: lines.length === 0 ? "clean working tree" : `${lines.length} uncommitted path(s)${lines.length > MAX_PATHS ? `, first ${MAX_PATHS} listed` : ""}`,
109
+ last_verify: readLastVerify(root)
110
+ };
111
+ }
112
+ function describeDrift(envelope, actual) {
113
+ if (typeof envelope !== "object" || envelope === null || Array.isArray(envelope)) return [];
114
+ const e = envelope;
115
+ const drift = [];
116
+ const recordedIdentity = typeof e["repo_identity"] === "string" ? e["repo_identity"] : null;
117
+ if (recordedIdentity && actual.repo_identity && recordedIdentity !== actual.repo_identity) {
118
+ drift.push(
119
+ `IDENTITY DRIFT: this envelope was written in "${recordedIdentity}", you are in "${actual.repo_identity}". Re-verify every path before acting \u2014 same branch name does not mean same working tree.`
120
+ );
121
+ }
122
+ const recordedBranch = typeof e["branch"] === "string" ? e["branch"] : null;
123
+ if (recordedBranch && actual.branch && recordedBranch !== actual.branch) {
124
+ drift.push(
125
+ `BRANCH DRIFT: envelope written on "${recordedBranch}", checkout is on "${actual.branch}".`
126
+ );
127
+ }
128
+ const recordedHead = typeof e["head"] === "string" ? e["head"] : null;
129
+ if (recordedHead && actual.head && recordedHead !== actual.head) {
130
+ drift.push(
131
+ `COMMIT DRIFT: envelope written at ${recordedHead.slice(0, 12)}, HEAD is now ${actual.head.slice(0, 12)} \u2014 re-read anything the envelope quotes.`
132
+ );
133
+ }
134
+ return drift;
135
+ }
136
+
137
+ // src/scripts/_lib/recycle_envelope_paths.ts
138
+ import * as path2 from "node:path";
139
+ var RECYCLE_ENVELOPE_REL = path2.join("agents", "runtime", "state", "recycle-envelope.json");
140
+ var RECYCLE_CONSUMED_REL = path2.join(
141
+ "agents",
142
+ "runtime",
143
+ "state",
144
+ "recycle-envelope.consumed.json"
145
+ );
146
+ var RECYCLE_MAX_AGE_HOURS = 48;
147
+ var RECYCLE_ENVELOPE_MAX_BYTES = 6144;
148
+
149
+ export {
150
+ collectRepoAnchor,
151
+ collectGrounding,
152
+ describeDrift,
153
+ RECYCLE_ENVELOPE_REL,
154
+ RECYCLE_CONSUMED_REL,
155
+ RECYCLE_MAX_AGE_HOURS,
156
+ RECYCLE_ENVELOPE_MAX_BYTES
157
+ };