@event4u/agent-config 8.7.0 → 8.9.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 (171) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +109 -222
  3. package/CONTRIBUTING.md +25 -0
  4. package/README.md +7 -4
  5. package/dist/agent-src/commands/agent-handoff.md +39 -2
  6. package/dist/agent-src/commands/research/deep.md +8 -0
  7. package/dist/agent-src/commands/research/report.md +7 -0
  8. package/dist/agent-src/commands/roadmap/create.md +12 -0
  9. package/dist/agent-src/commands/roadmap/process-full.md +31 -5
  10. package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +30 -1
  11. package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +1 -1
  12. package/dist/agent-src/contexts/execution/orchestration-benchmark-gate.md +28 -16
  13. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +36 -5
  14. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +37 -0
  15. package/dist/agent-src/contexts/execution/subagent-topologies.md +34 -0
  16. package/dist/agent-src/contexts/execution/verification-mechanics.md +9 -9
  17. package/dist/agent-src/rules/active-remediation.md +92 -0
  18. package/dist/agent-src/rules/agent-authority.md +1 -1
  19. package/dist/agent-src/rules/broken-access-control.md +106 -0
  20. package/dist/agent-src/rules/communication-through-line.md +42 -0
  21. package/dist/agent-src/rules/decision-revisit-gate.md +8 -0
  22. package/dist/agent-src/rules/delegation-policy.md +5 -0
  23. package/dist/agent-src/rules/direct-answers.md +1 -1
  24. package/dist/agent-src/rules/downstream-changes.md +1 -0
  25. package/dist/agent-src/rules/external-code-graph-interop.md +65 -0
  26. package/dist/agent-src/rules/git-history-discipline.md +18 -0
  27. package/dist/agent-src/rules/lethal-trifecta-guard.md +6 -1
  28. package/dist/agent-src/rules/minimal-safe-diff.md +66 -1
  29. package/dist/agent-src/rules/non-destructive-by-default.md +3 -0
  30. package/dist/agent-src/rules/prefer-enums-over-literals.md +65 -0
  31. package/dist/agent-src/rules/question-not-instruction.md +76 -0
  32. package/dist/agent-src/rules/senior-engineering-discipline.md +82 -0
  33. package/dist/agent-src/rules/think-before-action.md +1 -0
  34. package/dist/agent-src/rules/tool-safety.md +8 -0
  35. package/dist/agent-src/rules/untrusted-input-defense.md +87 -22
  36. package/dist/agent-src/scripts/update_roadmap_progress.ts +2 -1
  37. package/dist/agent-src/skills/accessibility-auditor/SKILL.md +19 -0
  38. package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +112 -0
  39. package/dist/agent-src/skills/ai-code-blindspots/evals/triggers.json +52 -0
  40. package/dist/agent-src/skills/authz-review/SKILL.md +21 -4
  41. package/dist/agent-src/skills/code-review/SKILL.md +2 -0
  42. package/dist/agent-src/skills/command-writing/SKILL.md +53 -40
  43. package/dist/agent-src/skills/dcf-modeling/evals/domain-truth.json +29 -0
  44. package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +1 -0
  45. package/dist/agent-src/skills/dependency-upgrade/SKILL.md +20 -0
  46. package/dist/agent-src/skills/design-intelligence/SKILL.md +49 -12
  47. package/dist/agent-src/skills/design-review/SKILL.md +29 -15
  48. package/dist/agent-src/skills/design-system-capture/SKILL.md +63 -24
  49. package/dist/agent-src/skills/forecasting/evals/domain-truth.json +29 -0
  50. package/dist/agent-src/skills/frontend-render-security/SKILL.md +104 -0
  51. package/dist/agent-src/skills/frontend-render-security/evals/triggers.json +52 -0
  52. package/dist/agent-src/skills/markitdown/SKILL.md +1 -0
  53. package/dist/agent-src/skills/mcp/SKILL.md +24 -0
  54. package/dist/agent-src/skills/mcp-builder/SKILL.md +9 -1
  55. package/dist/agent-src/skills/memory-consolidation/SKILL.md +55 -4
  56. package/dist/agent-src/skills/roadmap-writing/SKILL.md +46 -5
  57. package/dist/agent-src/skills/runway-cognition/evals/domain-truth.json +29 -0
  58. package/dist/agent-src/skills/scenario-modeling/evals/domain-truth.json +29 -0
  59. package/dist/agent-src/skills/secrets-management/SKILL.md +7 -0
  60. package/dist/agent-src/skills/skill-writing/SKILL.md +12 -3
  61. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +27 -33
  62. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +112 -0
  63. package/dist/agent-src/skills/supply-chain-intake/evals/triggers.json +52 -0
  64. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +72 -2
  65. package/dist/agent-src/skills/ui-component-architect/SKILL.md +9 -0
  66. package/dist/agent-src/skills/unit-economics-modeling/evals/domain-truth.json +40 -0
  67. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  68. package/dist/agent-src/templates/roadmaps.md +60 -0
  69. package/dist/cli/registry.js +3 -0
  70. package/dist/cli/registry.js.map +1 -1
  71. package/dist/discovery/deprecation-report.md +1 -1
  72. package/dist/discovery/discovery-manifest.json +268 -46
  73. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  74. package/dist/discovery/discovery-manifest.summary.md +4 -4
  75. package/dist/discovery/orphan-report.md +1 -1
  76. package/dist/discovery/packs.json +18 -8
  77. package/dist/discovery/trust-report.md +11 -11
  78. package/dist/discovery/workspaces.json +16 -6
  79. package/dist/install/install.mjs +141 -3
  80. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  81. package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
  82. package/dist/mcp/registry-manifest.json +4 -4
  83. package/dist/router.json +1 -1
  84. package/dist/scripts/_lib/claude_builtin_names.js +145 -0
  85. package/dist/scripts/_lib/claude_builtin_names.js.map +1 -0
  86. package/dist/scripts/condense.js +14 -0
  87. package/dist/scripts/condense.js.map +1 -1
  88. package/dist/server/schemas/settings.js +2 -1
  89. package/dist/server/schemas/settings.js.map +1 -1
  90. package/docs/CLAIMS.md +58 -2
  91. package/docs/architecture.md +3 -3
  92. package/docs/archive/CHANGELOG-pre-8.9.0.md +306 -0
  93. package/docs/benchmark.md +113 -0
  94. package/docs/catalog.md +32 -5
  95. package/docs/contracts/command-clusters.md +18 -0
  96. package/docs/contracts/design-artifact-verification.md +124 -0
  97. package/docs/contracts/injected-block-authenticity-model.md +66 -0
  98. package/docs/contracts/mcp-tool-inventory.md +31 -30
  99. package/docs/decisions/ADR-061-corpus-grounding-layer.md +13 -0
  100. package/docs/decisions/ADR-105-automatic-subagent-orchestration.md +6 -0
  101. package/docs/decisions/ADR-116-memory-tripwire-activation-path.md +11 -2
  102. package/docs/decisions/ADR-117-subagents-auto-default-on.md +88 -0
  103. package/docs/decisions/INDEX.md +1 -0
  104. package/docs/experiences/content_creator.md +2 -0
  105. package/docs/experiences/finance.md +2 -0
  106. package/docs/experiences/founder.md +2 -0
  107. package/docs/experiences/ops.md +2 -0
  108. package/docs/featured-skills.md +2 -2
  109. package/docs/getting-started-by-role.md +1 -1
  110. package/docs/getting-started.md +1 -1
  111. package/docs/governance-advantage.md +1 -1
  112. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +27 -0
  113. package/docs/guidelines/agent-infra/emphasis-budget.md +45 -0
  114. package/docs/guidelines/agent-infra/memory-access.md +12 -0
  115. package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +151 -0
  116. package/docs/guidelines/agent-infra/tool-description-as-policy.md +35 -0
  117. package/docs/guidelines/design-canon.md +1 -0
  118. package/docs/proof.md +60 -3
  119. package/docs/release-runbook.md +138 -0
  120. package/docs/second-brain-scope.md +116 -0
  121. package/docs/succession.md +80 -0
  122. package/package.json +2 -2
  123. package/src/agent-src/scripts/update_roadmap_progress.ts +2 -1
  124. package/src/config/agent-settings.template.yml +25 -6
  125. package/src/scripts/_dispatch.bash +27 -0
  126. package/src/scripts/_lib/claude_builtin_names.ts +148 -0
  127. package/src/scripts/_lib/file_slicer.ts +117 -0
  128. package/src/scripts/_lib/lexical_index.ts +155 -0
  129. package/src/scripts/_lib/orchestration_gate.ts +12 -8
  130. package/src/scripts/_lib/orchestration_record.ts +170 -0
  131. package/src/scripts/_lib/orchestration_savings.ts +180 -0
  132. package/src/scripts/_lib/retrieval_sanitize.ts +71 -0
  133. package/src/scripts/_lib/security_lint.ts +1 -0
  134. package/src/scripts/_lib/stat_index.ts +98 -0
  135. package/src/scripts/benchmark.ts +122 -0
  136. package/src/scripts/build_proof.ts +51 -0
  137. package/src/scripts/chat_history.ts +79 -7
  138. package/src/scripts/check_memory.ts +2 -0
  139. package/src/scripts/check_quality_regression.ts +51 -0
  140. package/src/scripts/check_roadmap_trackable.ts +3 -2
  141. package/src/scripts/condense.ts +14 -0
  142. package/src/scripts/discovery_graph.ts +0 -0
  143. package/src/scripts/domain_soundness_status.ts +236 -0
  144. package/src/scripts/external_sources_denylist.json +4 -1
  145. package/src/scripts/generate_index.ts +17 -0
  146. package/src/scripts/hot_context_hook.ts +47 -2
  147. package/src/scripts/install-hooks.sh +25 -0
  148. package/src/scripts/install.ts +35 -2
  149. package/src/scripts/learning_sidecar.ts +0 -0
  150. package/src/scripts/lint_agent_skill_names.ts +29 -0
  151. package/src/scripts/lint_behavioural_eval_freshness.ts +140 -0
  152. package/src/scripts/lint_knowledge_scale.ts +4 -3
  153. package/src/scripts/lint_roadmap_complexity.ts +124 -0
  154. package/src/scripts/lint_versioned_cache.ts +195 -0
  155. package/src/scripts/mcp_server/consumer_tool_catalog.json +23 -3
  156. package/src/scripts/mcp_server/tools.ts +182 -1
  157. package/src/scripts/measure_lexical_ranking.ts +173 -0
  158. package/src/scripts/memory_lookup.ts +0 -0
  159. package/src/scripts/memory_replay.ts +285 -0
  160. package/src/scripts/orchestration_record.ts +140 -0
  161. package/src/scripts/orchestration_savings_report.ts +124 -0
  162. package/src/scripts/schemas/domain-truth.schema.json +94 -0
  163. package/src/scripts/schemas/evals.schema.json +113 -0
  164. package/src/scripts/schemas/skill.schema.json +4 -0
  165. package/src/scripts/score_domain_truth.ts +192 -0
  166. package/src/scripts/second_brain_retrieval.ts +278 -0
  167. package/src/scripts/second_brain_run.ts +341 -0
  168. package/src/scripts/second_brain_score.ts +186 -0
  169. package/src/scripts/session_memory_index.ts +94 -0
  170. package/src/scripts/skill_eval_coverage.ts +318 -0
  171. package/src/server/schemas/settings.ts +5 -2
