@event4u/agent-config 1.18.0 → 1.20.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/agent-handoff.md +14 -10
- package/.agent-src/commands/chat-history/import.md +170 -0
- package/.agent-src/commands/chat-history/learn.md +178 -0
- package/.agent-src/commands/chat-history/show.md +17 -18
- package/.agent-src/commands/chat-history.md +26 -25
- package/.agent-src/commands/council/default.md +77 -82
- package/.agent-src/commands/create-pr.md +28 -8
- package/.agent-src/commands/feature/roadmap.md +22 -0
- package/.agent-src/commands/roadmap/create.md +38 -6
- package/.agent-src/commands/roadmap/execute.md +36 -9
- package/.agent-src/commands/sync-gitignore.md +1 -1
- package/.agent-src/contexts/communication/rules-auto/skill-quality-mechanics.md +76 -0
- package/.agent-src/contexts/communication/rules-auto/slash-command-routing-policy-mechanics.md +3 -3
- package/.agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +5 -12
- package/.agent-src/rules/agent-authority.md +1 -0
- package/.agent-src/rules/agent-docs.md +1 -0
- package/.agent-src/rules/analysis-skill-routing.md +1 -0
- package/.agent-src/rules/architecture.md +1 -0
- package/.agent-src/rules/artifact-drafting-protocol.md +1 -0
- package/.agent-src/rules/artifact-engagement-recording.md +1 -0
- package/.agent-src/rules/ask-when-uncertain.md +1 -0
- package/.agent-src/rules/augment-portability.md +1 -0
- package/.agent-src/rules/augment-source-of-truth.md +1 -0
- package/.agent-src/rules/autonomous-execution.md +1 -0
- package/.agent-src/rules/capture-learnings.md +1 -0
- package/.agent-src/rules/cli-output-handling.md +2 -2
- package/.agent-src/rules/command-suggestion-policy.md +1 -0
- package/.agent-src/rules/commit-conventions.md +1 -0
- package/.agent-src/rules/commit-policy.md +1 -0
- package/.agent-src/rules/context-hygiene.md +22 -0
- package/.agent-src/rules/direct-answers.md +11 -2
- package/.agent-src/rules/docker-commands.md +1 -0
- package/.agent-src/rules/docs-sync.md +1 -0
- package/.agent-src/rules/downstream-changes.md +1 -0
- package/.agent-src/rules/e2e-testing.md +1 -0
- package/.agent-src/rules/guidelines.md +1 -0
- package/.agent-src/rules/improve-before-implement.md +1 -0
- package/.agent-src/rules/language-and-tone.md +38 -6
- package/.agent-src/rules/laravel-translations.md +1 -0
- package/.agent-src/rules/markdown-safe-codeblocks.md +1 -0
- package/.agent-src/rules/minimal-safe-diff.md +1 -0
- package/.agent-src/rules/missing-tool-handling.md +1 -0
- package/.agent-src/rules/model-recommendation.md +1 -0
- package/.agent-src/rules/no-attribution-footers.md +48 -0
- package/.agent-src/rules/no-cheap-questions.md +1 -0
- package/.agent-src/rules/no-roadmap-references.md +2 -1
- package/.agent-src/rules/non-destructive-by-default.md +1 -0
- package/.agent-src/rules/onboarding-gate.md +26 -0
- package/.agent-src/rules/package-ci-checks.md +1 -0
- package/.agent-src/rules/php-coding.md +1 -0
- package/.agent-src/rules/preservation-guard.md +1 -0
- package/.agent-src/rules/review-routing-awareness.md +1 -0
- package/.agent-src/rules/reviewer-awareness.md +1 -0
- package/.agent-src/rules/roadmap-progress-sync.md +22 -0
- package/.agent-src/rules/role-mode-adherence.md +2 -2
- package/.agent-src/rules/rule-type-governance.md +1 -0
- package/.agent-src/rules/runtime-safety.md +1 -0
- package/.agent-src/rules/scope-control.md +1 -0
- package/.agent-src/rules/security-sensitive-stop.md +1 -0
- package/.agent-src/rules/size-enforcement.md +1 -0
- package/.agent-src/rules/skill-improvement-trigger.md +1 -0
- package/.agent-src/rules/skill-quality.md +50 -0
- package/.agent-src/rules/slash-command-routing-policy.md +39 -0
- package/.agent-src/rules/think-before-action.md +1 -0
- package/.agent-src/rules/token-efficiency.md +1 -0
- package/.agent-src/rules/tool-safety.md +1 -0
- package/.agent-src/rules/ui-audit-gate.md +1 -0
- package/.agent-src/rules/upstream-proposal.md +1 -0
- package/.agent-src/rules/user-interaction.md +22 -5
- package/.agent-src/rules/verify-before-complete.md +1 -0
- package/.agent-src/skills/ai-council/SKILL.md +4 -5
- package/.agent-src/skills/dcf-modeling/SKILL.md +89 -0
- package/.agent-src/skills/funnel-analysis/SKILL.md +100 -0
- package/.agent-src/skills/md-language-check/SKILL.md +1 -1
- package/.agent-src/skills/okr-tree-modeling/SKILL.md +93 -0
- package/.agent-src/skills/rice-prioritization/SKILL.md +100 -0
- package/.agent-src/skills/roadmap-management/SKILL.md +29 -4
- package/.agent-src/skills/subagent-orchestration/SKILL.md +34 -2
- package/.agent-src/skills/unit-economics-modeling/SKILL.md +104 -0
- package/.agent-src/skills/using-git-worktrees/SKILL.md +1 -0
- package/.agent-src/skills/verify-completion-evidence/SKILL.md +8 -1
- package/.agent-src/templates/agent-settings.md +21 -26
- package/.agent-src/templates/roadmaps.md +8 -3
- package/.agent-src/templates/scripts/work_engine/hook_bootstrap.py +16 -5
- package/.agent-src/templates/scripts/work_engine/hooks/__init__.py +4 -4
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/__init__.py +4 -4
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/_chat_history_base.py +7 -51
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_append.py +1 -2
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_halt_append.py +1 -2
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.py +163 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.py +110 -0
- package/.agent-src/templates/scripts/work_engine/hooks/settings.py +36 -0
- package/.agent-src/templates/scripts/work_engine/scoring/decision_trace.py +141 -0
- package/.agent-src/templates/scripts/work_engine/scoring/memory_visibility.py +125 -0
- package/.agent-src/templates/skill.md +30 -1
- package/.claude-plugin/marketplace.json +8 -4
- package/AGENTS.md +44 -3
- package/CHANGELOG.md +173 -0
- package/README.md +22 -22
- package/config/agent-settings.template.yml +42 -13
- package/config/gitignore-block.txt +4 -4
- package/docs/architecture.md +3 -3
- package/docs/catalog.md +18 -13
- package/docs/contracts/adr-chat-history-split.md +10 -1
- package/docs/contracts/adr-settings-sync-engine.md +127 -0
- package/docs/contracts/command-clusters.md +1 -1
- package/docs/contracts/cross-wing-handoff.md +133 -0
- package/docs/contracts/decision-trace-v1.md +146 -0
- package/docs/contracts/file-ownership-matrix.json +348 -126
- package/docs/contracts/hook-architecture-v1.md +220 -0
- package/docs/contracts/memory-visibility-v1.md +122 -0
- package/docs/contracts/one-off-script-lifecycle.md +109 -0
- package/docs/contracts/rule-interactions.yml +22 -0
- package/docs/customization.md +2 -1
- package/docs/development.md +4 -1
- package/docs/getting-started.md +21 -29
- package/docs/guidelines/agent-infra/ask-when-uncertain-demos.md +1 -1
- package/docs/guidelines/agent-infra/layered-settings.md +32 -13
- package/docs/hook-payload-capture.md +221 -0
- package/docs/migrations/commands-1.15.0.md +17 -12
- package/docs/skills-catalog.md +5 -4
- package/llms.txt +4 -3
- package/package.json +1 -1
- package/scripts/agent-config +45 -1
- package/scripts/ai_council/_default_prices.py +4 -4
- package/scripts/ai_council/bundler.py +3 -3
- package/scripts/ai_council/clients.py +25 -9
- package/scripts/ai_council/modes.py +3 -4
- package/scripts/ai_council/one_off_archive/2026-05/README.md +22 -0
- package/scripts/ai_council/one_off_archive/2026-05/_one_off_roundtrip.py +13 -8
- package/scripts/ai_council/one_off_archive/2026-05/_one_off_tier_retrofit.py +180 -0
- package/scripts/ai_council/pricing.py +10 -9
- package/scripts/ai_council/session.py +92 -0
- package/scripts/build_rule_trigger_matrix.py +1 -9
- package/scripts/capture_showcase_session.py +361 -0
- package/scripts/chat_history.py +963 -597
- package/scripts/check_always_budget.py +7 -2
- package/scripts/check_references.py +12 -2
- package/scripts/context_hygiene_hook.py +14 -6
- package/scripts/council_cli.py +407 -0
- package/scripts/hook_manifest.yaml +217 -0
- package/scripts/hooks/__init__.py +1 -0
- package/scripts/hooks/augment-chat-history.sh +10 -0
- package/scripts/hooks/augment-dispatcher.sh +72 -0
- package/scripts/hooks/cline-dispatcher.sh +86 -0
- package/scripts/hooks/cowork-dispatcher.sh +98 -0
- package/scripts/hooks/cursor-dispatcher.sh +76 -0
- package/scripts/hooks/dispatch_hook.py +383 -0
- package/scripts/hooks/envelope.py +98 -0
- package/scripts/hooks/gemini-dispatcher.sh +117 -0
- package/scripts/hooks/state_io.py +122 -0
- package/scripts/hooks/windsurf-dispatcher.sh +123 -0
- package/scripts/hooks_status.py +157 -0
- package/scripts/install-hooks.sh +2 -2
- package/scripts/install.py +725 -87
- package/scripts/install.sh +38 -1
- package/scripts/lint_handoffs.py +214 -0
- package/scripts/lint_hook_manifest.py +217 -0
- package/scripts/lint_one_off_age.py +184 -0
- package/scripts/lint_rule_tiers.py +78 -0
- package/scripts/lint_showcase_sessions.py +148 -0
- package/scripts/minimal_safe_diff_hook.py +245 -0
- package/scripts/onboarding_gate_hook.py +13 -8
- package/scripts/readme_linter.py +12 -3
- package/scripts/redact_hook_capture.py +148 -0
- package/scripts/roadmap_progress_hook.py +5 -0
- package/scripts/schemas/skill.schema.json +5 -0
- package/scripts/skill_linter.py +163 -1
- package/scripts/sync_agent_settings.py +32 -129
- package/scripts/sync_yaml_rt.py +734 -0
- package/scripts/update_prices.py +3 -3
- package/scripts/verify_before_complete_hook.py +216 -0
- package/.agent-src/commands/chat-history/checkpoint.md +0 -126
- package/.agent-src/commands/chat-history/clear.md +0 -103
- package/.agent-src/commands/chat-history/resume.md +0 -183
- package/.agent-src/rules/chat-history-cadence.md +0 -109
- package/.agent-src/rules/chat-history-ownership.md +0 -123
- package/.agent-src/rules/chat-history-visibility.md +0 -96
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_heartbeat.py +0 -50
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_turn_check.py +0 -49
- package/scripts/check_phase_coupling.py +0 -148
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: subagent-orchestration
|
|
3
|
-
description: "Use when orchestrating implementer/judge subagents —
|
|
3
|
+
description: "Use when orchestrating implementer/judge subagents — six modes (do-and-judge, do-in-steps, do-in-parallel, do-competitively, judge-with-debate, do-in-worktrees) — models from .agent-settings.yml."
|
|
4
4
|
source: package
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -44,7 +44,7 @@ judge is a fresh pair of eyes. If `.agent-settings.yml` resolves to
|
|
|
44
44
|
identical implementer and judge models, surface the mismatch before
|
|
45
45
|
running — do not silently continue.
|
|
46
46
|
|
|
47
|
-
## The
|
|
47
|
+
## The six modes
|
|
48
48
|
|
|
49
49
|
Each mode has a decision row: when to use, when not, and the expected
|
|
50
50
|
model pairing. Defaults come from
|
|
@@ -100,6 +100,38 @@ migration, public API) where a single judge is too easy to fool.
|
|
|
100
100
|
|---|---|---|
|
|
101
101
|
| Security, data integrity, public API change | Routine internal refactor | judges = same tier (2x); meta-judge = one tier up |
|
|
102
102
|
|
|
103
|
+
### 6. do-in-worktrees
|
|
104
|
+
|
|
105
|
+
Cross-wing or cross-skill chain executed across isolated git
|
|
106
|
+
worktrees — each handoff in the chain runs in its own worktree, so
|
|
107
|
+
the workspace state of one step never leaks into the next. Operationalizes
|
|
108
|
+
the worktree boundary clause in
|
|
109
|
+
[`docs/contracts/cross-wing-handoff.md`](../../../docs/contracts/cross-wing-handoff.md)
|
|
110
|
+
§ 3. State-machine layer only — worktree creation/destruction lives
|
|
111
|
+
in [`using-git-worktrees`](../using-git-worktrees/SKILL.md) and
|
|
112
|
+
[`finishing-a-development-branch`](../finishing-a-development-branch/SKILL.md).
|
|
113
|
+
|
|
114
|
+
| When to use | When not | Model pairing |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| Multi-step cross-wing chain (≥2 senior skills, each ≥30 min) where one step's open files / branch state would confuse the next | Fast iteration where each step < 30 min — worktree overhead exceeds isolation benefit | implementers = same tier per step; judge = one tier up at chain end |
|
|
117
|
+
|
|
118
|
+
**Handoff shape:** initiator-skill emits the typed output declared in
|
|
119
|
+
its `## Output` block → control passes to delegated-skill in a fresh
|
|
120
|
+
worktree → delegated-skill consumes the input shape declared in its
|
|
121
|
+
`## Input` (or `## When the agent should load this`) block. The
|
|
122
|
+
handoff is auditable; `lint_handoffs.py` validates the chain.
|
|
123
|
+
|
|
124
|
+
**Example chain (W3 launch):** `positioning` (worktree A) →
|
|
125
|
+
`messaging-architecture` (worktree B, consumes positioning's
|
|
126
|
+
`positioning-statement.md`) → `gtm-launch` (worktree C, consumes
|
|
127
|
+
both prior artifacts). Each worktree carries one branch; the chain
|
|
128
|
+
end produces a single integration PR.
|
|
129
|
+
|
|
130
|
+
**Anti-pattern:** do not use for fast iteration loops where each
|
|
131
|
+
step is under ~30 minutes. The branch-creation, context-switch, and
|
|
132
|
+
worktree-cleanup cost dominates. Stick with mode 1 (do-and-judge)
|
|
133
|
+
or mode 2 (do-in-steps) for those.
|
|
134
|
+
|
|
103
135
|
## Procedure
|
|
104
136
|
|
|
105
137
|
### 1. Inspect the task shape
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: unit-economics-modeling
|
|
3
|
+
description: "Use when modeling CAC, LTV, gross-margin payback, or contribution margin per customer — for SaaS, marketplace, or transactional businesses."
|
|
4
|
+
status: active
|
|
5
|
+
tier: senior
|
|
6
|
+
source: package
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# unit-economics-modeling
|
|
10
|
+
|
|
11
|
+
## When to use
|
|
12
|
+
|
|
13
|
+
- A board ask: "is this business unit-economic?" — needs CAC / LTV / payback, not vibes.
|
|
14
|
+
- A new channel is scaling and the question is whether the CAC payback period is sustainable.
|
|
15
|
+
- A pricing or packaging change needs to be tested against contribution margin per cohort.
|
|
16
|
+
|
|
17
|
+
Do NOT use for full-business intrinsic-value modeling, OKR setting, funnel-stage diagnosis, or backlog ranking (see Related Skills).
|
|
18
|
+
|
|
19
|
+
## Procedure
|
|
20
|
+
|
|
21
|
+
### Step 0: Inspect
|
|
22
|
+
|
|
23
|
+
1. Confirm the business shape — SaaS / marketplace / transactional. The three canonical cases differ in **revenue recognition** and **churn definition**, not in arithmetic.
|
|
24
|
+
2. Confirm a fully-loaded CAC is computable: paid spend + sales comp + content/SEO allocation + tooling. Marketing-spend-only CAC is a vanity metric.
|
|
25
|
+
|
|
26
|
+
### Step 1: Compute CAC per channel
|
|
27
|
+
|
|
28
|
+
1. CAC = `(fully-loaded acquisition spend in window) / (new paying customers acquired in same window)`. Match window to sales-cycle length, not calendar quarter.
|
|
29
|
+
2. Compute by channel **and** blended. Blended-only hides the channel that is breaking the average.
|
|
30
|
+
3. Anti-pattern: counting trial signups as customers. Customer = first paid charge cleared.
|
|
31
|
+
|
|
32
|
+
### Step 2: Compute gross margin
|
|
33
|
+
|
|
34
|
+
1. Gross margin = `(revenue − COGS) / revenue`. COGS includes hosting, payment fees, third-party APIs the customer's usage drives, and direct customer-success cost.
|
|
35
|
+
2. Gross margin must be **per dollar of revenue**, not per customer. Per-customer gross margin is contribution margin (Step 3).
|
|
36
|
+
3. SaaS healthy band: 70–85%. Marketplace: 15–40%. Transactional: 5–25%. Outside these — the business is mislabelled or the COGS allocation is wrong.
|
|
37
|
+
|
|
38
|
+
### Step 3: Compute LTV
|
|
39
|
+
|
|
40
|
+
1. Pick the canonical formula for the case:
|
|
41
|
+
- **SaaS:** `LTV = ARPA × gross_margin / monthly_churn_rate`. Use net-dollar churn for self-serve, gross logo churn for high-touch.
|
|
42
|
+
- **Marketplace:** `LTV = take_rate × GMV_per_user × retention_curve_AUC` over 24 months. Steady-state extrapolation is dishonest below 24 months of cohort data.
|
|
43
|
+
- **Transactional:** `LTV = avg_order_value × gross_margin × purchases_per_year × avg_lifetime_years`.
|
|
44
|
+
2. Cap implied lifetime at 5 years for any business with < 3 years of cohort history. Anything longer is a fairy tale.
|
|
45
|
+
3. State the formula used inline. Do not let the reader infer.
|
|
46
|
+
|
|
47
|
+
### Step 4: Compute payback and ratio
|
|
48
|
+
|
|
49
|
+
1. **CAC payback** (months) = `CAC / (ARPA × gross_margin)` for SaaS; analogue for marketplace and transactional. Healthy SaaS: ≤ 12 months.
|
|
50
|
+
2. **LTV / CAC ratio**: target ≥ 3.0. Below 1.5 is acquisition-loss territory; above 5.0 means under-investment in growth (or bad LTV math).
|
|
51
|
+
3. Both numbers, not one. Payback drives capital efficiency; ratio drives long-run economics.
|
|
52
|
+
|
|
53
|
+
### Step 5: Cohort the answer
|
|
54
|
+
|
|
55
|
+
1. Run Steps 1–4 by signup-quarter cohort. Trends matter more than the point estimate.
|
|
56
|
+
2. If LTV/CAC is improving but payback is lengthening, you are buying retention with discounting — flag.
|
|
57
|
+
3. If both deteriorate, the channel mix has shifted to a worse channel — segment by channel to find the leak.
|
|
58
|
+
|
|
59
|
+
### Step 6: Validate
|
|
60
|
+
|
|
61
|
+
1. Sanity-check LTV against revenue retention. If implied LTV > 8× annual revenue per customer with monthly churn > 2%, the math is wrong.
|
|
62
|
+
2. Sanity-check CAC against fully-loaded P&L. If channel CACs sum to less than total acquisition spend, allocations are missing.
|
|
63
|
+
|
|
64
|
+
## Gotcha
|
|
65
|
+
|
|
66
|
+
- Marketing-spend-only CAC is the most common deception. Sales comp, BDR salaries, content production, and tooling all belong in fully-loaded CAC.
|
|
67
|
+
- Net-dollar retention > 100% does not justify ignoring logo churn — they answer different questions.
|
|
68
|
+
- ARPA averaged across plan tiers hides churn concentrated in one tier. Compute per tier when tiers differ in price by more than 2×.
|
|
69
|
+
- Payback period using contribution margin (post variable-cost) is honest; payback using gross revenue is the kind of math VCs see in pitch decks and discount on sight.
|
|
70
|
+
|
|
71
|
+
## Do NOT
|
|
72
|
+
|
|
73
|
+
- Do NOT extrapolate LTV beyond observable cohort data without saying so explicitly.
|
|
74
|
+
- Do NOT mix freemium activation rates with paid CAC; they live in different universes.
|
|
75
|
+
- Do NOT report a single LTV/CAC for a business with multiple distinct customer segments — segment first.
|
|
76
|
+
|
|
77
|
+
## Related Skills
|
|
78
|
+
|
|
79
|
+
**WHEN to use this**
|
|
80
|
+
|
|
81
|
+
- The question is per-customer economics (CAC, LTV, payback, contribution margin).
|
|
82
|
+
- The decision is whether to scale a channel or pricing tier.
|
|
83
|
+
|
|
84
|
+
**WHEN NOT to use this**
|
|
85
|
+
|
|
86
|
+
- Whole-business intrinsic value with terminal value — route to [`dcf-modeling`](../dcf-modeling/SKILL.md).
|
|
87
|
+
- Diagnosing where conversion drops — route to [`funnel-analysis`](../funnel-analysis/SKILL.md).
|
|
88
|
+
- Ranking competing initiatives — route to [`rice-prioritization`](../rice-prioritization/SKILL.md).
|
|
89
|
+
- Setting team objectives that move these metrics — route to [`okr-tree-modeling`](../okr-tree-modeling/SKILL.md).
|
|
90
|
+
|
|
91
|
+
## When the agent should load this
|
|
92
|
+
|
|
93
|
+
- "What's our LTV / CAC?"
|
|
94
|
+
- "Is this channel paying back fast enough?"
|
|
95
|
+
- "Compute unit economics for this pricing tier."
|
|
96
|
+
- "Are we unit-economic at this CAC?"
|
|
97
|
+
- "Cohort our payback period."
|
|
98
|
+
|
|
99
|
+
## Output
|
|
100
|
+
|
|
101
|
+
1. **`unit-econ-table.md`** — table per channel and blended: CAC · ARPA · gross margin · payback months · LTV · LTV/CAC. With cohort columns (last 4 quarters).
|
|
102
|
+
2. **`assumptions.md`** — formula chosen (SaaS / marketplace / transactional), churn definition, COGS allocation method, lifetime cap. One bullet per choice.
|
|
103
|
+
3. **`cohort-trend.md`** — trend chart (ASCII or markdown table) of CAC, payback, LTV/CAC over the last 4–8 cohorts. Annotate channel-mix shifts.
|
|
104
|
+
4. **`sanity-checks.md`** — explicit cross-checks (LTV vs annual revenue, channel CAC sum vs P&L). Flag any that fail with a one-line investigation pointer.
|
|
@@ -15,6 +15,7 @@ source: package
|
|
|
15
15
|
* Experimenting with a refactor that may be thrown away — a throwaway
|
|
16
16
|
worktree is cheaper than a throwaway commit
|
|
17
17
|
* A long-running build or test suite is busy in the current worktree
|
|
18
|
+
* `subagent-orchestration` mode 6 (`do-in-worktrees`) was selected for a cross-wing chain — this skill is the executor that creates the per-step isolated worktrees the chain expects
|
|
18
19
|
|
|
19
20
|
Do NOT use when:
|
|
20
21
|
|
|
@@ -128,7 +128,12 @@ When reporting completion to the user:
|
|
|
128
128
|
3. **Result** — numeric breakdown (tests passed/failed/skipped, errors,
|
|
129
129
|
warnings)
|
|
130
130
|
4. **Caveats** — anything the output flagged but you chose to accept
|
|
131
|
-
5. **
|
|
131
|
+
5. **Untracked files** — if `git status --short` shows any untracked
|
|
132
|
+
files in the working tree, list them verbatim in the report. This
|
|
133
|
+
prevents silently-shipped artefacts (logs, scratch scripts, ad-hoc
|
|
134
|
+
notes) from disappearing into a future commit. Empty list means
|
|
135
|
+
omit the section.
|
|
136
|
+
6. **Next step** — e.g. "Ready for `/commit`" or "Awaiting review"
|
|
132
137
|
|
|
133
138
|
## Gotchas
|
|
134
139
|
|
|
@@ -188,3 +193,5 @@ Before sending a completion message:
|
|
|
188
193
|
* [ ] No warnings or skips are hidden
|
|
189
194
|
* [ ] Targeted tests green → full suite green → quality pipeline clean
|
|
190
195
|
* [ ] `git status` reflects only the intended change set
|
|
196
|
+
* [ ] If `git status --short` shows untracked files, the report lists
|
|
197
|
+
them verbatim under "Untracked files"
|
|
@@ -122,7 +122,7 @@ eloquent:
|
|
|
122
122
|
|
|
123
123
|
# --- Chat history (crash recovery) ---
|
|
124
124
|
#
|
|
125
|
-
# Persistent JSONL log at
|
|
125
|
+
# Persistent JSONL log at agents/.agent-chat-history (project root, git-ignored).
|
|
126
126
|
# Keeps a durable record of the conversation so a crashed or switched
|
|
127
127
|
# agent session can be resumed. See scripts/chat_history.py for the API.
|
|
128
128
|
#
|
|
@@ -141,26 +141,6 @@ chat_history:
|
|
|
141
141
|
# Overflow behavior: rotate (drop oldest) | compress (summarize)
|
|
142
142
|
on_overflow: rotate
|
|
143
143
|
|
|
144
|
-
# Heartbeat marker visibility: on | off | hybrid
|
|
145
|
-
# on — print marker every reply (~20 tokens/reply, legacy)
|
|
146
|
-
# off — never print (zero tokens, no drift signal)
|
|
147
|
-
# hybrid — print only on drift (missing/foreign/returning); silent otherwise
|
|
148
|
-
# YAML 1.1 booleanizes bare on/off — both are accepted, no quoting needed.
|
|
149
|
-
heartbeat: hybrid
|
|
150
|
-
|
|
151
|
-
# Population path: hook | checkpoint | manual
|
|
152
|
-
# hook — platform fires lifecycle hooks; agent observes only
|
|
153
|
-
# (Claude Code, Augment CLI, Cursor 1.7+, Cline non-Windows,
|
|
154
|
-
# Windsurf, Gemini CLI). scripts/install.py wires hooks.
|
|
155
|
-
# checkpoint — agent invokes /chat-history-checkpoint at phase boundaries
|
|
156
|
-
# (Augment IDE plugin, Cursor < 1.7, Cline on Windows).
|
|
157
|
-
# Cooperative three-gate Iron Law applies.
|
|
158
|
-
# manual — rule is inert (cloud surfaces). Persistence is local-only.
|
|
159
|
-
# Default `checkpoint` is the safest cooperative fallback. HOOK platforms
|
|
160
|
-
# set this to `hook` automatically when scripts/install.py merges the
|
|
161
|
-
# platform's settings file.
|
|
162
|
-
path: checkpoint
|
|
163
|
-
|
|
164
144
|
# --- Work-engine hooks ---
|
|
165
145
|
#
|
|
166
146
|
# Lifecycle hook surface of the `work_engine` Python engine
|
|
@@ -197,7 +177,7 @@ hooks:
|
|
|
197
177
|
# routing drift.
|
|
198
178
|
directive_set_guard: true
|
|
199
179
|
|
|
200
|
-
# Chat-history hooks — populate
|
|
180
|
+
# Chat-history hooks — populate agents/.agent-chat-history structurally from
|
|
201
181
|
# the engine. Gated by BOTH this block AND the global
|
|
202
182
|
# chat_history.enabled above; either off → no chat-history hook
|
|
203
183
|
# registers. Keep both on for the HOOK path; flip either off to fall
|
|
@@ -217,6 +197,21 @@ pipelines:
|
|
|
217
197
|
# Included by every cost_profile except `custom`.
|
|
218
198
|
skill_improvement: true
|
|
219
199
|
|
|
200
|
+
# --- Roadmap execution ---
|
|
201
|
+
#
|
|
202
|
+
# Controls when /roadmap execute runs the project's quality pipeline.
|
|
203
|
+
# Step checkboxes and the dashboard are ALWAYS updated in the same
|
|
204
|
+
# response — that cadence is governed by `roadmap-progress-sync` and
|
|
205
|
+
# is non-negotiable. This setting only governs *quality tool runs*.
|
|
206
|
+
roadmap:
|
|
207
|
+
# When to run quality tools during /roadmap execute.
|
|
208
|
+
# end_of_roadmap = once, before archiving (default — fastest, fewest tokens)
|
|
209
|
+
# per_phase = once after every completed phase
|
|
210
|
+
# per_step = after every completed step (legacy; highest token cost)
|
|
211
|
+
# Iron Law `verify-before-complete` still applies — fresh output is
|
|
212
|
+
# mandatory before any "roadmap complete" claim, regardless of cadence.
|
|
213
|
+
quality_cadence: end_of_roadmap
|
|
214
|
+
|
|
220
215
|
# --- Subagent orchestration ---
|
|
221
216
|
subagents:
|
|
222
217
|
# Model for implementer subagents (empty = same tier as the session model)
|
|
@@ -348,20 +343,20 @@ lives under `personal:` in YAML.
|
|
|
348
343
|
| `project.improvement_pr_branch_prefix` | string | `improve/agent-` | Branch prefix for agent improvement PRs. |
|
|
349
344
|
| `github.pr_reply_method` | `replies_endpoint`, `create_review_comment`, `auto` | `create_review_comment` | GitHub API method for replying to PR review comments. `auto` detects on first use. |
|
|
350
345
|
| `eloquent.access_style` | `getters_setters`, `get_attribute`, `magic_properties` | `getters_setters` | How to access Eloquent model attributes. See `eloquent` skill for details. |
|
|
351
|
-
| `chat_history.enabled` | `true`, `false` | `true` | Persist chat events to
|
|
346
|
+
| `chat_history.enabled` | `true`, `false` | `true` | Persist chat events to `agents/.agent-chat-history` (JSONL) for crash recovery. |
|
|
352
347
|
| `chat_history.frequency` | `per_turn`, `per_phase`, `per_tool` | per profile | Logging granularity. Defaults: `minimal`→`per_turn`, `balanced`→`per_phase`, `full`→`per_tool`. |
|
|
353
348
|
| `chat_history.max_size_kb` | integer | per profile | Max file size before overflow handling. Defaults: `minimal`→`128`, `balanced`→`256`, `full`→`512`. |
|
|
354
349
|
| `chat_history.on_overflow` | `rotate`, `compress` | per profile | On overflow: `rotate` drops oldest entries; `compress` marks the file for summarization on the next turn. Defaults: `minimal`/`balanced`→`rotate`, `full`→`compress`. |
|
|
355
|
-
| `chat_history.
|
|
356
|
-
| `chat_history.path` | `hook`, `checkpoint`, `manual` | `checkpoint` | Population path. `hook` = platform fires lifecycle hooks; `checkpoint` = agent invokes `/chat-history-checkpoint` at phase boundaries; `manual` = rule inert (cloud). `scripts/install.py` flips this to `hook` when the platform's hook config is deployed. See [`agents/contexts/chat-history-platform-hooks.md`](../../../agents/contexts/chat-history-platform-hooks.md). |
|
|
350
|
+
| `chat_history.text_limits.{user,agent,tool,phase}` | integer (chars) | `user=0`, `agent=5000`, `tool=200`, `phase=200` | Per-entry-type text-length cap. `0` = verbatim, no slice. `N > 0` = collapse whitespace, slice to N chars, append `" … [+K chars]"` so the log self-reports truncation. Defaults match `DEFAULT_TEXT_LIMITS` in `scripts/chat_history.py`. |
|
|
357
351
|
| `hooks.enabled` | `true`, `false` | `false` | Master switch for the work-engine hook layer. When `false` (default) the registry stays empty and golden replay is byte-stable. See [`agents/contexts/work-engine-hooks.md`](../../../agents/contexts/work-engine-hooks.md). |
|
|
358
352
|
| `hooks.trace` | `true`, `false` | `false` | Emit per-event trace lines on stderr. Useful for debugging; off by default because it is noisy. |
|
|
359
353
|
| `hooks.halt_surface_audit` | `true`, `false` | `true` | Defense-in-depth check that every halt surfaced by the dispatcher carries the expected shape. Cheap. |
|
|
360
354
|
| `hooks.state_shape_validation` | `true`, `false` | `true` | Re-run the state schema validator on `AFTER_LOAD` and `BEFORE_SAVE`. Cheap, catches drift. |
|
|
361
355
|
| `hooks.directive_set_guard` | `true`, `false` | `true` | Verify the dispatcher-resolved directive set matches the input envelope intent. Cheap, catches routing drift. |
|
|
362
|
-
| `hooks.chat_history.enabled` | `true`, `false` | `true` | Register
|
|
356
|
+
| `hooks.chat_history.enabled` | `true`, `false` | `true` | Register chat-history hooks (`append` on `after_step`, `halt_append` on `on_halt`). Gated by **both** this flag AND `chat_history.enabled`; either off → no chat-history hook registers. Schema v4: every entry self-identifies via 16-char session fingerprint, no ownership/sidecar layer. |
|
|
363
357
|
| `hooks.chat_history.script` | path | `scripts/chat_history.py` | Override path to the chat-history CLI. Set only when the script lives outside the standard location. |
|
|
364
358
|
| `pipelines.skill_improvement` | `true`, `false` | `true` | When `true`: propose learning capture after meaningful tasks. When `false`: silent. Included in every profile except `custom`. |
|
|
359
|
+
| `roadmap.quality_cadence` | `end_of_roadmap`, `per_phase`, `per_step` | `end_of_roadmap` | When `/roadmap execute` runs the project's quality pipeline. Default skips per-step / per-phase runs and gates only the final archival. `per_phase` runs once after every phase; `per_step` is the legacy verbose mode. Step checkboxes and the dashboard are always updated regardless. `verify-before-complete` still requires fresh output before any "roadmap complete" claim. |
|
|
365
360
|
| `subagents.implementer_model` | model alias or empty | _(empty)_ | Model for implementer subagents. Empty = same tier as session model. See [subagent-configuration](../contexts/subagent-configuration.md). |
|
|
366
361
|
| `subagents.judge_model` | model alias or empty | _(empty)_ | Model for judge subagents. Empty = one tier above implementer (opus if sonnet, sonnet if haiku). |
|
|
367
362
|
| `subagents.max_parallel` | integer | `3` | Maximum parallel subagent invocations. `1` serializes. |
|
|
@@ -39,11 +39,16 @@ Templates for roadmap files stored in `agents/roadmaps/` or `app/Modules/{Module
|
|
|
39
39
|
|
|
40
40
|
---
|
|
41
41
|
|
|
42
|
-
## Quality Gates (always apply)
|
|
42
|
+
## Quality Gates (always apply at completion)
|
|
43
43
|
|
|
44
|
-
Every roadmap must pass
|
|
44
|
+
Every roadmap must pass the project's quality pipeline before it is
|
|
45
|
+
considered done. **When** the pipeline runs during `/roadmap execute` is
|
|
46
|
+
governed by `roadmap.quality_cadence` in `.agent-settings.yml`
|
|
47
|
+
(`end_of_roadmap` default → once before archival; `per_phase` → after
|
|
48
|
+
every phase; `per_step` → after every step). Either way, a final fresh
|
|
49
|
+
run is mandatory before "complete" per `verify-before-complete`.
|
|
45
50
|
|
|
46
|
-
|
|
51
|
+
Common commands:
|
|
47
52
|
|
|
48
53
|
```bash
|
|
49
54
|
# PHP projects (inside Docker container if applicable)
|
|
@@ -17,10 +17,10 @@ from .hooks import HookRegistry
|
|
|
17
17
|
from .hooks.builtin import (
|
|
18
18
|
ChatHistoryAppendHook,
|
|
19
19
|
ChatHistoryHaltAppendHook,
|
|
20
|
-
|
|
21
|
-
ChatHistoryTurnCheckHook,
|
|
20
|
+
DecisionTraceHook,
|
|
22
21
|
DirectiveSetGuardHook,
|
|
23
22
|
HaltSurfaceAuditHook,
|
|
23
|
+
MemoryVisibilityHook,
|
|
24
24
|
StateShapeValidationHook,
|
|
25
25
|
TraceHook,
|
|
26
26
|
)
|
|
@@ -56,6 +56,13 @@ def _build_hook_registry(args: argparse.Namespace) -> HookRegistry:
|
|
|
56
56
|
StateShapeValidationHook().register(registry)
|
|
57
57
|
if settings.directive_set_guard:
|
|
58
58
|
DirectiveSetGuardHook().register(registry)
|
|
59
|
+
if settings.decision_trace:
|
|
60
|
+
DecisionTraceHook().register(registry)
|
|
61
|
+
if settings.memory_visibility:
|
|
62
|
+
MemoryVisibilityHook(
|
|
63
|
+
cost_profile=settings.cost_profile,
|
|
64
|
+
visibility_off=settings.memory_visibility_off,
|
|
65
|
+
).register(registry)
|
|
59
66
|
if settings.chat_history_enabled:
|
|
60
67
|
_register_chat_history_hooks(registry, settings)
|
|
61
68
|
|
|
@@ -65,12 +72,16 @@ def _build_hook_registry(args: argparse.Namespace) -> HookRegistry:
|
|
|
65
72
|
def _register_chat_history_hooks(
|
|
66
73
|
registry: HookRegistry, settings: HookSettings,
|
|
67
74
|
) -> None:
|
|
68
|
-
"""Register the
|
|
75
|
+
"""Register the structural chat-history hooks bound to the configured script.
|
|
76
|
+
|
|
77
|
+
Hook-only contract (post road-to-chat-history-hook-only): only the
|
|
78
|
+
append + halt-append hooks remain; cooperative ``turn-check`` /
|
|
79
|
+
``heartbeat`` hooks were removed when the cooperative always-rules
|
|
80
|
+
were retired.
|
|
81
|
+
"""
|
|
69
82
|
script = Path(settings.chat_history_script)
|
|
70
|
-
ChatHistoryTurnCheckHook(script).register(registry)
|
|
71
83
|
ChatHistoryAppendHook(script).register(registry)
|
|
72
84
|
ChatHistoryHaltAppendHook(script).register(registry)
|
|
73
|
-
ChatHistoryHeartbeatHook(script).register(registry)
|
|
74
85
|
|
|
75
86
|
|
|
76
87
|
__all__ = ["_build_hook_registry", "_register_chat_history_hooks"]
|
|
@@ -22,10 +22,10 @@ from __future__ import annotations
|
|
|
22
22
|
from .builtin import (
|
|
23
23
|
ChatHistoryAppendHook,
|
|
24
24
|
ChatHistoryHaltAppendHook,
|
|
25
|
-
|
|
26
|
-
ChatHistoryTurnCheckHook,
|
|
25
|
+
DecisionTraceHook,
|
|
27
26
|
DirectiveSetGuardHook,
|
|
28
27
|
HaltSurfaceAuditHook,
|
|
28
|
+
MemoryVisibilityHook,
|
|
29
29
|
StateShapeValidationHook,
|
|
30
30
|
TraceHook,
|
|
31
31
|
)
|
|
@@ -38,8 +38,7 @@ from .runner import HookRunner
|
|
|
38
38
|
__all__ = [
|
|
39
39
|
"ChatHistoryAppendHook",
|
|
40
40
|
"ChatHistoryHaltAppendHook",
|
|
41
|
-
"
|
|
42
|
-
"ChatHistoryTurnCheckHook",
|
|
41
|
+
"DecisionTraceHook",
|
|
43
42
|
"DirectiveSetGuardHook",
|
|
44
43
|
"HaltSurfaceAuditHook",
|
|
45
44
|
"HookCallback",
|
|
@@ -49,6 +48,7 @@ __all__ = [
|
|
|
49
48
|
"HookHalt",
|
|
50
49
|
"HookRegistry",
|
|
51
50
|
"HookRunner",
|
|
51
|
+
"MemoryVisibilityHook",
|
|
52
52
|
"StateShapeValidationHook",
|
|
53
53
|
"TraceHook",
|
|
54
54
|
]
|
|
@@ -13,20 +13,20 @@ from __future__ import annotations
|
|
|
13
13
|
|
|
14
14
|
from .chat_history_append import ChatHistoryAppendHook
|
|
15
15
|
from .chat_history_halt_append import ChatHistoryHaltAppendHook
|
|
16
|
-
from .
|
|
17
|
-
from .chat_history_turn_check import ChatHistoryTurnCheckHook
|
|
16
|
+
from .decision_trace import DecisionTraceHook
|
|
18
17
|
from .directive_set_guard import DirectiveSetGuardHook
|
|
19
18
|
from .halt_surface_audit import HaltSurfaceAuditHook
|
|
19
|
+
from .memory_visibility import MemoryVisibilityHook
|
|
20
20
|
from .state_shape_validation import StateShapeValidationHook
|
|
21
21
|
from .trace import TraceHook
|
|
22
22
|
|
|
23
23
|
__all__ = [
|
|
24
24
|
"ChatHistoryAppendHook",
|
|
25
25
|
"ChatHistoryHaltAppendHook",
|
|
26
|
-
"
|
|
27
|
-
"ChatHistoryTurnCheckHook",
|
|
26
|
+
"DecisionTraceHook",
|
|
28
27
|
"DirectiveSetGuardHook",
|
|
29
28
|
"HaltSurfaceAuditHook",
|
|
29
|
+
"MemoryVisibilityHook",
|
|
30
30
|
"StateShapeValidationHook",
|
|
31
31
|
"TraceHook",
|
|
32
32
|
]
|
|
@@ -12,9 +12,6 @@ import sys
|
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
from typing import Callable, Sequence
|
|
14
14
|
|
|
15
|
-
from ..context import HookContext
|
|
16
|
-
from ..exceptions import HookError
|
|
17
|
-
|
|
18
15
|
ProcessRunner = Callable[[Sequence[str]], "subprocess.CompletedProcess[str]"]
|
|
19
16
|
"""Callable that runs a subprocess. Production default: ``_default_runner``."""
|
|
20
17
|
|
|
@@ -28,65 +25,24 @@ def _default_runner(cmd: Sequence[str]) -> "subprocess.CompletedProcess[str]":
|
|
|
28
25
|
return subprocess.run(list(cmd), capture_output=True, text=True, check=False)
|
|
29
26
|
|
|
30
27
|
|
|
31
|
-
|
|
32
|
-
"""
|
|
28
|
+
class _ChatHistoryHookBase:
|
|
29
|
+
"""Shared plumbing — script path and runner.
|
|
33
30
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
unknown — callers raise ``HookError`` so the runner converts it to
|
|
40
|
-
a warning.
|
|
31
|
+
Schema v4 derives session attribution from the platform ``session_id``
|
|
32
|
+
(passed by the platform-hook dispatcher), not from a derived
|
|
33
|
+
first-user-msg. work-engine internal hooks have no platform session
|
|
34
|
+
in scope, so they omit ``--session-id`` and entries land in the
|
|
35
|
+
``<unknown>`` session bucket.
|
|
41
36
|
"""
|
|
42
|
-
work = ctx.work
|
|
43
|
-
if work is not None and getattr(work, "input", None) is not None:
|
|
44
|
-
inp = work.input
|
|
45
|
-
data = getattr(inp, "data", None) or {}
|
|
46
|
-
kind = getattr(inp, "kind", None)
|
|
47
|
-
if kind == "prompt":
|
|
48
|
-
raw = data.get("raw")
|
|
49
|
-
if raw:
|
|
50
|
-
return str(raw)
|
|
51
|
-
elif kind == "ticket":
|
|
52
|
-
joined = _ticket_msg(data)
|
|
53
|
-
if joined:
|
|
54
|
-
return joined
|
|
55
|
-
|
|
56
|
-
delivery = ctx.delivery
|
|
57
|
-
if delivery is not None:
|
|
58
|
-
ticket = getattr(delivery, "ticket", None) or {}
|
|
59
|
-
joined = _ticket_msg(ticket)
|
|
60
|
-
if joined:
|
|
61
|
-
return joined
|
|
62
|
-
return None
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def _ticket_msg(ticket: dict) -> str:
|
|
66
|
-
ticket_id = ticket.get("id") or ""
|
|
67
|
-
title = ticket.get("title") or ""
|
|
68
|
-
return f"{ticket_id}: {title}".strip(": ").strip()
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
class _ChatHistoryHookBase:
|
|
72
|
-
"""Shared plumbing — script path, runner, and first-msg derivation."""
|
|
73
37
|
|
|
74
38
|
def __init__(
|
|
75
39
|
self,
|
|
76
40
|
script_path: Path,
|
|
77
41
|
*,
|
|
78
42
|
runner: ProcessRunner | None = None,
|
|
79
|
-
first_user_msg: str | None = None,
|
|
80
43
|
) -> None:
|
|
81
44
|
self.script_path = Path(script_path)
|
|
82
45
|
self._runner = runner or _default_runner
|
|
83
|
-
self._fixed_msg = first_user_msg
|
|
84
|
-
|
|
85
|
-
def _resolve_msg(self, ctx: HookContext) -> str:
|
|
86
|
-
msg = self._fixed_msg or _derive_first_user_msg(ctx)
|
|
87
|
-
if not msg:
|
|
88
|
-
raise HookError("chat-history hook: cannot derive first-user-msg")
|
|
89
|
-
return msg
|
|
90
46
|
|
|
91
47
|
def _invoke(self, *args: str) -> "subprocess.CompletedProcess[str]":
|
|
92
48
|
cmd = [sys.executable, str(self.script_path), *args]
|
|
@@ -29,10 +29,9 @@ class ChatHistoryAppendHook(_ChatHistoryHookBase):
|
|
|
29
29
|
result = ctx.result
|
|
30
30
|
if result is None or getattr(result, "outcome", None) != Outcome.SUCCESS:
|
|
31
31
|
return
|
|
32
|
-
msg = self._resolve_msg(ctx)
|
|
33
32
|
payload: dict[str, Any] = {"step": ctx.step_name or "<unknown>"}
|
|
34
33
|
proc = self._invoke(
|
|
35
|
-
"append",
|
|
34
|
+
"append",
|
|
36
35
|
"--type", "phase", "--json", json.dumps(payload),
|
|
37
36
|
)
|
|
38
37
|
if proc.returncode != EXIT_OK:
|
|
@@ -22,7 +22,6 @@ class ChatHistoryHaltAppendHook(_ChatHistoryHookBase):
|
|
|
22
22
|
registry.register(HookEvent.ON_HALT, self._on_halt)
|
|
23
23
|
|
|
24
24
|
def _on_halt(self, ctx: HookContext) -> None:
|
|
25
|
-
msg = self._resolve_msg(ctx)
|
|
26
25
|
questions: list[str] = []
|
|
27
26
|
if ctx.result is not None:
|
|
28
27
|
questions = list(getattr(ctx.result, "questions", []) or [])
|
|
@@ -30,7 +29,7 @@ class ChatHistoryHaltAppendHook(_ChatHistoryHookBase):
|
|
|
30
29
|
questions = list(getattr(ctx.delivery, "questions", []) or [])
|
|
31
30
|
payload = {"step": ctx.step_name or "<unknown>", "questions": questions}
|
|
32
31
|
proc = self._invoke(
|
|
33
|
-
"append",
|
|
32
|
+
"append",
|
|
34
33
|
"--type", "decision", "--json", json.dumps(payload),
|
|
35
34
|
)
|
|
36
35
|
if proc.returncode != EXIT_OK:
|