@event4u/agent-config 4.9.0 → 5.1.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.
- package/.agent-src/commands/implement-ticket.md +5 -4
- package/.agent-src/contexts/execution/roadmap-process-loop.md +30 -4
- package/.agent-src/rules/language-and-tone.md +4 -10
- package/.agent-src/rules/linked-projects-onboarding-gate.md +82 -0
- package/.agent-src/rules/roadmap-progress-sync.md +39 -5
- package/.agent-src/scripts/update_roadmap_progress.py +63 -7
- package/.agent-src/skills/command-routing/SKILL.md +5 -4
- package/.agent-src/skills/roadmap-management/SKILL.md +121 -21
- package/.agent-src/skills/roadmap-writing/SKILL.md +63 -0
- package/.agent-src/templates/agent-settings.md +16 -0
- package/.agent-src/templates/roadmaps.md +22 -1
- package/.agent-src/templates/scripts/work_engine/_lib/agent_settings.py +20 -3
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +106 -0
- package/CONTRIBUTING.md +19 -0
- package/README.md +12 -1
- package/dist/cli/registry.js +0 -2
- package/dist/cli/registry.js.map +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +36 -14
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +6 -5
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +5 -4
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/router.json +1 -1671
- package/docs/architecture.md +1 -1
- package/docs/benchmark.md +20 -8
- package/docs/benchmarks.md +11 -0
- package/docs/catalog.md +3 -2
- package/docs/contracts/benchmark-corpus-spec.md +31 -3
- package/docs/contracts/command-surface-tiers.md +1 -1
- package/docs/contracts/hook-architecture-v1.md +33 -0
- package/docs/contracts/migrate-command.md +197 -0
- package/docs/contracts/settings-api.md +2 -1
- package/docs/contracts/value-dashboard-spec.md +374 -0
- package/docs/contracts/value-report-schema.md +150 -0
- package/docs/decisions/ADR-031-validation-severity-tiers-and-projection-roundtrip.md +97 -0
- package/docs/decisions/ADR-032-linked-projects-scope.md +118 -0
- package/docs/decisions/INDEX.md +2 -0
- package/docs/getting-started.md +1 -1
- package/docs/guidelines/agent-infra/installed-tools-manifest.md +6 -3
- package/docs/guidelines/agent-infra/language-and-tone-examples.md +35 -0
- package/docs/guides/cross-repo-linked-projects.md +86 -0
- package/docs/migration/v1-to-v2.md +40 -27
- package/docs/value.md +84 -0
- package/package.json +8 -8
- package/scripts/__pycache__/validate_frontmatter.cpython-312.pyc +0 -0
- package/scripts/_cli/cmd_migrate.py +264 -102
- package/scripts/_cli/cmd_settings_migrate.py +2 -1
- package/scripts/_dispatch.bash +147 -49
- package/scripts/_lib/__pycache__/__init__.cpython-312.pyc +0 -0
- package/scripts/_lib/__pycache__/agent_src.cpython-312.pyc +0 -0
- package/scripts/_lib/agent_settings.py +20 -3
- package/scripts/_lib/install_regenerator.py +129 -0
- package/scripts/_lib/linked_projects.py +238 -0
- package/scripts/_lib/value_ladder.py +599 -0
- package/scripts/_lib/value_report.py +441 -0
- package/scripts/bench_rtk_savings.py +320 -0
- package/scripts/check_no_local_settings_committed.py +51 -0
- package/scripts/compile_router.py +19 -5
- package/scripts/expected_perms.json +1 -1
- package/scripts/first_run_gate_hook.py +178 -0
- package/scripts/hook_manifest.yaml +16 -7
- package/scripts/hooks/dispatch_hook.py +27 -0
- package/scripts/hooks/dispatch_issues.py +136 -0
- package/scripts/hooks_doctor.py +40 -1
- package/scripts/install.py +25 -21
- package/scripts/lint_agents_layout.py +5 -4
- package/scripts/lint_bench_corpus.py +86 -4
- package/scripts/lint_global_paths.py +4 -3
- package/scripts/lint_marketplace_install_completeness.py +188 -0
- package/scripts/lint_value_dashboard.py +218 -0
- package/scripts/render_benchmark_md.py +6 -2
- package/scripts/render_value_md.py +355 -0
- package/scripts/repro/repro_marketplace_install_gap.sh +161 -0
- package/scripts/roadmap_progress_hook.py +23 -0
- package/scripts/router_telemetry.py +470 -0
- package/scripts/validate_frontmatter.py +23 -9
- package/scripts/_cli/cmd_migrate_to_global.py +0 -415
|
@@ -59,12 +59,13 @@ Three cases, in this order:
|
|
|
59
59
|
and `.work-state.json` does not. Migrate before doing anything else:
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
|
-
./agent-config migrate
|
|
62
|
+
./agent-config migrate
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
`.implement-ticket-state.json.bak
|
|
67
|
-
|
|
65
|
+
Unified `migrate` writes `.work-state.json`, renames source to
|
|
66
|
+
`.implement-ticket-state.json.bak`, sweeps other legacy install
|
|
67
|
+
artefacts (see `docs/contracts/migrate-command.md`). Idempotent and
|
|
68
|
+
safe to skip if already done. After this, treat the run as **Resume**.
|
|
68
69
|
- **Fresh run** — no state file at all. Write the resolved ticket to
|
|
69
70
|
`ticket.json` (id, title, body, acceptance_criteria) and pass it via
|
|
70
71
|
`--ticket-file ticket.json`. Honour `roles.active_role` from
|
|
@@ -231,10 +231,36 @@ execution either way.
|
|
|
231
231
|
consultations count (if on), steps remaining, halts.
|
|
232
232
|
- Final dashboard regen.
|
|
233
233
|
- **If the entire roadmap reached `count_open == 0`** → run the full
|
|
234
|
-
project quality pipeline. On
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
234
|
+
project quality pipeline. On red → stop, surface failures, do **not**
|
|
235
|
+
archive. On green → run **deferred-resolution gate** below before
|
|
236
|
+
archival.
|
|
237
|
+
|
|
238
|
+
### 6a. Deferred-resolution gate — Iron Law 3
|
|
239
|
+
|
|
240
|
+
Before any `git mv` to `archive/`, count `[~]` items in closing
|
|
241
|
+
roadmap. If `count_deferred > 0`, archival **blocked** per
|
|
242
|
+
[`roadmap-progress-sync § Iron Law 3`](../../rules/roadmap-progress-sync.md).
|
|
243
|
+
Loop MUST:
|
|
244
|
+
|
|
245
|
+
1. Enumerate every `[~]` step (phase + text + optional
|
|
246
|
+
`<!-- deferred: ... -->` annotation).
|
|
247
|
+
2. Surface numbered-options block from
|
|
248
|
+
[`roadmap-management § 4b`](../../skills/roadmap-management/SKILL.md) —
|
|
249
|
+
five choices: follow-up (draft), follow-up (ready + blocked),
|
|
250
|
+
keep-in-archive (intentional drop), restore to `[ ]`, convert
|
|
251
|
+
to `[-]` cancelled.
|
|
252
|
+
3. Wait for user. Autonomous mandate (`/work`,
|
|
253
|
+
`/roadmap:process-full`, "decide for me") does **not** lift this
|
|
254
|
+
gate — Iron Law 3 calls it "the canonical lost-information failure
|
|
255
|
+
mode this rule exists to prevent."
|
|
256
|
+
4. On picks 1 / 2 → run "Spawn follow-up from deferred items"
|
|
257
|
+
procedure in [`roadmap-management`](../../skills/roadmap-management/SKILL.md).
|
|
258
|
+
On picks 3 / 4 / 5 → apply change, re-evaluate decision table,
|
|
259
|
+
archive when gate clears.
|
|
260
|
+
|
|
261
|
+
`count_deferred == 0` → archive proceeds via
|
|
262
|
+
[`roadmap-management`](../../skills/roadmap-management/SKILL.md) skill
|
|
263
|
+
(`git mv`, regen).
|
|
238
264
|
|
|
239
265
|
## Scope deltas — what each wrapper binds
|
|
240
266
|
|
|
@@ -49,26 +49,20 @@ Stays in source language: code blocks, command output, file contents, quoted too
|
|
|
49
49
|
1. **Detect** — language of user's last chat message. Mixed → dominant; tie → German.
|
|
50
50
|
2. **Scan** — every user-visible token per catalog above.
|
|
51
51
|
3. **Rewrite** — wrong-language token → rewrite the whole reply.
|
|
52
|
-
4. **Confirm** — first sentence in target language; recommendation label matches; no
|
|
52
|
+
4. **Confirm** — first sentence in target language; recommendation label matches; no wrong-language filler-phrase opener. Blocklist: [`language-and-tone-examples § Pre-send gate`](../docs/guidelines/agent-infra/language-and-tone-examples.md#pre-send-gate--filler-phrase-blocklist).
|
|
53
53
|
|
|
54
54
|
## Spelled out
|
|
55
55
|
|
|
56
56
|
- German → informal "Du" (never "Sie"); capitalized at sentence start, lowercase otherwise.
|
|
57
57
|
- Code blocks / command output / file contents / quoted tool output stay native; only surrounding prose mirrors.
|
|
58
58
|
- Numbered options — `.md` source English; rendered reply translated at runtime.
|
|
59
|
+
- Code comments in English. `.md` files in English (see below). Translate existing German `.md` files when touched.
|
|
59
60
|
|
|
60
61
|
## Slip handling
|
|
61
62
|
|
|
62
63
|
Acknowledge **once** in the correct language ("Entschuldigung" / "Sorry"). Switch on the same reply. No re-explain in wrong language; no "from now on" promise.
|
|
63
64
|
|
|
64
|
-
Examples + wrong-vs-correct: [`language-and-tone-examples`](../docs/guidelines/agent-infra/language-and-tone-examples.md).
|
|
65
|
-
|
|
66
|
-
## Other language rules
|
|
67
|
-
|
|
68
|
-
- Code comments in English.
|
|
69
|
-
- `.md` files in English (see below). Translate existing German `.md` files when touched.
|
|
70
|
-
- Two spaces after `❌`, `✅`, `⚠️` in CLI; one space for other icons.
|
|
71
|
-
- One blank line max; no double/triple blanks. File ends with exactly one newline.
|
|
65
|
+
Examples + CLI spacing rules + wrong-vs-correct: [`language-and-tone-examples`](../docs/guidelines/agent-infra/language-and-tone-examples.md).
|
|
72
66
|
|
|
73
67
|
## `.md` files — ALWAYS English
|
|
74
68
|
|
|
@@ -76,4 +70,4 @@ Every text inside `.md` under `.augment/`, `.agent-src/`, `.agent-src.uncondense
|
|
|
76
70
|
|
|
77
71
|
**Labeled-anchor exception** — quoting German inside English prose is forbidden. Either translate, OR use a labeled `DE: … · EN: …` anchor block (only allowed location for German prose).
|
|
78
72
|
|
|
79
|
-
|
|
73
|
+
Pre-save detection heuristic (umlauts / German function words / non-English quoted phrases): [`language-and-tone-examples § pre-save detection`](../docs/guidelines/agent-infra/language-and-tone-examples.md#md-files--pre-save-detection-heuristic).
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: "auto"
|
|
3
|
+
tier: "2b"
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
description: "IDE-attached sibling repo detected — prompt once to opt it into proactive cross-repo awareness, persist local-only, then surface cross-repo impact on relevant changes"
|
|
6
|
+
source: package
|
|
7
|
+
triggers:
|
|
8
|
+
- intent: "work across two projects"
|
|
9
|
+
- intent: "sibling repository"
|
|
10
|
+
- keyword: "linked project"
|
|
11
|
+
- keyword: "cross-repo"
|
|
12
|
+
- keyword: "sibling repo"
|
|
13
|
+
- path_prefix: ".idea/modules.xml"
|
|
14
|
+
- path_prefix: ".idea/vcs.xml"
|
|
15
|
+
validator_ignore:
|
|
16
|
+
- type: "substring"
|
|
17
|
+
pattern: "scripts/_lib/linked_projects.py"
|
|
18
|
+
reason: "Rule names the detector module as the runtime detection entrypoint."
|
|
19
|
+
workspaces:
|
|
20
|
+
- agent-config-maintainer
|
|
21
|
+
- engineering
|
|
22
|
+
packs:
|
|
23
|
+
- engineering-base
|
|
24
|
+
lifecycle: experimental
|
|
25
|
+
trust:
|
|
26
|
+
level: experimental
|
|
27
|
+
confidence: medium
|
|
28
|
+
human_review_required: false
|
|
29
|
+
install:
|
|
30
|
+
default: true
|
|
31
|
+
removable: true
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
# Linked-Projects Onboarding Gate
|
|
35
|
+
|
|
36
|
+
**Iron Law.** IDE attached a sibling repo and it is not yet in `linked_projects` → prompt developer **once** to opt in, persist local-only, then proactively flag cross-repo impact — never bulk-include the sibling's files.
|
|
37
|
+
|
|
38
|
+
Closes the **proactivity gap**: agent can already read/write a sibling, but does not *consider* one unless told — and the developer who most needs cross-repo awareness won't think to mention the sibling. Detection reads the relationship already encoded by attaching the repo in the IDE (zero-knowledge). See the cross-repo guide (`docs/guides/cross-repo-linked-projects.md`) and ADR-032.
|
|
39
|
+
|
|
40
|
+
## When this fires
|
|
41
|
+
|
|
42
|
+
First substantive turn (and on new IDE attachment), when a detected sibling is absent from `linked_projects` in `.agent-settings.local.yml` (in agents/settings/). Inert when no sibling attached or every detected sibling already decided (opted-in or declined).
|
|
43
|
+
|
|
44
|
+
## Detection
|
|
45
|
+
|
|
46
|
+
Run the detector against project root:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
python3 -c "from scripts._lib.linked_projects import detect_linked_projects; \
|
|
50
|
+
import json; print(json.dumps(detect_linked_projects('.')))"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Returns config-attached siblings only (PhpStorm `.idea/modules.xml` + `vcs.xml`, VS Code `*.code-workspace`) resolving outside the project, existing, git repos. A sibling above `linked_projects_max_files` (default 20000) carries `"large": true` — awareness only, never excluded.
|
|
54
|
+
|
|
55
|
+
## Opt-in (one-time per sibling)
|
|
56
|
+
|
|
57
|
+
For each detected sibling **not** already in `linked_projects`, ask once (numbered options per `user-interaction`): include / decline / always / never-ask. Persist to `.agent-settings.local.yml` (in agents/settings/) (gitignored per-machine layer — never committed `.agent-settings.yml`):
|
|
58
|
+
|
|
59
|
+
```yaml
|
|
60
|
+
linked_projects:
|
|
61
|
+
- path: /abs/path/to/sibling
|
|
62
|
+
include: true # false = declined; never re-prompt
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Declined sibling (`include: false`) never prompted again.
|
|
66
|
+
|
|
67
|
+
## Behavioral directive (each `include: true` sibling)
|
|
68
|
+
|
|
69
|
+
- **proactively check cross-repo impact** when a change here may affect it — API-contract changes, shared-type / enum drift, renamed routes the sibling consumes — and **warn** before finishing;
|
|
70
|
+
- **do not bulk-include** the sibling's files (passive awareness, not implicit inclusion — large repos stay cheap);
|
|
71
|
+
- out-of-root edits are normal work, but the host agent's own out-of-root **permission gate still applies** (no silent cross-repo write).
|
|
72
|
+
|
|
73
|
+
## Kill-switch
|
|
74
|
+
|
|
75
|
+
Experimental, removable rule. If opt-in consistently declined or siblings never cited, remove it — no telemetry, signal is local.
|
|
76
|
+
|
|
77
|
+
## Follow-up (not yet shipped)
|
|
78
|
+
|
|
79
|
+
- Consumer-install detector reachability: detector lives in `scripts/_lib/`; exposing it as an `agent-config` CLI subcommand for consumers is a follow-up. Import-reachable in this repo / co-located maintainer setups today.
|
|
80
|
+
- Multi-agent verification: only Claude Code empirically validated (ADR-032). Cursor / Augment / Copilot unverified — manual fallback in the guide covers them until tested.
|
|
81
|
+
|
|
82
|
+
Trigger-set above activates this routing under the `balanced` and `full` profiles.
|
|
@@ -48,11 +48,42 @@ IS A RULE VIOLATION, NOT AN OVERSIGHT.
|
|
|
48
48
|
|
|
49
49
|
`command:` triggers in this rule's frontmatter load it the moment any `/roadmap:process-*` command fires and keep it loaded for the whole run — independent of whether the agent is editing files under `agents/roadmaps/`. The loop carries its own deterministic flip-guard at [`roadmap-process-loop § 5b`](../contexts/execution/roadmap-process-loop.md#5b-flip-guard--deterministic) — defense-in-depth, not a substitute for the inline flip.
|
|
50
50
|
|
|
51
|
-
**Step counts as done** when
|
|
51
|
+
**Step counts as done** when code/doc saved AND verification cited in step passed (fresh output, this reply or earlier).
|
|
52
52
|
|
|
53
|
-
**
|
|
53
|
+
**Glyph semantics** — single source of truth, aligned with `scripts/update_roadmap_progress.py` and [`roadmap-management`](../skills/roadmap-management/SKILL.md):
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
| Glyph | Meaning | Counter |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| `[ ]` | open — planned, not done | `count_open` |
|
|
58
|
+
| `[x]` | done — landed + verified | `count_done` |
|
|
59
|
+
| `[~]` | deferred — planned, not happening **this** run; blocks archive (Iron Law 3) | `count_deferred` |
|
|
60
|
+
| `[-]` | cancelled — scope dropped | `count_cancelled` |
|
|
61
|
+
|
|
62
|
+
`[~]` is **not** "in-progress". Mid-reply work-in-flight has no checkbox change until step lands — normal `[ ] → [x]`.
|
|
63
|
+
|
|
64
|
+
**Dashboard regen cadence — opt-in batching.** Checkbox flip is non-batchable. **Subprocess regen** (`./agent-config roadmap:progress`) is batchable per `roadmap.dashboard_regen_cadence` (`per_step` default · `every_5_steps` · `phase_boundary`). Run end, phase boundary, any file-shape touch (rename / phase add / archive — Iron Law 1) always force immediate regen regardless of cadence.
|
|
65
|
+
|
|
66
|
+
## Iron Law 3 — no silent archive with unresolved deferred items
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
A ROADMAP WITH `[~]` DEFERRED ITEMS NEVER AUTO-ARCHIVES SILENTLY.
|
|
70
|
+
SURFACE EVERY DEFERRED STEP. ASK USER WHAT HAPPENS TO THE PLAN.
|
|
71
|
+
A SILENT ARCHIVE THAT BURIES PLANNED-FOR-LATER WORK
|
|
72
|
+
IS A RULE VIOLATION, NOT A CONVENIENCE.
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
When closure check fires (`count_open == 0` and `count_deferred > 0`), agent MUST:
|
|
76
|
+
|
|
77
|
+
1. Enumerate every `[~]` step (phase + step text + any inline `<!-- deferred: ... -->` annotation).
|
|
78
|
+
2. Present numbered options (per [`user-interaction`](user-interaction.md)) — at minimum:
|
|
79
|
+
1. **Follow-up roadmap (draft)** — spawn `agents/roadmaps/road-to-<slug>.md` with `status: draft`, `parent_roadmap: <this-slug>`, deferred steps lifted verbatim into phases. Draft hidden from dashboard until flipped to `ready`.
|
|
80
|
+
2. **Follow-up roadmap (ready, blocked)** — spawn with `status: ready` (default), `parent_roadmap: <this-slug>`, plus body note `> Blocked until <condition>`. Dashboard surfaces it; execution waits.
|
|
81
|
+
3. **Keep in this archive** — confirm deferred items stay searchable in archived file; no follow-up. Records explicit decision-to-drop in same reply.
|
|
82
|
+
4. **Restore selected items to `[ ]`** — finish them in this roadmap before archive.
|
|
83
|
+
5. **Convert selected items to `[-]` cancelled** — drop with rationale recorded inline.
|
|
84
|
+
3. Only after user resolves deferrals does `git mv` to `archive/` run. Dashboard regen happens after resolution.
|
|
85
|
+
|
|
86
|
+
Migration mechanics (file naming, frontmatter, body shape, parent back-link) live in [`roadmap-management § Spawn follow-up from deferred items`](../skills/roadmap-management/SKILL.md). Rule owns obligation; skill owns procedure.
|
|
56
87
|
|
|
57
88
|
## Pre-send self-check — MANDATORY
|
|
58
89
|
|
|
@@ -66,9 +97,12 @@ Before sending any reply that landed roadmap work:
|
|
|
66
97
|
- `phase_boundary` → only when this reply closes the phase or run.
|
|
67
98
|
- Any file-shape touch (rename / phase add / archive) → yes, regardless of cadence.
|
|
68
99
|
If yes and not run yet → run `./agent-config roadmap:progress`, then continue.
|
|
69
|
-
4. Did `count_open` reach 0?
|
|
100
|
+
4. Did `count_open` reach 0?
|
|
101
|
+
- **No** → continue normally.
|
|
102
|
+
- **Yes + `count_deferred == 0`** → `git mv` to `archive/` and regen again — same reply.
|
|
103
|
+
- **Yes + `count_deferred > 0`** → STOP. Run Iron Law 3 deferred-resolution flow (surface items + numbered options + wait). Archive only after resolution.
|
|
70
104
|
|
|
71
|
-
Any "no" at step 2 → reply is incomplete. Do not send.
|
|
105
|
+
Any "no" at step 2 → reply is incomplete. Do not send. Skipped step 3 regen fine when cadence permits — checkbox truth lives in markdown file. Skipping deferred-resolution gate at step 4 is **never** acceptable; it is the canonical "lost-information" failure mode this rule exists to prevent.
|
|
72
106
|
|
|
73
107
|
Long-form mechanics (failure-mode catalog, Copilot fallback, `[~]` vs `[ ]` semantics, hook + CI defence-in-depth) live in `guideline:agent-infra/roadmap-progress-mechanics`.
|
|
74
108
|
Trigger-set above activates this routing under the `balanced` and `full` profiles.
|
|
@@ -16,6 +16,13 @@ Checkbox states:
|
|
|
16
16
|
Percentage = done / (done + open). Deferred and cancelled do not count towards
|
|
17
17
|
"open" (they are explicit decisions).
|
|
18
18
|
|
|
19
|
+
`[~]` deferred items carry plans the user intends to revisit later. They
|
|
20
|
+
block silent auto-archive per `roadmap-progress-sync` Iron Law 3: a
|
|
21
|
+
roadmap with `count_open == 0` and `count_deferred > 0` is reported
|
|
22
|
+
separately (`pending_iron_law_3`) and the user must resolve the
|
|
23
|
+
deferrals (spawn follow-up roadmap, restore, or convert to cancelled)
|
|
24
|
+
before the file moves to `archive/`.
|
|
25
|
+
|
|
19
26
|
Roadmap visibility is binary:
|
|
20
27
|
|
|
21
28
|
- No `status:` frontmatter (or `status: ready`) → executable, listed.
|
|
@@ -245,18 +252,38 @@ def collect(roadmap_root: Path) -> list[RoadmapStats]:
|
|
|
245
252
|
|
|
246
253
|
|
|
247
254
|
def unarchived_complete(roadmaps: list[RoadmapStats]) -> list[RoadmapStats]:
|
|
248
|
-
# A roadmap is complete when every active checkbox is done
|
|
249
|
-
# one active checkbox exists
|
|
250
|
-
#
|
|
251
|
-
#
|
|
252
|
-
#
|
|
253
|
-
|
|
255
|
+
# A roadmap is complete-and-clean when every active checkbox is done,
|
|
256
|
+
# at least one active checkbox exists, AND no `[~]` deferred items
|
|
257
|
+
# remain. The `roadmap-progress-sync` rule mandates that such a
|
|
258
|
+
# roadmap be moved to `agents/roadmaps/archive/` in the same response
|
|
259
|
+
# that closes its last open item; `collect()` already excludes that
|
|
260
|
+
# directory, so anything left here is unarchived.
|
|
261
|
+
#
|
|
262
|
+
# Deferred items are intentionally excluded — they block silent
|
|
263
|
+
# archive per Iron Law 3 (see `pending_iron_law_3` below).
|
|
264
|
+
return [
|
|
265
|
+
r for r in roadmaps
|
|
266
|
+
if r.total_active > 0 and r.open_ == 0 and r.deferred == 0
|
|
267
|
+
]
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def pending_iron_law_3(roadmaps: list[RoadmapStats]) -> list[RoadmapStats]:
|
|
271
|
+
# Roadmaps with no open work but unresolved `[~]` deferred items.
|
|
272
|
+
# Per `roadmap-progress-sync` Iron Law 3 the agent must NOT auto-
|
|
273
|
+
# archive these — surface the deferred items and ask the user
|
|
274
|
+
# (spawn follow-up, restore, or convert). The dashboard merely
|
|
275
|
+
# reports the state; the obligation lives in the rule.
|
|
276
|
+
return [
|
|
277
|
+
r for r in roadmaps
|
|
278
|
+
if r.total_active > 0 and r.open_ == 0 and r.deferred > 0
|
|
279
|
+
]
|
|
254
280
|
|
|
255
281
|
|
|
256
282
|
def render(roadmaps: list[RoadmapStats]) -> str:
|
|
257
283
|
total_done = sum(r.done for r in roadmaps)
|
|
258
284
|
total_active = sum(r.total_active for r in roadmaps)
|
|
259
285
|
overall_pct = round(total_done * 100 / total_active) if total_active else 0
|
|
286
|
+
pending = pending_iron_law_3(roadmaps)
|
|
260
287
|
lines: list[str] = []
|
|
261
288
|
lines.append("# Roadmap Progress\n")
|
|
262
289
|
header_meta = (
|
|
@@ -274,6 +301,21 @@ def render(roadmaps: list[RoadmapStats]) -> str:
|
|
|
274
301
|
lines.append("## Overall\n")
|
|
275
302
|
lines.append(f"**{total_done} / {total_active} steps done · {overall_pct}%**\n")
|
|
276
303
|
lines.append("```text\n" + bar(overall_pct, 40) + f" {overall_pct}%\n```\n")
|
|
304
|
+
if pending:
|
|
305
|
+
lines.append("## ⚠️ Iron Law 3 — unresolved deferred items\n")
|
|
306
|
+
lines.append(
|
|
307
|
+
"These roadmaps have `count_open == 0` but carry `[~]` deferred "
|
|
308
|
+
"items. Per `roadmap-progress-sync` Iron Law 3 they do NOT "
|
|
309
|
+
"auto-archive — the user must resolve the deferrals first "
|
|
310
|
+
"(spawn follow-up, restore, or cancel). See "
|
|
311
|
+
"[`roadmap-management § 4b`](../packages/core/.agent-src.uncondensed/skills/roadmap-management/SKILL.md).\n"
|
|
312
|
+
)
|
|
313
|
+
lines.append("| Roadmap | Done | Deferred | Cancelled |")
|
|
314
|
+
lines.append("|---|---:|---:|---:|")
|
|
315
|
+
for r in pending:
|
|
316
|
+
lines.append(f"| [{r.rel}](roadmaps/{r.rel}) | {r.done} | "
|
|
317
|
+
f"{r.deferred} | {r.cancelled} |")
|
|
318
|
+
lines.append("")
|
|
277
319
|
if not roadmaps:
|
|
278
320
|
lines.append("_No open roadmaps._\n")
|
|
279
321
|
return "\n".join(lines) + "\n"
|
|
@@ -326,6 +368,7 @@ def main() -> int:
|
|
|
326
368
|
new_text = render(roadmaps)
|
|
327
369
|
current = target.read_text(encoding="utf-8") if target.exists() else ""
|
|
328
370
|
complete = unarchived_complete(roadmaps)
|
|
371
|
+
pending = pending_iron_law_3(roadmaps)
|
|
329
372
|
if args.check:
|
|
330
373
|
stale = current != new_text
|
|
331
374
|
if stale:
|
|
@@ -340,7 +383,14 @@ def main() -> int:
|
|
|
340
383
|
for r in complete:
|
|
341
384
|
print(f" - {r.rel} ({r.done}/{r.total_active} done)",
|
|
342
385
|
file=sys.stderr)
|
|
343
|
-
if
|
|
386
|
+
if pending:
|
|
387
|
+
print("❌ Iron Law 3 — roadmaps with unresolved `[~]` deferred "
|
|
388
|
+
"items must NOT auto-archive. Resolve via `roadmap-management § 4b` "
|
|
389
|
+
"(spawn follow-up, restore, or cancel):", file=sys.stderr)
|
|
390
|
+
for r in pending:
|
|
391
|
+
print(f" - {r.rel} ({r.done}/{r.total_active} done · "
|
|
392
|
+
f"{r.deferred} deferred)", file=sys.stderr)
|
|
393
|
+
if stale or complete or pending:
|
|
344
394
|
return 1
|
|
345
395
|
print(f"✅ {target.relative_to(args.repo_root)} is up to date.")
|
|
346
396
|
return 0
|
|
@@ -353,6 +403,12 @@ def main() -> int:
|
|
|
353
403
|
"`agents/roadmaps/archive/`:", file=sys.stderr)
|
|
354
404
|
for r in complete:
|
|
355
405
|
print(f" - {r.rel}", file=sys.stderr)
|
|
406
|
+
if pending:
|
|
407
|
+
print("⚠️ Iron Law 3 — roadmaps with unresolved `[~]` deferred items. "
|
|
408
|
+
"Surface them and ask the user (`roadmap-management § 4b`) "
|
|
409
|
+
"before any archive:", file=sys.stderr)
|
|
410
|
+
for r in pending:
|
|
411
|
+
print(f" - {r.rel} ({r.deferred} deferred)", file=sys.stderr)
|
|
356
412
|
return 0
|
|
357
413
|
|
|
358
414
|
|
|
@@ -80,10 +80,11 @@ output — surface it as-is. The two flows are mutually exclusive at the
|
|
|
80
80
|
state-file level: one `.work-state.json` carries one envelope at a
|
|
81
81
|
time, and the engine refuses to switch mid-flight.
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
`.implement-ticket-state.json` file
|
|
85
|
-
schema
|
|
86
|
-
|
|
83
|
+
Unified `./agent-config migrate` sweeps a legacy
|
|
84
|
+
`.implement-ticket-state.json` file into the v1 `.work-state.json`
|
|
85
|
+
schema as one cleanup step (see `docs/contracts/migrate-command.md`).
|
|
86
|
+
Wrapper invokes it automatically when legacy file is detected;
|
|
87
|
+
agents should not bypass the dispatcher.
|
|
87
88
|
|
|
88
89
|
## GitHub API: Replying to PR review comments
|
|
89
90
|
|
|
@@ -238,45 +238,145 @@ After the last step of a roadmap is done, check completion status:
|
|
|
238
238
|
- `[-]` = cancelled (individual item dropped)
|
|
239
239
|
|
|
240
240
|
3. **Decision rule — `count_open == 0` means the roadmap has no active
|
|
241
|
-
work left. `[x]`, `[
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
| ≥ 1 | 0 |
|
|
249
|
-
| 0 | 0 | ≥ 1 | **Auto-
|
|
250
|
-
| ≥ 0 | ≥ 1 | ≥ 0 | **
|
|
241
|
+
work left. `[x]`, `[-]` are final states. `[~]` deferred items
|
|
242
|
+
block silent closure — they carry plans user has not consented to drop
|
|
243
|
+
(enforced by [`roadmap-progress-sync`](../../rules/roadmap-progress-sync.md)
|
|
244
|
+
Iron Law 3).**
|
|
245
|
+
|
|
246
|
+
| count_x | count_open | count_deferred | count_cancelled | Action |
|
|
247
|
+
|---|---|---|---|---|
|
|
248
|
+
| ≥ 1 | 0 | 0 | 0 | **Auto-archive** (silent) — pure completion |
|
|
249
|
+
| ≥ 1 | 0 | 0 | ≥ 1 | **Auto-archive** (silent) — done with explicit drops |
|
|
250
|
+
| ≥ 1 | 0 | ≥ 1 | ≥ 0 | **STOP — Iron Law 3 flow.** Surface deferred items, present follow-up options, wait. Step 4b. |
|
|
251
|
+
| 0 | 0 | ≥ 1 | ≥ 0 | **STOP — Iron Law 3 flow.** Scope-drop or deferred-to-later? Same options as 4b. |
|
|
252
|
+
| 0 | 0 | 0 | ≥ 1 | **Auto-skip** (silent) — no work, all cancelled |
|
|
253
|
+
| ≥ 0 | ≥ 1 | ≥ 0 | ≥ 0 | **Ask the user** — open work remains (step 4a) |
|
|
251
254
|
|
|
252
255
|
Show on auto-move:
|
|
253
256
|
|
|
254
257
|
- Archive: `✅ Roadmap archived → agents/roadmaps/archive/{filename}`
|
|
255
258
|
- Skip: `⏭️ Roadmap skipped → agents/roadmaps/skipped/{filename}`
|
|
256
259
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
+
`[-]` cancelled items remain searchable in archived file — they were
|
|
261
|
+
explicit drops. `[~]` deferred items, by contrast, may not silently
|
|
262
|
+
follow file into archive: they represent work user planned and would
|
|
263
|
+
lose track of. Step 4b is the gate.
|
|
260
264
|
|
|
261
|
-
|
|
265
|
+
4a. **Open items remain (`count_open ≥ 1`)** → **Ask the user.** Show what's incomplete:
|
|
262
266
|
|
|
263
267
|
```
|
|
264
268
|
📋 Roadmap completion check:
|
|
265
269
|
|
|
266
270
|
✅ Completed: {count_x}
|
|
267
271
|
⬜ Open: {count_open} — {list of open items, 1 line each}
|
|
268
|
-
⏭️ Deferred: {
|
|
269
|
-
❌ Cancelled: {
|
|
272
|
+
⏭️ Deferred: {count_deferred} — {list of deferred items, 1 line each}
|
|
273
|
+
❌ Cancelled: {count_cancelled} — {list of cancelled items, 1 line each}
|
|
270
274
|
|
|
271
275
|
> 1. Archive — mark open items as cancelled [-] and archive now
|
|
272
276
|
> 2. Keep active — I want to finish the open items
|
|
273
|
-
> 3. Mark open items as deferred [~] and archive
|
|
277
|
+
> 3. Mark open items as deferred [~] and archive (triggers Iron Law 3 flow)
|
|
274
278
|
> 4. Skip — move to skipped/ (no meaningful work done, not pursuing)
|
|
275
279
|
```
|
|
276
280
|
|
|
277
|
-
Option 4
|
|
278
|
-
trivial (e.g. prerequisites
|
|
279
|
-
|
|
281
|
+
Option 4 only appropriate when `count_x == 0` or completed items were
|
|
282
|
+
trivial (e.g. prerequisites). If user picks 4 despite meaningful work
|
|
283
|
+
done, confirm once — archive usually right. Picking option 3 does
|
|
284
|
+
NOT archive immediately — converts open → deferred, re-enters the
|
|
285
|
+
`count_deferred > 0` branch, which runs step 4b.
|
|
286
|
+
|
|
287
|
+
4b. **Deferred items present (`count_deferred ≥ 1`, `count_open == 0`)** — Iron Law 3 flow.
|
|
288
|
+
Archive **blocked** until user resolves deferrals. Surface plan and ask:
|
|
289
|
+
|
|
290
|
+
```
|
|
291
|
+
📋 Roadmap closure check — deferred items must resolve before archive:
|
|
292
|
+
|
|
293
|
+
✅ Completed: {count_x}
|
|
294
|
+
⏭️ Deferred: {count_deferred}
|
|
295
|
+
{for each deferred item:}
|
|
296
|
+
- Phase {N}: {step text} {<!-- deferred: <annotation> --> if present}
|
|
297
|
+
|
|
298
|
+
These items carry plans you would lose to a silent archive.
|
|
299
|
+
|
|
300
|
+
> 1. Spawn follow-up roadmap as DRAFT
|
|
301
|
+
> → agents/roadmaps/road-to-{auto-slug}.md, status: draft,
|
|
302
|
+
> parent_roadmap: {this-slug}. Hidden from dashboard until you
|
|
303
|
+
> flip status to "ready".
|
|
304
|
+
> 2. Spawn follow-up roadmap as READY (with blocked-until note)
|
|
305
|
+
> → status: ready (default), parent_roadmap: {this-slug}, plus
|
|
306
|
+
> `> Blocked until <condition>` line in body. Visible in
|
|
307
|
+
> dashboard; execution waits on condition.
|
|
308
|
+
> 3. Keep deferred items in this archive — confirm "no follow-up"
|
|
309
|
+
> intentional drop. Items stay searchable in archive/.
|
|
310
|
+
> 4. Restore selected items to [ ] — finish them here before archive.
|
|
311
|
+
> 5. Convert selected items to [-] cancelled — drop with rationale.
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Picks 1 or 2 → see "Spawn follow-up from deferred items" below.
|
|
315
|
+
Picks 3, 4, or 5 → apply the change in this roadmap; re-evaluate
|
|
316
|
+
the decision table; archive when gate clears.
|
|
317
|
+
|
|
318
|
+
### Spawn follow-up from deferred items (procedure)
|
|
319
|
+
|
|
320
|
+
When user picks option 1 or 2 in step 4b:
|
|
321
|
+
|
|
322
|
+
1. **Derive slug.** Default `<parent-slug>-followup` (e.g. `road-to-x.md`
|
|
323
|
+
→ `road-to-x-followup.md`). User-supplied slug in picker → use that.
|
|
324
|
+
Avoid collisions with `agents/roadmaps/` (active + `archive/` + `skipped/`).
|
|
325
|
+
|
|
326
|
+
2. **Write new file** at `agents/roadmaps/<slug>.md`:
|
|
327
|
+
|
|
328
|
+
```markdown
|
|
329
|
+
---
|
|
330
|
+
complexity: lightweight # bump if parent was structural
|
|
331
|
+
status: draft # option 1; omit for option 2 (= ready)
|
|
332
|
+
parent_roadmap: <parent-slug> # back-link to source
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
# Roadmap: Follow-up to <parent-title>
|
|
336
|
+
|
|
337
|
+
> <One sentence stating carried-over outcome.>
|
|
338
|
+
|
|
339
|
+
## Context
|
|
340
|
+
|
|
341
|
+
This roadmap collects items deferred from
|
|
342
|
+
[`agents/roadmaps/archive/<parent-slug>.md`](archive/<parent-slug>.md).
|
|
343
|
+
See parent's archive entry for original rationale.
|
|
344
|
+
|
|
345
|
+
## Prerequisites
|
|
346
|
+
|
|
347
|
+
- [ ] Read `AGENTS.md` and parent archive entry.
|
|
348
|
+
{parent prerequisites still relevant, copied verbatim}
|
|
349
|
+
|
|
350
|
+
<!-- Option 2 only — body note, NOT a frontmatter key: -->
|
|
351
|
+
> Blocked until <condition>. Execution starts when condition clears.
|
|
352
|
+
|
|
353
|
+
## Phase 1: <name carried from parent>
|
|
354
|
+
|
|
355
|
+
- [ ] {deferred step text, copied verbatim with parent-phase pointer}
|
|
356
|
+
{repeat per deferred item, regrouped by parent phase}
|
|
357
|
+
|
|
358
|
+
## Acceptance Criteria
|
|
359
|
+
|
|
360
|
+
- [ ] {restate or adjust per deferred scope}
|
|
361
|
+
- [ ] All quality gates pass — see `quality-tools`.
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
3. **In parent roadmap** (still in working tree), append a line at
|
|
365
|
+
bottom (above any final `---`):
|
|
366
|
+
|
|
367
|
+
```
|
|
368
|
+
<!-- Deferred items migrated to agents/roadmaps/<followup-slug>.md on YYYY-MM-DD -->
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
Do **not** delete `[~]` lines — keep visible in archived parent so
|
|
372
|
+
trail stays grep-able. Follow-up carries forward executable copy.
|
|
373
|
+
|
|
374
|
+
4. **Regenerate dashboard.** Follow-up appears (draft hidden, ready
|
|
375
|
+
visible) and parent — once moved — drops off.
|
|
376
|
+
|
|
377
|
+
5. **Archive parent** (`git mv` → `archive/`) and regen one more time
|
|
378
|
+
per [`roadmap-progress-sync`](../../rules/roadmap-progress-sync.md)
|
|
379
|
+
Iron Laws 1 + 3.
|
|
280
380
|
|
|
281
381
|
5. **Move the file** with `git mv` so history is preserved:
|
|
282
382
|
|
|
@@ -351,7 +451,7 @@ The dashboard is a **read-only snapshot**. Do not edit it by hand — regenerate
|
|
|
351
451
|
- Roadmap files go in `agents/roadmaps/` — don't create them in other directories.
|
|
352
452
|
- Don't mark phases complete without running verification (tests, quality checks) — the verify-before-complete rule applies.
|
|
353
453
|
- The model tends to skip phases it deems "simple" — every phase must be explicitly completed.
|
|
354
|
-
- Auto-archive
|
|
454
|
+
- Auto-archive is allowed when `count_open == 0` AND `count_deferred == 0`. `[-]` cancelled items archive silently (explicit drops). `[~]` deferred items **block** silent archive — they trigger the Iron Law 3 flow (see step 4b).
|
|
355
455
|
- `archive/` and `skipped/` are distinct — `archive/` = work happened, `skipped/` = no meaningful work, not pursuing. Create either directory if it doesn't exist.
|
|
356
456
|
- Use `git mv` (not `mv`) so history follows the file.
|
|
357
457
|
|
|
@@ -99,6 +99,69 @@ phase is done) and **rollback** (what to revert if the phase fails).
|
|
|
99
99
|
A phase without exit criteria is open-ended; a phase without
|
|
100
100
|
rollback assumes success.
|
|
101
101
|
|
|
102
|
+
### 6. Step-marker semantics — pick `[~]` (defer) vs `[-]` (cancel) honestly
|
|
103
|
+
|
|
104
|
+
Difference carries load when authoring (and especially when rewriting
|
|
105
|
+
mid-flight):
|
|
106
|
+
|
|
107
|
+
| Glyph | Semantic | When to use |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| `[~]` | **deferred** — planned, will be done, just not in this roadmap | Scope-cut + clear intent to revisit. Triggers Iron Law 3 follow-up flow before archive — info preservation enforced. |
|
|
110
|
+
| `[-]` | **cancelled** — won't be done at all | Scope rejected, design changed, replaced by another roadmap. Decision final; no follow-up implied. |
|
|
111
|
+
|
|
112
|
+
Optional inline annotations on same line:
|
|
113
|
+
|
|
114
|
+
```markdown
|
|
115
|
+
- [~] Migrate bulk-import job to chunked dispatch. <!-- deferred: ops capacity in Q3 -->
|
|
116
|
+
- [-] Wire SQS retry topic. <!-- cancelled: superseded by Lambda DLQ in road-to-event-bridge -->
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Annotation for next human reader (and for migration procedure when
|
|
120
|
+
[`roadmap-management`](../roadmap-management/SKILL.md) spawns a follow-up).
|
|
121
|
+
Bare `[~]` / `[-]` allowed; annotated preferred.
|
|
122
|
+
|
|
123
|
+
### 7. Follow-up roadmaps spawn from deferred items — frontmatter shape
|
|
124
|
+
|
|
125
|
+
When parent roadmap closes with `[~]` items,
|
|
126
|
+
[`roadmap-management`](../roadmap-management/SKILL.md) skill spawns a
|
|
127
|
+
follow-up. Authors and reviewers must recognise the shape:
|
|
128
|
+
|
|
129
|
+
```markdown
|
|
130
|
+
---
|
|
131
|
+
complexity: lightweight
|
|
132
|
+
status: draft # optional — draft hides from dashboard
|
|
133
|
+
parent_roadmap: <parent-slug> # back-link to archived source
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
# Roadmap: Follow-up to <parent-title>
|
|
137
|
+
|
|
138
|
+
> <One sentence: carried-over outcome.>
|
|
139
|
+
|
|
140
|
+
## Context
|
|
141
|
+
|
|
142
|
+
This roadmap collects items deferred from
|
|
143
|
+
[`agents/roadmaps/archive/<parent-slug>.md`](../archive/<parent-slug>.md).
|
|
144
|
+
{ … original phases preserved verbatim … }
|
|
145
|
+
|
|
146
|
+
<!-- For option 2 (ready + blocked), add as body note, NOT in frontmatter: -->
|
|
147
|
+
> Blocked until <condition>. Execution starts when condition clears.
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Two states author picks between (mirrors Iron Law 3 numbered-options
|
|
151
|
+
block in [`roadmap-progress-sync`](../../rules/roadmap-progress-sync.md)):
|
|
152
|
+
|
|
153
|
+
- **`status: draft`** → hidden from `agents/roadmaps-progress.md` until
|
|
154
|
+
flipped. Use for items user wants captured but not surfaced to
|
|
155
|
+
active backlog yet.
|
|
156
|
+
- **`status: ready` (default; omit key)** plus body `> Blocked until …`
|
|
157
|
+
note → visible in dashboard, execution gated by documented
|
|
158
|
+
condition. Blocking is body convention, not enforced by dashboard
|
|
159
|
+
generator — readers honor the note.
|
|
160
|
+
|
|
161
|
+
Follow-up is **not** authored from scratch — deferred steps copied
|
|
162
|
+
verbatim (with phase context). Preserves plan exactly as author
|
|
163
|
+
originally wrote it.
|
|
164
|
+
|
|
102
165
|
## Output format
|
|
103
166
|
|
|
104
167
|
A single Markdown file at `agents/roadmaps/{name}.md`:
|