@@ -232,6 +232,18 @@ Write the pick to frontmatter as `execution.mode:`
232
232
  and expensive as a mid-run ambiguity halt; pre-existing `[~]` items
233
233
  guarantee the archival gate interrupts the run.
234
234
  `lint_roadmap_complexity` warns on the same patterns as a backstop.
235
+ - **Human-gate scan (ALL picks):** scan drafted steps for human-gate
236
+ patterns (`user verifies/reviews/approves`, `manually check`,
237
+ `sign-off`, `wait for approval`, `ask the user`, "Review / Sign-off"
238
+ phases). Human checkpoints default to **zero** (template rule 22) —
239
+ rewrite each hit as agent-verifiable check (command, targeted test)
240
+ **before saving**, or promote to structured `## Blockers` entry:
241
+ **human gate** only when only a human can decide/authorize
242
+ (Hard-Floor authorization, billable spend, contested decision);
243
+ **external dependency** becomes a blocker whose `Resolved when:`
244
+ names an agent-checkable status probe — never a human gate. Do not
245
+ author safety floors as steps — they fire at run time on their own.
246
+ `lint_roadmap_complexity` warns on the same patterns as a backstop.
235
247
 
236
248
  ### 11. Hand back — HARD STOP, never auto-offer execution
237
249
 
@@ -57,7 +57,11 @@ with the **scope delta below**.
57
57
  (`false` / missing) the pipeline never runs locally; remote CI is
58
58
  the gate. On red → stop, surface, do **not** silently roll into
59
59
  the next phase. Under `mode: phase-checkpoints`, additionally emit
60
- the compact status + continue prompt at every boundary; under
60
+ a compact status LINE at every boundary — but under `process-full`
61
+ this is a NON-BLOCKING status, NOT a stop-and-wait: the run continues
62
+ to the next phase immediately. `phase-checkpoints` narrows to a
63
+ stop-and-wait only under `/roadmap:process-phase`, never here (a
64
+ process-full invocation overrides the mode's boundary-wait). Under
61
65
  `autonomous`, boundaries are silent (quality pipeline aside).
62
66
  - **Final archival:** when the roadmap is fully closed, run the
63
67
  archival check from
@@ -66,10 +70,32 @@ with the **scope delta below**.
66
70
  ## Iron Law — Full is Full
67
71
 
68
72
  ```
69
- /roadmap:process-full PROCESSES EVERY OPEN STEP IN THE FILE.
70
- PHASE-INTERNAL "(DEFERRED)" / "(OPTIONAL)" / "GATED ON PHASE X"
71
- NOTES DO NOT NARROW THE WORKING SET. ONLY THE FIVE HALT CONDITIONS
72
- STOP THE RUN.
73
+ /roadmap:process-full IS LAW: IT PROCESSES EVERY OPEN STEP IN THE FILE,
74
+ TO COMPLETION, ACROSS EVERY PHASE. ONLY THE FIVE HALT CONDITIONS STOP IT.
75
+ PHASE-INTERNAL "(DEFERRED)" / "(OPTIONAL)" / "GATED ON PHASE X" NOTES DO
76
+ NOT NARROW THE WORKING SET. A PHASE BOUNDARY IS NOT A STOP.
77
+ ```
78
+
79
+ The **five — and only five — halt conditions** (exhaustive; nothing else
80
+ stops the run):
81
+
82
+ 1. **Hard-Floor** trigger ([`non-destructive-by-default`](../../rules/non-destructive-by-default.md)).
83
+ 2. **Council-off + genuine ambiguity** (only outside an accepted contract with council available).
84
+ 3. **Security-sensitive** surface reached.
85
+ 4. **Scope-out-of-roadmap** work discovered.
86
+ 5. **Test / quality red** that cannot be cleared within the N=3 budget.
87
+
88
+ ```
89
+ FORBIDDEN NON-HALT REASONS — NEVER STOP THE RUN FOR ANY OF THESE:
90
+ · "running low on context / token budget"
91
+ · "quality would degrade / deserves a fresh focused run later"
92
+ · "avoid a PR pile-up" / "let the open PRs merge first"
93
+ · "this phase is large / touches a deep subsystem"
94
+ · "phase-checkpoints mode, so I'll checkpoint and wait"
95
+ · any agent-invented caution not in the five halt conditions above.
96
+ INVENTING A HALT REASON IS A VIOLATION OF THE COMMAND AND THE USER'S WILL.
97
+ IF CONTEXT RUNS OUT MID-RUN, KEEP LANDING COMPLETE STEPS UNTIL IT DOES —
98
+ NEVER ANNOUNCE A BOUNDARY-STOP BY CHOICE.
73
99
  ```
74
100
 
75
101
  Phase-internal `(deferred)` / `(optional)` / `gated on Phase N` tags are
@@ -43,7 +43,7 @@ behavior. Cannot → read more.
43
43
  ## Consult memory before editing
44
44
 
45
45
  Invariants live in the memory layer; architectural rationale lives in ADRs.
46
- Via [`memory-access`](../../../../../docs/guidelines/agent-infra/memory-access.md),
46
+ Via [`memory-access`](../../../../../../docs/guidelines/agent-infra/memory-access.md),
47
47
  call `retrieve(types=["domain-invariants"], keys=<touched paths>, limit=3)` —
48
48
  a matching `domain-invariant` is a hard constraint. For *why* the current
49
49
  shape exists, check the ADR index `docs/decisions/INDEX.md`. Cite the `id` /
@@ -96,3 +96,32 @@ context only — does NOT mean the user's message is about that file.
96
96
  - Treat the open file as relevant only when the user's message
97
97
  explicitly references it (e.g. "fix this file", "what does this
98
98
  do?", "update the open file").
99
+
100
+ ## Goal-driven execution — vague ask → verifiable goal
101
+
102
+ Before executing a multi-step task, transform it into criteria a tool can
103
+ check. Strong criteria let the loop run independently; weak criteria ("make it
104
+ work") guarantee rework.
105
+
106
+ | Vague ask | Verifiable goal |
107
+ |---|---|
108
+ | "Add validation" | Write tests for the invalid inputs, then make them pass |
109
+ | "Fix the bug" | Write a test that reproduces it (fails), then make it pass |
110
+ | "Refactor X" | Tests green before AND after; diff shows no behavior change |
111
+ | "Make it faster" | Name the metric + target (p95 < 200ms); measure before/after |
112
+ | "Clean this up" | Clarification trigger — no checkable success state exists yet |
113
+
114
+ For multi-step tasks, state the plan with a verify per step:
115
+
116
+ ```
117
+ 1. [step] → verify: [check]
118
+ 2. [step] → verify: [check]
119
+ 3. [step] → verify: [check]
120
+ ```
121
+
122
+ A step without a `verify:` is not a step — it is an assumption. A task whose
123
+ success cannot be checked is a clarification trigger, not an execution
124
+ trigger (route to `ask-when-uncertain`).
125
+
126
+ Wrong/right demos:
127
+ [`simplicity-and-goal-demos`](../../../../../../docs/guidelines/agent-infra/simplicity-and-goal-demos.md).
@@ -12,7 +12,7 @@ whether dispatch is physically possible on the host).
12
12
  | Key | Default | Purpose |
13
13
  |---|---|---|
14
14
  | `subagents.enabled` | `true` | Global master switch. `false` = the whole layer is off — the canonical kill-switch. No auto-dispatch, no routing, everything runs in-session. |
15
- | `subagents.auto` | `ask` | Auto-dispatch mode: `off` \| `ask` \| `on`. |
15
+ | `subagents.auto` | `on` | Auto-dispatch mode: `off` \| `ask` \| `on`. Default `on` on subagent-capable hosts (flipped from `ask` 2026-07-09, ADR-117), `off` elsewhere. |
16
16
  | `subagents.downshift` | `true` | Route delegable sub-tasks to the lowest-capable tier (Phase 2). |
17
17
  | `subagents.quota_arbitrage` | `true` | Prefer a separate-quota-pool model where the host manifest allows it (Phase 2 bonus). |
18
18
  | `subagents.model_map` | `{}` | Optional per-tier model override for downshift routing. |
@@ -1,9 +1,19 @@
1
- # Orchestration Benchmark & Default-Flip Gate (Phase 6)
2
-
3
- The falsification gate the whole auto-orchestration roadmap is built around.
4
- Reaching the user's "default `on`" is a **measured milestone**, not an
5
- assumption: the shipped default for `subagents.auto` flips toward `on` only
6
- when a real benchmark proves a net win at held quality.
1
+ # Orchestration Benchmark & Demotion Gate (Phase 6 → telemetry-demotion)
2
+
3
+ Originally the falsification gate the auto-orchestration roadmap was built
4
+ around: shipped default for `subagents.auto` would flip toward `on` only on a
5
+ benchmark proving a net win at held quality.
6
+
7
+ **As of 2026-07-09 the shipped default IS `on`** on subagent-capable hosts
8
+ (ADR-117; [`orchestration-default-flip-verdict`](../../../../agents/settings/contexts/orchestration-default-flip-verdict.md)
9
+ § 2026-07-09). Flipped on a **bounded-downside re-evaluation**, not a passed
10
+ benchmark: rigorous paired bench:ab not producible here (no runtime executing
11
+ model `Task`/`Agent` calls), win-validation deadlocked (telemetry needs `on`,
12
+ `on` gated on telemetry). Re-eval broke the deadlock — downside of `on` is
13
+ structurally small (delegable slices cost-routed to cheapest tier,
14
+ classification fires only on real structural signals, every return verified) →
15
+ `on` gathers realized telemetry responsibly. This gate now governs
16
+ **demotion**: measured regression flips default back to `ask`.
7
17
 
8
18
  ## Measurement — pin the method
9
19
 
@@ -30,18 +40,20 @@ HONEST-NULL EXIT: no win, or quality regressed → KEEP the conservative default
30
40
 
31
41
  `gateVerdict()` encodes pass = `net_win && quality_held`.
32
42
 
33
- ## Default flip — one line, host-gated
43
+ ## Default state + demotion — host-gated
34
44
 
35
- On a **passing** gate, the shipped default for `subagents.auto` becomes `on`
36
- **only** on hosts whose capability manifest reports `subagent_spawn: true`
37
- (`off` elsewhere). `resolveShippedDefault()` encodes this. The flip itself is a
38
- one-line edit to the `subagents.auto` default in
39
- `src/config/agent-settings.template.yml` — no code change, host-gated by the
40
- manifest at runtime.
45
+ Shipped default for `subagents.auto` is `on` on hosts whose manifest reports
46
+ `subagent_spawn: true` (`off` elsewhere) — set directly in
47
+ `src/config/agent-settings.template.yml`. `resolveShippedDefault()` remains the
48
+ host-gated resolver, now serving **demotion**: fed a `fail` verdict from
49
+ accumulated real-world orchestration telemetry, resolves back to `ask`
50
+ (conservative). A `pass` keeps `on`. Demotion path is a one-line edit,
51
+ host-gated by the manifest at runtime.
41
52
 
42
- Until the gate passes, the shipped default stays `ask` (conservative). This is
43
- the reconciliation of the user's "default on" goal with the council's
44
- "prove-first": `on` is the destination, reached by evidence, not assumed.
53
+ The 2026-07-09 flip reconciles the user's "default on" goal with the council's
54
+ "prove-first": rather than wait on a benchmark that cannot be produced here,
55
+ `on` ships because its downside is bounded and reversible, and realized
56
+ telemetry is now free to accrue and drive demotion if it regresses.
45
57
 
46
58
  ## Reproducibility
47
59
 
@@ -23,6 +23,8 @@ v1 forward-compat rule on unknown fields).
23
23
  "task_class": null,
24
24
  "tier_chosen": null,
25
25
  "tier_source": null,
26
+ "dispatch_tokens": null,
27
+ "session_tier": null,
26
28
  "escalated_from": null,
27
29
  "verify_result_by_tier": null
28
30
  }
@@ -46,8 +48,10 @@ v1 forward-compat rule on unknown fields).
46
48
  | `tier_source` | enum \| null | Where `tier_chosen` came from: `static` (frontmatter/category pin) · `inferred` (deterministic per-slice inference) · `inherit` (session tier — no downshift decision). Lets the evidence gate score inferred routing separately from static pinning. |
47
49
  | `escalated_from` | string \| null | When the slice re-dispatched after a verification failure: tier of the FAILED attempt (e.g. `lite` when a lite return failed verify and the slice re-ran on `medium`). `null` = no escalation. |
48
50
  | `verify_result_by_tier` | object \| null | Map tier → verification result per attempt of this slice (e.g. `{"lite":"fail","medium":"pass"}`). Values: `pass` \| `fail` \| `skipped`. Feeds the per-tier verify-pass-rate tripwire. Enums only, no verdict bodies. |
51
+ | `dispatch_tokens` | int \| null | **Cost-% extension.** Absolute tokens the dispatched slice consumed (measured subagent usage). Feeds the MODELED cost-% in `orchestration_savings_report`, which needs an absolute base the token-count delta lacks. `null` = not recorded. Counts only. |
52
+ | `session_tier` | string \| null | **Cost-% extension.** The orchestrator's OWN tier — the baseline the downshift cost-% measures `tier_chosen` against (a `high`→`lite` downshift is a rate win the token count can't see). `null` = not recorded. |
49
53
 
50
- All five routing fields are additive and optional — a line without them is
54
+ These routing + cost fields are additive and optional — a line without them is
51
55
  still a valid orchestration line; readers ignore unknown fields per the v1
52
56
  forward-compat rule.
53
57
 
@@ -74,10 +78,22 @@ audit-log-v1 path; `YYYY-MM` = current UTC month). The line is a standard
74
78
  audit-log-v1 object with `input_kind: "orchestration"` and an `orchestration`
75
79
  sub-object carrying this shape.
76
80
 
77
- **No hook or daemon required.** The agent writes directly via its file-write
78
- tool — same mechanism as any other agent-written artifact. No-runtime-compatible
79
- capture path (decided 2026-06-30, maintainer decision; see
80
- `road-to-subagent-value-realization.md § Council notes`).
81
+ **No hook or daemon required.** The agent writes the line directly —
82
+ no-runtime-compatible capture path (decided 2026-06-30, maintainer decision; see
83
+ `road-to-subagent-value-realization.md § Council notes`). Do NOT hand-author the
84
+ JSON: run the recorder, which validates + builds a conformant line from the
85
+ counts you already have:
86
+
87
+ ```bash
88
+ ./scripts-run src/scripts/orchestration_record --spawn-count <n> \
89
+ --token-delta <±n> --provenance measured|estimated \
90
+ [--tier-chosen lite|medium|high] [--tier-source static|inferred|inherit] \
91
+ [--task-class <id>] [--tiers a,b] [--dispatch-outcome DONE|BLOCKED|…]
92
+ ```
93
+
94
+ A capture **hook** is the wrong tool: the PostToolUse payload carries no subagent
95
+ token usage (only the orchestrator sees it) and a hook reverses the 2026-06-30
96
+ no-hook decision. Reader: `src/scripts/orchestration_savings_report.ts`.
81
97
 
82
98
  **`token_delta` sourcing priority:**
83
99
  1. Host-reported: read `usage.output_tokens` (and `usage.input_tokens` if
@@ -87,6 +103,21 @@ capture path (decided 2026-06-30, maintainer decision; see
87
103
  response length (chars / 4 ≈ tokens). Set `token_delta_provenance:
88
104
  "estimated"`. Lossy; measured always preferred.
89
105
 
106
+ ## Savings report
107
+
108
+ Aggregate accumulated telemetry into a token-savings report:
109
+
110
+ ```bash
111
+ ./scripts-run src/scripts/orchestration_savings_report [--dir <path>] [--format text|json]
112
+ ```
113
+
114
+ Sums `token_delta` across dispatches (negative = net saved); splits by
115
+ provenance (measured vs estimated), `tier_chosen`, `task_class`. Reports
116
+ **ABSOLUTE net tokens saved, never a percentage**: telemetry records net delta,
117
+ not the absolute in-session baseline → "% of session saved" not derivable. A
118
+ percentage needs an additive absolute-baseline field (deferred follow-up).
119
+ Reader: [`src/scripts/_lib/orchestration_savings.ts`](../../../../src/scripts/_lib/orchestration_savings.ts).
120
+
90
121
  ## Related
91
122
 
92
123
  - [`audit-log-v1`](../../../../docs/contracts/audit-log-v1.md) — the frozen
@@ -28,6 +28,25 @@ roadmaps with open work that is blocked-for-later — parked, not active).
28
28
  surface alternatives in the pre-run summary.
29
29
  - None active → tell the user; suggest [`/roadmap:create`](../../commands/roadmap/create.md).
30
30
 
31
+ ### Live merge-state before any "in-flight / merged / handled" claim
32
+
33
+ Selection reasoning that **excludes** a roadmap — or a pre-run summary,
34
+ decision, or user-facing message that **describes** one — as *in-flight*,
35
+ *handled by an open PR*, *already merged*, or *not yet merged* → verify **live
36
+ at claim time** (`gh pr view <n> --json state,mergedAt` / `gh pr list --search
37
+ "<slug>"`). Never infer merge state from:
38
+
39
+ - **dashboard open-count** — lags: a completed roadmap archives in the
40
+ **merging** PR, so it can read "open" on `main` while its PR is already
41
+ merged, or read "open" seconds before a merge you never re-checked;
42
+ - **session memory** ("opened a PR for this earlier") or an **earlier fetch** —
43
+ a merge can land between fetch and message.
44
+
45
+ Stale merge-state claim ships an unnecessary message about work already done —
46
+ the failure this prevents. The [`direct-answers`](../../rules/direct-answers.md)
47
+ Iron-Law-2 live-state rule (git/PR state never from memory), applied to
48
+ roadmap selection.
49
+
31
50
  ## 2. Pre-run summary — gate or inline note
32
51
 
33
52
  Read `roadmap.skip_pre_run_gate` from `.agent-settings.yml` (default
@@ -259,6 +278,24 @@ drafting, council enablement), not safety.
259
278
 
260
279
  On halt: stop, surface state, do **not** auto-fix outside the failing step.
261
280
 
281
+ ### Forbidden non-halt reasons — agent-invented cautions
282
+
283
+ Halt list above is exhaustive. Never stop a `process-full` (or any wrapper) run
284
+ for an invented reason not on it. NOT halt conditions — stopping for them
285
+ violates the command + user's will:
286
+
287
+ - "low context / token budget" — keep landing complete steps until context
288
+ actually runs out; never announce a boundary-stop by choice.
289
+ - "quality would degrade / deserves a fresh focused run later"
290
+ - "avoid a PR pile-up" / "let open PRs merge first"
291
+ - "this phase is large / deep subsystem"
292
+ - "phase-checkpoints, so I'll checkpoint and wait" — under `process-full` a
293
+ phase boundary emits a non-blocking status line and the run continues; the
294
+ stop-and-wait reading applies only to `process-phase`.
295
+
296
+ Genuine inability to continue = one of the five real halt conditions fired —
297
+ surface THAT, not a manufactured caution.
298
+
262
299
  ### Non-halt — gating notes, "optional" tags
263
300
 
264
301
  The following are **authoring annotations**, never halt conditions. Do
@@ -0,0 +1,34 @@
1
+ # Subagent Topologies — per-mode communication shape
2
+
3
+ Descriptive, not enforced. Documents the **expected agent-to-agent
4
+ communication topology** for each [`subagent-orchestration`](../../skills/subagent-orchestration/SKILL.md)
5
+ mode so consumers can predict latency, failure modes, and where consensus
6
+ is required. Cited from
7
+ an internal findings note (local-only) <!-- council-ref-allowed: ADR decision trace for topology anti-drift defaults -->
8
+ row 7 (the external runtime's `hierarchical, 6–8 agents, raft consensus` anti-drift
9
+ default).
10
+
11
+ | Mode | Topology | Anti-drift default | Notes |
12
+ |---|---|---|---|
13
+ | do-and-judge | `hierarchical` | 1 implementer · 1 judge · session-orchestrated | Two-node hub-and-spoke; orchestrator owns the loop. |
14
+ | do-and-judge-two-stage | `hierarchical` | 1 implementer · 2 sequential judges | Stages are serialized; spec-judge gates quality-judge. |
15
+ | do-in-steps | `ring` | N steps · 1 judge between each | Step N output → judge → step N+1 input; cycle on revise. |
16
+ | do-in-parallel | `star` | 6–8 implementers · 1 judge · session-hub | Capped by `subagents.max_parallel`; judge runs once on union. |
17
+ | do-competitively | `mesh` | 2–4 implementers · 1 judge | Implementers do not see each other; judge sees all candidates. |
18
+ | judge-with-debate | `hierarchical-mesh` | 2 judges · 1 meta-judge | Judges debate (mesh edge); meta-judge reconciles (hierarchical). |
19
+ | do-in-worktrees | `adaptive` | per-step topology of the underlying mode | Each worktree picks its own shape; chain is hierarchical. |
20
+
21
+ **Anti-drift default** (the external runtime convention, descriptive only):
22
+ `hierarchical, 6–8 agents, raft consensus`. Consumers free to
23
+ override per orchestration — the table is the **starting point**,
24
+ not a constraint. Topology is metadata for capacity planning, not
25
+ runtime-enforced.
26
+
27
+ **Glossary:**
28
+
29
+ - `hierarchical` — orchestrator hub; agents reply to hub only.
30
+ - `mesh` — agents see each other's outputs (e.g. competing diffs).
31
+ - `hierarchical-mesh` — peer debate followed by hub reconciliation.
32
+ - `ring` — output of step N feeds input of step N+1 in order.
33
+ - `star` — N agents fan out from a single hub; no peer comms.
34
+ - `adaptive` — topology shifts per step; outer chain remains hub.
@@ -11,15 +11,15 @@ incidents.
11
11
 
12
12
  ## Gate zero — `quality.local_auto_run` (default `false`)
13
13
 
14
- `false` or missing → **never run quality tools or full test suites
15
- proactively — never ask**. User runs them manually; **remote CI is the
16
- authoritative gate.** Run one ONLY on: (1) explicit ask this turn,
17
- (2) concrete CI failure — run exactly that failing check, (3) new-gate
18
- carve-out (a NEW gate/test this change introduces runs once to be
19
- proven). Completion wording: *"quality gates delegated to remote CI"* —
20
- never a pass claim for tools that did not run. Narrow probes proving
21
- the specific change (one `--filter` test, `curl`, syntax check on the
22
- edited file) stay allowed. Everything below applies when `true`.
14
+ `false`/missing → **never run the full quality pipeline or full test
15
+ suites proactively — never ask**; remote CI is the gate. Run one ONLY on:
16
+ (1) explicit ask this turn, (2) concrete CI failure — run exactly that
17
+ check, (3) new-gate carve-out (a NEW gate/test this change adds, run once).
18
+ Completion wording: *"quality gates delegated to remote CI"* — never a pass
19
+ claim for tools that did not run. Narrow probes stay allowed (one `--filter`
20
+ test, `curl`); a type-check + lint **scoped to the changed files** is
21
+ REQUIRED before a source push/PR — NOT the full pipeline. Everything below
22
+ applies when `true`.
23
23
 
24
24
  ## When to run what — timing matters (`local_auto_run: true`)
25
25
 
@@ -0,0 +1,92 @@
1
+ ---
2
+ type: "auto"
3
+ tier: "2b"
4
+ alwaysApply: false
5
+ description: "Spotted an issue while working (security gap, missing test, bad code, duplication, stale idiom) — never ignore; fix small+aligned inline, ask on bigger, propose a follow-up PR for many"
6
+ triggers:
7
+ - intent: "spotted an unrelated issue while working"
8
+ - intent: "found legacy or duplicated code"
9
+ - keyword: "refactor"
10
+ - keyword: "duplicate"
11
+ - keyword: "legacy"
12
+ - keyword: "deprecated"
13
+ - keyword: "modernize"
14
+ - keyword: "upgrade"
15
+ - keyword: "cleanup"
16
+ - keyword: "technical debt"
17
+ workspaces: [engineering]
18
+ packs: [engineering-base]
19
+ ---
20
+
21
+ # Active Remediation
22
+
23
+ The user doesn't see the code at the spot you're editing — you do. So this package guides the agent to **actively improve** what it touches: don't accept legacy, debt, security gaps, or duplication as given. But active improvement is bounded — never the scope creep `minimal-safe-diff` exists to stop. The rule is a **ladder**: act by size and alignment, and **never silently ignore** a real issue.
24
+
25
+ ## The Iron Law
26
+
27
+ ```
28
+ NEVER IGNORE A REAL ISSUE YOU SPOT — AT MINIMUM, NOTE IT.
29
+ SMALL + TASK-ALIGNED → FIX IT NOW, IN THE SAME CHANGE, WITH ITS TEST.
30
+ BIGGER OR DIVERGENT → NOTE IT, FINISH THE TASK, THEN ASK — NEVER MID-FLOW.
31
+ TOO MANY → PROPOSE ONE OR MORE SEPARATE FOLLOW-UP PRs THE USER REVIEWS.
32
+ A LIVE SECURITY / DATA-EXPOSURE GAP IS NEVER MERELY "NOTED FOR LATER".
33
+ ```
34
+
35
+ ## What to remediate
36
+
37
+ Security gaps (broken access control, injection, secrets, missing authz — see `broken-access-control`) · missing/weak test coverage · bad code (dead code, silent error-swallow, unguarded edge cases) · **duplication** (same/near-same logic repeated instead of one method/abstraction) · **stale version-idioms** (code for an older language/framework version than the project runs).
38
+
39
+ ## The ladder — classify, then act
40
+
41
+ ### Fix now (autonomous, inline) — a bounded amendment to `minimal-safe-diff`
42
+
43
+ Allowed **only** when ALL hold — the testable "small + task-aligned" definition:
44
+ - **Same request path / module** as the current task (not an unrelated feature).
45
+ - **≤ ~10 changed lines** in one production file plus its test file — no wider cross-file ripple.
46
+ - **No public-API / response-shape change**, no new parameter.
47
+ - **No dependency bump, no migration, no data change.**
48
+ - **Its verification ships in the same commit** — the security fix's negative test, the correctness fix's case.
49
+
50
+ Under those constraints the fix is auditable in the same diff and is *not* scope creep — it corrects a boundary the agent touched. Anything outside them → **note + ask**, never auto. (`minimal-safe-diff` still governs the rest: no reformatting, no opportunistic refactor, no drive-by rename.)
51
+
52
+ ### Note + ask (batched)
53
+
54
+ Bigger, or diverges from the task → do **not** refactor inline, do **not** interrupt the flow. Note the site (file:line + issue). Surface the batch as **one** numbered-options prompt (`user-interaction`, one recommendation line) **after the task is delivered** — or mid-work only when the flow makes it natural. Each option carries a real trade-off (`no-cheap-questions`). Refactor only on an explicit yes, as a separate scoped change (`scope-control`, `downstream-changes`).
55
+
56
+ ### Propose a follow-up PR (many spots)
57
+
58
+ Too many to fold in without blowing the current diff's scope → propose **one or more separate follow-up PRs** (or a roadmap under `agents/roadmaps/`, using the shared-prefix convention) so the user reviews before merge. Creating the PR/roadmap is **permission-gated** — propose, get a yes, then create (`scope-control`, `commit-policy`).
59
+
60
+ ## Version-gated modernization
61
+
62
+ Update stale idioms to the version the project **actually runs** — only when that version is **verified**:
63
+ - **Establish the version first** from the manifest constraint (`composer.json` `require`, `package.json` `engines`, `.tool-versions`, lockfile) — use the **lowest** bound; on an ambiguous/monorepo range, ask once. **Unknown version → do not touch** (must fit the project structure — the `source-discovery` gate).
64
+ - **Syntax-only, behavior-preserving idioms** (e.g. `array()` → `[]`, `isset($x)?$x:$d` → `$x ?? $d`, concat → template) provably equivalent → treat as a small fix (auto per the ladder).
65
+ - **Behavioral changes** (`readonly`/typed properties, new semantics) and **any dependency/version bump** → **ask only**, never auto (a version bump stays under `minimal-safe-diff`'s no-dependency-bump prohibition; a pure syntax idiom is categorically different).
66
+
67
+ ## Live-security carve-out (priority)
68
+
69
+ A **live cross-user / cross-tenant data exposure** (`broken-access-control`) is not "note for later": a potential GDPR-notifiable breach (Art. 33, 72 h from discovery). Meets the fix-now bar → fix now with its negative test. Otherwise → **stop and surface it immediately** (a safety surface, visible even under an autonomous mandate — like the `no-pr-progress-comments` safety carve-out). Never defer silently, never look away.
70
+
71
+ ## Guardrails — don't become a nagging machine
72
+
73
+ - Subordinate to `no-cheap-questions` (self-check items 3 & 14 — real trade-off, not a disguised continuation/commit ask), `autonomous-execution` (the end-of-session batch must not read as "shall I continue?"), `user-interaction`, `ask-when-uncertain` (one batched prompt = one question).
74
+ - Threshold to surface at all: a **real, nameable** improvement with concrete benefit. Cosmetic nitpicks with no trade-off → drop silently. The live-security carve-out is the only case that interrupts or overrides autonomy.
75
+
76
+ ## When it fires
77
+
78
+ While implementing/modifying code you pass an issue outside the literal task. Also on explicit "clean this up / modernize / dedupe".
79
+
80
+ ## When NOT to fire
81
+
82
+ - No issue spotted. Prose/docs-only. User fenced the scope ("just this one line").
83
+ - The issue is the task itself — then it's just the task (no ladder needed).
84
+
85
+ ## See also
86
+
87
+ - [`minimal-safe-diff`](minimal-safe-diff.md) — the carve-out above is bounded by it; everything outside the five conditions stays note+ask.
88
+ - [`broken-access-control`](broken-access-control.md) — the security category + the live-exposure carve-out.
89
+ - [`prefer-enums-over-literals`](prefer-enums-over-literals.md) — an instance of this ladder (enum literals).
90
+ - [`source-discovery-gate`](source-discovery-gate.md) — establishing the verified project version before modernizing.
91
+ - [`scope-control`](scope-control.md), [`commit-policy`](commit-policy.md) — PR/commit creation stays permission-gated.
92
+ - [`improve-before-implement`](improve-before-implement.md) — the pre-work challenge (before); this is the during/after remediation.
@@ -13,7 +13,7 @@ Four rules answer **"may the agent do this autonomously?"** Higher band wins.
13
13
 
14
14
  | Band | Trigger | Canonical rule |
15
15
  |---|---|---|
16
- | **1. Hard Floor** | Prod-trunk merge · deploy · push · prod data/infra · whimsical bulk deletion · bulk-deletion or infra commit | [`non-destructive-by-default`](non-destructive-by-default.md) |
16
+ | **1. Hard Floor** | Prod-trunk merge · deploy · push · prod data/infra · whimsical bulk deletion · bulk-deletion or infra commit · irreversible external action (send · publish · post · purchase · submit) | [`non-destructive-by-default`](non-destructive-by-default.md) |
17
17
  | **2. Permission Gate** | Git op · branch / PR / tag · architectural or library change · scope expansion | [`scope-control`](scope-control.md) |
18
18
  | **3. Commit Default** | About to commit — never, unless one of four exceptions fires | [`commit-policy`](commit-policy.md) |
19
19
  | **4. Trivial-vs-Blocking** | Routine workflow question — act or ask | [`autonomous-execution`](autonomous-execution.md) |
@@ -0,0 +1,106 @@
1
+ ---
2
+ type: "auto"
3
+ tier: "2a"
4
+ alwaysApply: false
5
+ description: "Endpoint/query returning user or tenant data — authenticated ≠ authorized; enforce a server-derived ownership/tenant/role check + the three negative tests (401/non-owner/cross-tenant)"
6
+ triggers:
7
+ - intent: "returning user or tenant data"
8
+ - intent: "adding an endpoint that reads a record by id"
9
+ - keyword: "endpoint"
10
+ - keyword: "route"
11
+ - keyword: "authorization"
12
+ - keyword: "tenant"
13
+ - keyword: "IDOR"
14
+ - keyword: "session"
15
+ - keyword: "login"
16
+ - keyword: "controller"
17
+ - keyword: "findById"
18
+ routes_to:
19
+ - "skill:authz-review"
20
+ - "skill:threat-modeling"
21
+ - "skill:multi-tenancy"
22
+ workspaces: [engineering]
23
+ packs: [engineering-base]
24
+ ---
25
+
26
+ # Broken Access Control
27
+
28
+ The most common — and most damaging — failure in real systems and AI-written code: log in as one user, see another user's data. **Authenticated ≠ authorized.** The login check passes so the endpoint *feels* protected; the per-object ownership/tenant check is a separate line devs and AI omit — especially when the object id comes from the request. OWASP Web #1 (A01:2021) and API #1 (BOLA/IDOR), trivially scriptable, and a recurring real-world breach class — e.g. First American Financial (885M documents exposed via sequential ids with no ownership check).
29
+
30
+ ## The Iron Law
31
+
32
+ ```
33
+ AUTHENTICATED IS NOT AUTHORIZED. EVERY REQUEST-SUPPLIED ID/FILTER GETS A
34
+ SERVER-DERIVED OWNERSHIP/TENANT CHECK BEFORE ANY DATA IS RETURNED.
35
+ NO DATA-RETURNING ENDPOINT IS DONE WITHOUT THREE NEGATIVE TESTS:
36
+ UNAUTHENTICATED → 401 · NOT-OWNER → 403/404 · CROSS-TENANT → 403/404 (404 HIDES EXISTENCE).
37
+ ROLE DECIDES WHICH FIELDS — THE SERVER STRIPS THEM. THE FRONTEND HIDING A FIELD IS NOT PROTECTION.
38
+ A LIVE CROSS-USER EXPOSURE IS A NOTIFIABLE BREACH — NEVER SILENTLY PATCH IT.
39
+ ```
40
+
41
+ ## Non-optional controls (every data-returning surface)
42
+
43
+ - **Server-derived principal.** Ownership/tenant derived from the session/token, **never** from a request header/param/body the caller controls. A matching id in the request is not authorization.
44
+ - **Ownership/tenant check on every request id** before returning data. `findById(params.id)` with no `where owner/tenant = currentPrincipal` is the canonical bug.
45
+ - **Tenant-scoped by construction.** Every query on a tenant table carries the tenant predicate; prefer a base scope that injects it so a forgotten clause can't leak. (DSGVO: Mandantentrennung / Trennungskontrolle is a required TOM — a missing `tenant_id` filter is a compliance failure, not just a bug.)
46
+ - **Response minimization.** Return only entitled fields — no `SELECT *` / full-object serialization leaking PII "because the model has it" (Art. 25(2)).
47
+ - **Property-level authz (BOPLA / mass assignment).** Reject `role` / `user_id` / `tenant_id` / `is_admin` from the request body; explicit field allow-list, never whole-body binding.
48
+ - **Role/field-level output filtering (vertical BOPLA).** *Which* fields a principal receives depends on role + business rules — a driver role must not receive `price`; an office role must not receive the boss's `offer`. Serialize via a **role-scoped output DTO**, never the raw model / `to_json()`; sensitive fields (`price`/`cost`/`margin`/`salary`/`discount`/`offer`/internal notes) default-deny per role.
49
+ - **No guessable public ids** on sensitive resources — UUID/ULID, not sequential integers (turns one bug into full-DB enumeration).
50
+
51
+ ## The three negative tests — the completion gate
52
+
53
+ A protected endpoint is **not complete** until these exist and pass (happy-path 200 alone is the tautology this rule stops):
54
+
55
+ 1. **unauthenticated → 401** (no token).
56
+ 2. **authenticated but not the owner → 403/404** (user A requests user B's object with A's token).
57
+ 3. **cross-tenant → 403/404** (a principal in tenant A requests tenant B's resource; prefer 404 on sensitive resources — a hard 403 confirms the id exists in another tenant).
58
+
59
+ Small + task-aligned gap in code you touched → add the check **and** its negative test in the same commit (auto-fix boundary in `active-remediation`). Bigger → surface it.
60
+
61
+ ## Role-based field-level access — both directions (vertical BOPLA + BFLA)
62
+
63
+ Object-ownership (above) is *horizontal* (may this principal touch this record). This is *vertical*: which **fields** and which **functions** a role may reach — the maintainer's case (driver ≠ price, office worker ≠ boss's offer). Depends on role + business rules, and **the server is the only boundary** — the frontend hiding a field does not protect it: the raw JSON on the wire is readable via `curl`/DevTools/a proxy (3Fun leak: a privacy toggle filtered only in the app; the server returned every user's location to a direct query).
64
+
65
+ - **Read side (CWE-213 / Excessive Data Exposure).** Build the response from a **role-scoped output DTO** — never serialize the ORM model directly. Sensitive fields default-deny per role. A client `?fields=` selection is ergonomics, not authorization — intersect it server-side with the role's read-allowlist.
66
+ - **Write side (CWE-915).** Bind input through a **role-scoped write-allowlist** — never the raw body. Read-allowed ≠ write-allowed: a role may *see* `status` but not *set* `status:"approved"`; two independent sets.
67
+ - **Function level (BFLA, OWASP API #5).** A role must not reach a function/verb reserved for a higher role. Gate **every mutating verb** (POST/PUT/PATCH/DELETE), deny-by-default — not just the GET you were asked about. The admin button being hidden is not a control.
68
+ - **Nested / GraphQL.** Field-level checks propagate to nested selections; a low-role token selecting a restricted field gets null/error, not data.
69
+ - **Negative tests, per (role × sensitive field), both directions:** lower-role token → the field is **absent from the raw response body** (assert the body, not the UI); lower-role setting it on input → rejected/ignored, **verified by re-reading the persisted record**; every privileged verb → 403 for lower roles (403/404 on sensitive object reads).
70
+
71
+ ## Defense-in-depth (so one miss can't leak)
72
+
73
+ Stack ≥2 independent layers on sensitive data — query-level ownership scoping, a centralized default-deny policy layer (a route with no policy is denied, not silently open), and DB row-level security as the backstop for a forgotten `WHERE tenant_id`. The RLS / policy-layer configuration, the per-role authz matrix, and the audit greps live once in [`authz-review`](../skills/authz-review/SKILL.md).
74
+
75
+ ## GDPR / DSGVO — data protection by design
76
+
77
+ A cross-user leak violates **Art. 5(1)(f)** (integrity & confidentiality — a principle → higher fine tier), **Art. 25** (by design/default: default-deny + least privilege + response minimization), and **Art. 32** — which also **mandates a process for regularly testing effectiveness** of these controls (untested authz is a direct Art. 32 gap; hence the three negative tests are non-optional). A discovered live exposure is a **notifiable breach** (Art. 33, 72 h from discovery) — surface as "notify + remediate", never a silent patch. Data-protection context, not legal advice → `privacy-review`, `domain-safety-pii`.
78
+
79
+ ## Backstop greps (authoring-time)
80
+
81
+ ```bash
82
+ # Record fetched by request id with no owner/tenant predicate nearby (high-noise — a hit means read the line, not auto-fix)
83
+ rg -n '(findById|find|findOne|get)\(\s*(req\.|request\.|params\.|\$request|\$id)'
84
+ # Client-supplied tenant/user hint used as the scope (should come from the session)
85
+ rg -n '(tenant|tenantId|user_id|userId)\s*=\s*(req|request|params|headers|query)\.'
86
+ ```
87
+
88
+ The full authoring-time grep set (mass-assignment, raw-serialization, secrets) lives once in [`ai-code-blindspots`](../skills/ai-code-blindspots/SKILL.md).
89
+
90
+ A hit means read that line — is the ownership/tenant check present? Some are safe (already scoped); none should ship unchecked.
91
+
92
+ ## When it fires
93
+
94
+ Writing/modifying any endpoint, route, query, or serializer returning user- or tenant-owned data, or any auth/session/login/tenant path.
95
+
96
+ ## When NOT to fire
97
+
98
+ - Public, non-user-specific data with no principal concept (public docs page, health check with no data).
99
+ - Prose/docs/config-only edits.
100
+
101
+ ## See also
102
+
103
+ - [`authz-review`](../skills/authz-review/SKILL.md) — the 6-stage per-entrypoint chain, defense-in-depth, authz matrix, negative-test contract.
104
+ - [`security-sensitive-stop`](security-sensitive-stop.md) — threat-model BEFORE editing an auth/tenant path (fires first).
105
+ - [`active-remediation`](active-remediation.md) — the fix-now/ask/follow-up ladder + the live-exposure safety carve-out.
106
+ - [`threat-modeling`](../skills/threat-modeling/SKILL.md), [`multi-tenancy`](../skills/multi-tenancy/SKILL.md), [`ai-code-blindspots`](../skills/ai-code-blindspots/SKILL.md), [`privacy-review`](../skills/privacy-review/SKILL.md).
@@ -0,0 +1,42 @@
1
+ ---
2
+ type: "auto"
3
+ tier: "2b"
4
+ alwaysApply: false
5
+ description: "Multi-step or continuation replies carry a red thread — state the goal once, tie each turn back to it, name what changed since last turn, close the loop with one end-summary"
6
+ triggers:
7
+ - intent: "producing a multi-step or continuation reply"
8
+ - intent: "reporting progress on ongoing work"
9
+ workspaces: [agent-config-maintainer, construction, engineering, finance, founder, gtm, legal-review-prep, ops, product, small-business]
10
+ packs: [meta]
11
+ ---
12
+
13
+ # Communication Through-Line
14
+
15
+ The user follows the work through your replies. A multi-step task whose replies jump between sub-topics with no visible thread forces the user to re-derive where things stand every turn. Give the work a **red thread**: a followable narrative from goal to result. Session-spanning coherence — distinct from single-reply brevity (`direct-answers`) and option formatting (`user-interaction`), which it never overrides.
16
+
17
+ ## The Iron Law
18
+
19
+ ```
20
+ STATE THE GOAL ONCE. TIE EACH TURN BACK TO IT. NAME WHAT CHANGED SINCE THE LAST TURN.
21
+ CLOSE THE LOOP WITH ONE END-SUMMARY. NEVER MAKE THE USER RE-DERIVE WHERE THINGS STAND.
22
+ ```
23
+
24
+ ## Checkable behaviors
25
+
26
+ - **Anchor once.** At the start of a multi-step task, state the goal/plan in one line (not re-stated every turn).
27
+ - **Each turn locates itself.** A mid-task reply says, in a few words, where it sits in the plan ("step 3/5", "now the downstream wiring") — so the user never scrolls up to orient.
28
+ - **Name the delta.** On a continuation, say what changed since the last turn (what landed, what's next) rather than restating everything.
29
+ - **Close the loop.** A work reply ends with ONE end-summary mapping back to the stated goal — reached or not, what remains. (Same single end-summary `direct-answers` requires; do not add a second.)
30
+ - **Signal pivots.** If the work changes direction (new sub-task, interrupt, blocker), say so explicitly — a silent topic switch breaks the thread.
31
+
32
+ ## When NOT to over-apply
33
+
34
+ - A one-shot answer or trivial reply needs no plan-anchor or end-summary (`direct-answers` brevity wins).
35
+ - Don't narrate for its own sake — the thread is orientation, not play-by-play (respect `personal.play_by_play`).
36
+ - Never let the through-line inflate a reply past what the task needs; brevity and the one-recommendation rule win on conflict.
37
+
38
+ ## See also
39
+
40
+ - [`direct-answers`](direct-answers.md) — brevity + the single end-summary this closes the loop with.
41
+ - [`user-interaction`](user-interaction.md) — the one-recommendation format; through-line never adds a competing summary.
42
+ - [`language-and-tone`](language-and-tone.md) — the thread is in the user's language.