@event4u/agent-config 2.19.0 → 2.20.1
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-status.md +29 -0
- package/.agent-src/commands/onboard.md +221 -81
- package/.agent-src/packs/README.md +49 -0
- package/.agent-src/packs/agency-delivery.yml +63 -0
- package/.agent-src/packs/content-engine.yml +53 -0
- package/.agent-src/packs/founder-mvp.yml +51 -0
- package/.agent-src/presets/README.md +26 -0
- package/.agent-src/presets/balanced.yml +34 -0
- package/.agent-src/presets/fast.yml +31 -0
- package/.agent-src/presets/strict.yml +38 -0
- package/.agent-src/profiles/README.md +29 -0
- package/.agent-src/profiles/agency.yml +27 -0
- package/.agent-src/profiles/content_creator.yml +25 -0
- package/.agent-src/profiles/developer.yml +26 -0
- package/.agent-src/profiles/finance.yml +24 -0
- package/.agent-src/profiles/founder.yml +25 -0
- package/.agent-src/profiles/ops.yml +25 -0
- package/.agent-src/rules/no-cheap-questions.md +25 -17
- package/.agent-src/skills/adr-create/SKILL.md +78 -68
- package/.agent-src/skills/subagent-orchestration/SKILL.md +33 -0
- package/.agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/.agent-src/templates/skill-archive-note.md +101 -0
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +73 -70
- package/README.md +68 -72
- package/config/agent-settings.template.yml +22 -0
- package/docs/adrs/caveman/0001-default-off-until-bench.md +93 -0
- package/docs/adrs/caveman/README.md +9 -0
- package/docs/adrs/cost/0001-hard-stop-hook.md +114 -0
- package/docs/adrs/cost/README.md +9 -0
- package/docs/adrs/memory/0001-consumer-side-snapshot.md +111 -0
- package/docs/adrs/memory/README.md +9 -0
- package/docs/adrs/router/0001-three-tier-routing.md +119 -0
- package/docs/adrs/router/README.md +9 -0
- package/docs/adrs/schema/0001-json-schema-frontmatter.md +102 -0
- package/docs/adrs/schema/README.md +9 -0
- package/docs/adrs/smoke/0001-per-tier-smoke-scripts.md +99 -0
- package/docs/adrs/smoke/README.md +9 -0
- package/docs/architecture/current-onboard-baseline.md +126 -0
- package/docs/architecture/current-safety-behavior.md +137 -0
- package/docs/archive/CHANGELOG-pre-2.16.0.md +48 -0
- package/docs/archive/CHANGELOG-pre-2.17.0.md +63 -0
- package/docs/contracts/adr-layout.md +108 -0
- package/docs/contracts/benchmark-corpus-spec.md +97 -0
- package/docs/contracts/benchmark-report-schema.md +111 -0
- package/docs/contracts/command-clusters.md +1 -0
- package/docs/contracts/command-taxonomy.md +137 -0
- package/docs/contracts/compression-default-kill-criterion.md +69 -0
- package/docs/contracts/config-presets.md +144 -0
- package/docs/contracts/cost-dashboard.md +143 -0
- package/docs/contracts/cost-enforcement.md +134 -0
- package/docs/contracts/file-ownership-matrix.json +0 -7
- package/docs/contracts/mcp-tool-inventory.md +53 -0
- package/docs/contracts/measurement-baseline.md +102 -0
- package/docs/contracts/namespace.md +125 -0
- package/docs/contracts/profile-system.md +142 -0
- package/docs/contracts/safety-model.md +129 -0
- package/docs/contracts/smoke-contracts.md +144 -0
- package/docs/contracts/workflow-packs.md +121 -0
- package/docs/decisions/ADR-010-profile-pack-preset-boundary.md +132 -0
- package/docs/decisions/INDEX.md +1 -0
- package/docs/featured-commands.md +27 -0
- package/docs/parity/bench-ruflo.json +58 -0
- package/docs/parity/bench.json +41 -0
- package/docs/parity/ruflo.md +46 -0
- package/docs/profiles.md +91 -0
- package/package.json +1 -1
- package/scripts/_cli/cmd_explain.py +250 -0
- package/scripts/_lib/bench_cost.py +138 -0
- package/scripts/_lib/bench_quality.py +118 -0
- package/scripts/_lib/bench_report.py +150 -0
- package/scripts/agent-config +13 -0
- package/scripts/audit_adr_coverage.py +175 -0
- package/scripts/audit_mcp_tools.py +146 -0
- package/scripts/bench_baseline_ready.py +108 -0
- package/scripts/bench_drift_check.py +151 -0
- package/scripts/bench_per_tool.py +216 -0
- package/scripts/bench_run.py +155 -0
- package/scripts/config/__init__.py +9 -0
- package/scripts/config/presets.py +206 -0
- package/scripts/config/profiles.py +173 -0
- package/scripts/cost/budget.mjs +73 -12
- package/scripts/cost/preflight.mjs +89 -0
- package/scripts/lint_archived_skills.py +143 -0
- package/scripts/lint_bench_corpus.py +161 -0
- package/scripts/lint_namespace.py +135 -0
- package/scripts/lint_roadmap_complexity.py +3 -2
- package/scripts/skill_overlap.py +204 -0
- package/scripts/skill_usage_collect.py +191 -0
- package/scripts/skill_usage_report.py +162 -0
- package/scripts/smoke/kernel.sh +101 -0
- package/scripts/smoke/router.sh +129 -0
- package/scripts/smoke/schema.sh +71 -0
- package/scripts/smoke/skills.sh +101 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# ADR 0001 — Caveman compression default stays OFF until `task bench`
|
|
2
|
+
|
|
3
|
+
> Area: `caveman` · Status: accepted · Date: 2026-05-16 · Type: retrospective
|
|
4
|
+
> Roadmap: `agents/roadmaps/step-11-ruflo-parity.md` Phase 4 Step 3
|
|
5
|
+
> Supersedes: —
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
Caveman-speak is a turn-time compression dialect that trades English
|
|
10
|
+
grammar for tokens. The dialect is documented in
|
|
11
|
+
[`caveman-speak`](../../../.agent-src.uncompressed/rules/caveman-speak.md);
|
|
12
|
+
the question this ADR records is **whether the dialect should default
|
|
13
|
+
ON for all consumers**.
|
|
14
|
+
|
|
15
|
+
The North-Star council ([`council-synthesis.md` § 7](../../../agents/audit-2026-05-14-north-star/council-synthesis.md))
|
|
16
|
+
landed split: two voices (token-efficiency, ops) argued default-ON
|
|
17
|
+
saves 40 %+ tokens on long sessions; two voices (UX, governance)
|
|
18
|
+
argued default-ON degrades novice readability and locks in a dialect
|
|
19
|
+
nobody has measured against the real benchmark corpus.
|
|
20
|
+
|
|
21
|
+
## Decision
|
|
22
|
+
|
|
23
|
+
**`caveman.speak_scope` defaults `off`**. Carve-outs (security ·
|
|
24
|
+
destructive · multi-step · code blocks · paths · numbered options ·
|
|
25
|
+
Iron-Law markers) stay in the rule body so the dialect is **defined**
|
|
26
|
+
even when **inactive**. The default flips only when `task bench`
|
|
27
|
+
produces measured win/loss numbers against the locked 25-prompt corpus.
|
|
28
|
+
|
|
29
|
+
Authoritative kill-criterion:
|
|
30
|
+
[`docs/contracts/compression-default-kill-criterion.md`](../../contracts/compression-default-kill-criterion.md)
|
|
31
|
+
§ Rule lines 8–11.
|
|
32
|
+
|
|
33
|
+
### Decision owner
|
|
34
|
+
|
|
35
|
+
`step-4-measurement-and-benchmark.md` closeout phase. Not this doc.
|
|
36
|
+
Not `step-99`. Not the North-Star council. The closeout reads
|
|
37
|
+
`docs/parity/bench.json` and applies exactly one of three branches
|
|
38
|
+
defined in the kill-criterion.
|
|
39
|
+
|
|
40
|
+
### Default-ON gates (all required)
|
|
41
|
+
|
|
42
|
+
1. ≥ 30 % token reduction averaged across the 25-prompt corpus.
|
|
43
|
+
2. ≤ 5 % regression on the readability score from the same run.
|
|
44
|
+
3. Reversibility check passes (caveman → English round-trip ≥ 95 %
|
|
45
|
+
semantic preservation per the bench scorer).
|
|
46
|
+
|
|
47
|
+
Any gate fails → default stays OFF. Re-bench after the next dialect
|
|
48
|
+
edit.
|
|
49
|
+
|
|
50
|
+
## Considered alternatives
|
|
51
|
+
|
|
52
|
+
### Alt 1 — Default ON now (rejected)
|
|
53
|
+
|
|
54
|
+
Flip the default immediately; let consumers opt out.
|
|
55
|
+
|
|
56
|
+
**Why rejected:** no measured baseline exists. The two pro voices'
|
|
57
|
+
40 % claim is from informal turn-snippet comparisons, not the locked
|
|
58
|
+
corpus. Default-on without measurement is exactly the Ruflo-style
|
|
59
|
+
"trust me it's faster" pattern the audit calls out.
|
|
60
|
+
|
|
61
|
+
### Alt 2 — Default ON for cost-profile `lean`, OFF for `default` (rejected)
|
|
62
|
+
|
|
63
|
+
Couple the default to the cost profile.
|
|
64
|
+
|
|
65
|
+
**Why rejected:** cost profiles already carry profile-specific budget
|
|
66
|
+
ladders and smoke contracts. Adding a dialect coupling makes the
|
|
67
|
+
matrix `2 × N` instead of `1 × N`. The kill-criterion measurement is
|
|
68
|
+
the same regardless of profile — make the decision once.
|
|
69
|
+
|
|
70
|
+
### Alt 3 — Keep default OFF, measure first (accepted)
|
|
71
|
+
|
|
72
|
+
The chosen path. Dialect ships, stays dormant, gets benched, then
|
|
73
|
+
either ships default-on or gets deprecated. No middle state.
|
|
74
|
+
|
|
75
|
+
## Consequences
|
|
76
|
+
|
|
77
|
+
- **Positive:** new consumers get standard English by default; the
|
|
78
|
+
novice-onboarding path is unaffected; the dialect is auditable and
|
|
79
|
+
measurable before it becomes the default cost vector.
|
|
80
|
+
- **Negative:** the 40 %+ token savings are leave-on-table for any
|
|
81
|
+
consumer who doesn't explicitly opt in. Mitigated by surfacing the
|
|
82
|
+
flag in `/onboard` once `task bench` lands.
|
|
83
|
+
- **Reversal cost:** flip the default in
|
|
84
|
+
[`.agent-settings.yml`](../../../.agent-settings.yml.example)
|
|
85
|
+
template; existing user settings unaffected by template change.
|
|
86
|
+
|
|
87
|
+
## References
|
|
88
|
+
|
|
89
|
+
- [`docs/contracts/compression-default-kill-criterion.md`](../../contracts/compression-default-kill-criterion.md) — kill-criterion contract.
|
|
90
|
+
- [`.agent-src.uncompressed/rules/caveman-speak.md`](../../../.agent-src.uncompressed/rules/caveman-speak.md) — dialect definition.
|
|
91
|
+
- [`agents/roadmaps/step-4-measurement-and-benchmark.md`](../../../agents/roadmaps/step-4-measurement-and-benchmark.md) — bench owner.
|
|
92
|
+
- [`agents/audit-2026-05-14-north-star/council-synthesis.md`](../../../agents/audit-2026-05-14-north-star/council-synthesis.md) § 7 — council split.
|
|
93
|
+
- [`agents/roadmaps/step-11-ruflo-parity.md`](../../../agents/roadmaps/step-11-ruflo-parity.md) Phase 4 Step 3 — origin.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# ADRs — `caveman`
|
|
2
|
+
|
|
3
|
+
> Caveman-speak compression, decompression, reversibility guards.
|
|
4
|
+
|
|
5
|
+
Contract: [`docs/contracts/compression-default-kill-criterion.md`](../../../docs/contracts/compression-default-kill-criterion.md).
|
|
6
|
+
|
|
7
|
+
| # | Title | Status | Date | Supersedes |
|
|
8
|
+
|---|---|---|---|---|
|
|
9
|
+
| [0001](0001-default-off-until-bench.md) | Default Off Until Bench | — | — | — |
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# ADR 0001 — Hard-stop hook surface
|
|
2
|
+
|
|
3
|
+
> Area: `cost` · Status: accepted · Date: 2026-05-16 · Type: retrospective
|
|
4
|
+
> Roadmap: `agents/roadmaps/step-11-ruflo-parity.md` Phase 2 Step 3
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
`step-11-measurement-governance-parity` Phase 2 lands a 5-tier budget
|
|
9
|
+
ladder (`OK / INFO / WARNING / CRITICAL / HARD_STOP`) evaluated by
|
|
10
|
+
[`scripts/cost/budget.mjs`](../../../scripts/cost/budget.mjs). The
|
|
11
|
+
roadmap requires that the `HARD_STOP` tier fail closed when the user
|
|
12
|
+
opts into `cost.enforcement: hard-stop` — without changing the
|
|
13
|
+
default-on advisory experience.
|
|
14
|
+
|
|
15
|
+
This package is a governance layer, not a runtime orchestrator (see
|
|
16
|
+
[`step-11`](../../../agents/roadmaps/step-11-ruflo-parity.md) scope
|
|
17
|
+
boundary). The hook must therefore live at a **process-entry seam**,
|
|
18
|
+
not inside the rule-loader, agent dispatcher, or per-tool-call
|
|
19
|
+
interceptor — none of those exist in this codebase by design.
|
|
20
|
+
|
|
21
|
+
## Decision
|
|
22
|
+
|
|
23
|
+
Land a single shell-entry preflight script:
|
|
24
|
+
[`scripts/cost/preflight.mjs`](../../../scripts/cost/preflight.mjs).
|
|
25
|
+
|
|
26
|
+
### Surface
|
|
27
|
+
|
|
28
|
+
- **Where it fires:** any shell or CI wrapper that opts in by calling
|
|
29
|
+
`task cost:preflight` (or `node scripts/cost/preflight.mjs`) before
|
|
30
|
+
composing a turn. Not auto-injected anywhere.
|
|
31
|
+
- **What it does:** wraps `budget.mjs check`. Reads `cost.enforcement`
|
|
32
|
+
from `.agent-settings.yml`. Exits non-zero **only** when
|
|
33
|
+
`enforcement: hard-stop` **and** `level: HARD_STOP`.
|
|
34
|
+
- **Refusal output:** human-readable refusal block citing
|
|
35
|
+
[`docs/contracts/cost-enforcement.md`](../../contracts/cost-enforcement.md)
|
|
36
|
+
with the three bypass paths (raise budget · reset ledger · disable
|
|
37
|
+
enforcement). Machine-readable equivalent on `PREFLIGHT_QUIET=1`.
|
|
38
|
+
|
|
39
|
+
### Default behaviour without a budget
|
|
40
|
+
|
|
41
|
+
When `cost.budgets.{daily,weekly,monthly}` are all `0`:
|
|
42
|
+
|
|
43
|
+
- `preflight.mjs` exits `0`. Always.
|
|
44
|
+
- This is the **fail-open default**. Unconfigured projects never get
|
|
45
|
+
blocked.
|
|
46
|
+
|
|
47
|
+
### Bypass
|
|
48
|
+
|
|
49
|
+
Three options, all documented in the refusal block and the contract:
|
|
50
|
+
|
|
51
|
+
1. **Raise the budget** — edit `.agent-settings.yml § cost.budgets`.
|
|
52
|
+
2. **Reset the ledger** — `node scripts/cost/track.mjs reset` (drops
|
|
53
|
+
historical spend from utilization).
|
|
54
|
+
3. **Disable enforcement** — set `cost.enforcement: advisory`.
|
|
55
|
+
|
|
56
|
+
No env-var override. Bypass is durable and auditable.
|
|
57
|
+
|
|
58
|
+
## Considered alternatives
|
|
59
|
+
|
|
60
|
+
### Alt 1 — Rule-loader hook (rejected)
|
|
61
|
+
|
|
62
|
+
Refuse to compose the turn-start preamble in the kernel-rule loader.
|
|
63
|
+
|
|
64
|
+
**Why rejected:** the kernel-rule loader is a static-projection step
|
|
65
|
+
(`scripts/sync.py` writes `.agent-src/rules/` from
|
|
66
|
+
`.agent-src.uncompressed/`). There is no live loader at turn-start to
|
|
67
|
+
hook — Claude / Augment / etc. read the projected files directly. A
|
|
68
|
+
"refusal" would have to be baked into the file content, which mixes
|
|
69
|
+
policy enforcement with documentation. Out of scope.
|
|
70
|
+
|
|
71
|
+
### Alt 2 — `/onboard` boot path (rejected)
|
|
72
|
+
|
|
73
|
+
Block `/onboard` when over budget.
|
|
74
|
+
|
|
75
|
+
**Why rejected:** `/onboard` is a one-shot install path. Blocking it
|
|
76
|
+
when the **historical** spend exceeds the **new** budget creates a
|
|
77
|
+
chicken-and-egg lock-out. Onboarding must never fail-closed.
|
|
78
|
+
|
|
79
|
+
### Alt 3 — Per-tool-call interceptor (rejected)
|
|
80
|
+
|
|
81
|
+
Wrap every tool call with a budget check.
|
|
82
|
+
|
|
83
|
+
**Why rejected:** this package doesn't intercept tool calls. Building
|
|
84
|
+
that would require a runtime engine — the explicit Non-goal of
|
|
85
|
+
`step-11` (see scope boundary). This is the Ruflo-style runtime
|
|
86
|
+
absorption we ruled out.
|
|
87
|
+
|
|
88
|
+
### Alt 4 — Single-shell-entry preflight (accepted)
|
|
89
|
+
|
|
90
|
+
The chosen surface. Opt-in by wrapper invocation; predictable; no
|
|
91
|
+
runtime, no projection coupling, no chicken-and-egg edges. Matches the
|
|
92
|
+
governance-layer charter.
|
|
93
|
+
|
|
94
|
+
## Consequences
|
|
95
|
+
|
|
96
|
+
- **Positive:** consumers who want fail-closed behaviour get it with
|
|
97
|
+
one settings flip + one task invocation. The default-on experience
|
|
98
|
+
is unchanged. No runtime is introduced. The hook composes with `task
|
|
99
|
+
ci`, `task work:*`, or any shell wrapper the consumer chooses.
|
|
100
|
+
- **Negative:** the hook is **opt-in by wrapper**. A consumer who sets
|
|
101
|
+
`enforcement: hard-stop` but never invokes `task cost:preflight`
|
|
102
|
+
gets no enforcement. Documented as a known limitation; mitigated by
|
|
103
|
+
surfacing the gap in `agent-status`.
|
|
104
|
+
- **Reversal cost:** flip `cost.enforcement: advisory` globally, or
|
|
105
|
+
remove the `task cost:preflight` call from wrappers. Hook becomes
|
|
106
|
+
inert with no code change.
|
|
107
|
+
|
|
108
|
+
## References
|
|
109
|
+
|
|
110
|
+
- [`docs/contracts/cost-enforcement.md`](../../contracts/cost-enforcement.md) — contract surface.
|
|
111
|
+
- [`scripts/cost/budget.mjs`](../../../scripts/cost/budget.mjs) — evaluator.
|
|
112
|
+
- [`scripts/cost/preflight.mjs`](../../../scripts/cost/preflight.mjs) — this hook.
|
|
113
|
+
- [`agents/roadmaps/step-11-ruflo-parity.md`](../../../agents/roadmaps/step-11-ruflo-parity.md) Phase 2 Step 3 — origin.
|
|
114
|
+
- [`agents/audit-2026-05-14-north-star/external-findings.md`](../../../agents/audit-2026-05-14-north-star/external-findings.md) § 2 row "hard stop" — upstream Ruflo pattern this absorbs.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# ADRs — `cost`
|
|
2
|
+
|
|
3
|
+
> Budget ladder, hard-stop hook, cost reporting and dashboards.
|
|
4
|
+
|
|
5
|
+
Contract: [`docs/contracts/cost-enforcement.md`](../../../docs/contracts/cost-enforcement.md).
|
|
6
|
+
|
|
7
|
+
| # | Title | Status | Date | Supersedes |
|
|
8
|
+
|---|---|---|---|---|
|
|
9
|
+
| [0001](0001-hard-stop-hook.md) | Hard Stop Hook | — | — | — |
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# ADR 0001 — Consumer-side snapshot of the agent-memory contract
|
|
2
|
+
|
|
3
|
+
> Area: `memory` · Status: accepted · Date: 2026-05-16 · Type: retrospective
|
|
4
|
+
> Roadmap: `agents/roadmaps/step-11-ruflo-parity.md` Phase 4 Step 3
|
|
5
|
+
> Supersedes: —
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
`@event4u/agent-memory` is a sibling package owned by this team. It
|
|
10
|
+
provides MCP-server semantic-retrieval plus a v1 retrieval envelope
|
|
11
|
+
(`id`, `type`, `source`, `confidence`, `body`, …). The spec-side
|
|
12
|
+
source-of-truth lives in
|
|
13
|
+
[`agents/roadmaps/archive/agent-memory/`](../../../agents/roadmaps/archive/agent-memory/);
|
|
14
|
+
the implementation lives in the sibling repo.
|
|
15
|
+
|
|
16
|
+
The question this ADR records is: **what surface does `agent-config`
|
|
17
|
+
freeze internally**, given the package ships independently and the
|
|
18
|
+
two repos can drift between releases?
|
|
19
|
+
|
|
20
|
+
## Decision
|
|
21
|
+
|
|
22
|
+
**Maintain a consumer-side snapshot at
|
|
23
|
+
[`docs/contracts/agent-memory-contract.md`](../../contracts/agent-memory-contract.md)** —
|
|
24
|
+
a point-in-time pin of the interface `agent-config`'s wired code
|
|
25
|
+
**currently assumes**.
|
|
26
|
+
|
|
27
|
+
### Three expected backend states
|
|
28
|
+
|
|
29
|
+
Probed by [`scripts/memory_status.py`](../../../scripts/memory_status.py):
|
|
30
|
+
|
|
31
|
+
| Status | Meaning | Agent-config behaviour |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| `absent` | Package not installed / CLI not on PATH | File fallback only |
|
|
34
|
+
| `misconfigured` | Installed; `health()` fails within 2 s | Warn once per session, fall back to file |
|
|
35
|
+
| `present` | Installed; healthy within 2 s | Route retrieval through package |
|
|
36
|
+
|
|
37
|
+
Detection is **bounded** (≤ 2 s cold probe), **cached per process**,
|
|
38
|
+
**non-raising** on probe failure.
|
|
39
|
+
|
|
40
|
+
### CLI candidates
|
|
41
|
+
|
|
42
|
+
Probed in `_CLI_CANDIDATES`: `memory` (canonical, v1.1+) ·
|
|
43
|
+
`agent-memory` (planned alias) · `agentmem` (legacy). If the released
|
|
44
|
+
package diverges from these names, this file updates — never the
|
|
45
|
+
other way round.
|
|
46
|
+
|
|
47
|
+
### Retrieval envelope (v1)
|
|
48
|
+
|
|
49
|
+
Mandatory per entry: `id`, `type`, `source ∈ {repo, operational}`,
|
|
50
|
+
`confidence`, `body`. Optional: `trust`, `last_validated`,
|
|
51
|
+
`shadowed_by`. Envelope: `contract_version`, `status ∈ {ok, partial,
|
|
52
|
+
error}`, `entries`, `slices`, `errors`. Source-of-truth:
|
|
53
|
+
[`scripts/memory_lookup.py`](../../../scripts/memory_lookup.py)
|
|
54
|
+
lines 320–345.
|
|
55
|
+
|
|
56
|
+
### Refresh policy
|
|
57
|
+
|
|
58
|
+
The snapshot doc carries a `Last refreshed:` line. On every sibling
|
|
59
|
+
package release that touches the CLI or envelope shape, the
|
|
60
|
+
maintainer:
|
|
61
|
+
|
|
62
|
+
1. Runs the sibling package's CLI against `agent-config`'s test
|
|
63
|
+
fixtures.
|
|
64
|
+
2. Updates this contract doc with the new shape, bumps
|
|
65
|
+
`Last refreshed:`, files the diff as a PR.
|
|
66
|
+
3. Updates `_CLI_CANDIDATES` and any consumer skills only if the
|
|
67
|
+
shape diff is breaking.
|
|
68
|
+
|
|
69
|
+
## Considered alternatives
|
|
70
|
+
|
|
71
|
+
### Alt 1 — No internal pin; trust the sibling spec (rejected)
|
|
72
|
+
|
|
73
|
+
Read the sibling package's spec at runtime / docs time.
|
|
74
|
+
|
|
75
|
+
**Why rejected:** the two repos release on independent cadences. A
|
|
76
|
+
mid-iteration sibling-package change would silently break consumer
|
|
77
|
+
code. The internal pin makes the divergence point a diffable doc.
|
|
78
|
+
|
|
79
|
+
### Alt 2 — Submodule the sibling spec (rejected)
|
|
80
|
+
|
|
81
|
+
Git submodule pulls `agent-memory/docs/` into `agent-config/`.
|
|
82
|
+
|
|
83
|
+
**Why rejected:** submodules complicate consumer installs (npx /
|
|
84
|
+
shell installer must handle nested clones); the spec is fast-moving
|
|
85
|
+
and submodule churn dwarfs the consumer-side surface this package
|
|
86
|
+
actually wires.
|
|
87
|
+
|
|
88
|
+
### Alt 3 — Consumer-side snapshot (accepted)
|
|
89
|
+
|
|
90
|
+
The chosen path. One readable doc, refreshed on sibling-package
|
|
91
|
+
release, citable from every consumer skill that touches memory.
|
|
92
|
+
|
|
93
|
+
## Consequences
|
|
94
|
+
|
|
95
|
+
- **Positive:** drift between sibling spec and consumer wiring lands
|
|
96
|
+
in one diffable file; the `present` / `misconfigured` / `absent`
|
|
97
|
+
contract is one citation away; new consumer skills don't have to
|
|
98
|
+
re-derive the envelope shape.
|
|
99
|
+
- **Negative:** the snapshot can lag the sibling package. Mitigated
|
|
100
|
+
by the explicit `Last refreshed:` line and the refresh policy in §
|
|
101
|
+
"Refresh policy" above.
|
|
102
|
+
- **Reversal cost:** delete the contract doc; consumers fall back to
|
|
103
|
+
reading the sibling spec directly. No code change required.
|
|
104
|
+
|
|
105
|
+
## References
|
|
106
|
+
|
|
107
|
+
- [`docs/contracts/agent-memory-contract.md`](../../contracts/agent-memory-contract.md) — the consumer-side snapshot.
|
|
108
|
+
- [`scripts/memory_status.py`](../../../scripts/memory_status.py) — three-state probe.
|
|
109
|
+
- [`scripts/memory_lookup.py`](../../../scripts/memory_lookup.py) — retrieval envelope source.
|
|
110
|
+
- [`agents/roadmaps/archive/agent-memory/`](../../../agents/roadmaps/archive/agent-memory/) — sibling-package spec.
|
|
111
|
+
- [`agents/roadmaps/step-11-ruflo-parity.md`](../../../agents/roadmaps/step-11-ruflo-parity.md) Phase 4 Step 3 — origin.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# ADRs — `memory`
|
|
2
|
+
|
|
3
|
+
> Memory MCP, propose / promote / poison flow, runtime-trust scoring.
|
|
4
|
+
|
|
5
|
+
Contract: [`docs/contracts/agent-memory-contract.md`](../../../docs/contracts/agent-memory-contract.md).
|
|
6
|
+
|
|
7
|
+
| # | Title | Status | Date | Supersedes |
|
|
8
|
+
|---|---|---|---|---|
|
|
9
|
+
| [0001](0001-consumer-side-snapshot.md) | Consumer Side Snapshot | — | — | — |
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# ADR 0001 — Three-tier rule router (kernel · tier-1 · tier-2)
|
|
2
|
+
|
|
3
|
+
> Area: `router` · Status: accepted · Date: 2026-05-16 · Type: retrospective
|
|
4
|
+
> Roadmap: `agents/roadmaps/step-11-ruflo-parity.md` Phase 4 Step 3
|
|
5
|
+
> Supersedes: —
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
Every rule in `.agent-src.uncompressed/rules/` loads into a host
|
|
10
|
+
agent's system prompt. Loading them all is wasteful (the workspace
|
|
11
|
+
budget is finite) and noisy (irrelevant rules degrade attention).
|
|
12
|
+
The kernel-membership work
|
|
13
|
+
([`docs/contracts/kernel-membership.md`](../../contracts/kernel-membership.md))
|
|
14
|
+
proved 9 rules are unconditionally relevant; the rest are
|
|
15
|
+
situational.
|
|
16
|
+
|
|
17
|
+
The router question is: **how does a non-kernel rule declare when it
|
|
18
|
+
fires, what artefacts carry its body, and how does the host agent
|
|
19
|
+
look that up cheaply at session start**.
|
|
20
|
+
|
|
21
|
+
## Decision
|
|
22
|
+
|
|
23
|
+
**Three tiers, declared in rule frontmatter, compiled into a single
|
|
24
|
+
[`router.json`](../../../router.json) at the repo root.** Host agents
|
|
25
|
+
read `router.json` once per session.
|
|
26
|
+
|
|
27
|
+
### Tier semantics
|
|
28
|
+
|
|
29
|
+
| Tier | Load behaviour | Workspace cost |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| `kernel` | Body injected verbatim every turn | High (capped per ADR-002 · ≤ 26k chars) |
|
|
32
|
+
| `tier-1` | Description stub injected; body loaded on trigger | Low (stub only) |
|
|
33
|
+
| `tier-2` | No injection; loaded only on explicit trigger match | Zero (until activated) |
|
|
34
|
+
|
|
35
|
+
The tier value sits in the rule's `tier:` frontmatter key; the
|
|
36
|
+
schema enforces the enum (`scripts/schemas/rule.schema.json`).
|
|
37
|
+
|
|
38
|
+
### Trigger vocabulary
|
|
39
|
+
|
|
40
|
+
Six match kinds, OR-combined across entries, AND-combined within an
|
|
41
|
+
entry's qualifier object (full grammar:
|
|
42
|
+
[`rule-router.md`](../../contracts/rule-router.md) § `triggers:` shape):
|
|
43
|
+
|
|
44
|
+
`keyword` · `phrase` · `intent` · `file_pattern` · `path_prefix` ·
|
|
45
|
+
`command`. Kernel rules **forbid** `triggers:` — they are
|
|
46
|
+
unconditional by definition.
|
|
47
|
+
|
|
48
|
+
### Compilation pipeline
|
|
49
|
+
|
|
50
|
+
1. `scripts/sync.py` projects `.agent-src.uncompressed/` → `.agent-src/`.
|
|
51
|
+
2. `scripts/compile_router.py` walks rule frontmatter, validates the
|
|
52
|
+
`routes_to:` targets exist on disk, writes `router.json`.
|
|
53
|
+
3. `scripts/skill_linter.py` runs the bidirectional check: every
|
|
54
|
+
`routes_to:` target has a matching `triggered_by:` back-ref.
|
|
55
|
+
|
|
56
|
+
### `routes_to:` resolution
|
|
57
|
+
|
|
58
|
+
Plain `<kind>:<id>` strings; kinds are `skill`, `guideline`,
|
|
59
|
+
`command`, `contract`. Resolution paths are pinned in
|
|
60
|
+
[`rule-router.md`](../../contracts/rule-router.md) lines 73–77 and
|
|
61
|
+
enforced by the linter.
|
|
62
|
+
|
|
63
|
+
## Considered alternatives
|
|
64
|
+
|
|
65
|
+
### Alt 1 — Single flat list (rejected)
|
|
66
|
+
|
|
67
|
+
All rules `always`-load.
|
|
68
|
+
|
|
69
|
+
**Why rejected:** the rules tree is ~70 entries; even with caveman
|
|
70
|
+
compression the workspace budget blows past the kernel cap. Static
|
|
71
|
+
loading wastes attention on rules irrelevant to the current turn.
|
|
72
|
+
|
|
73
|
+
### Alt 2 — Pure-runtime semantic search (rejected)
|
|
74
|
+
|
|
75
|
+
Embed every rule, semantic-match the turn against the index, load
|
|
76
|
+
top-k.
|
|
77
|
+
|
|
78
|
+
**Why rejected:** introduces a runtime (this package is a governance
|
|
79
|
+
layer, not a runtime — see step-11 scope boundary); index drift adds
|
|
80
|
+
a non-trivial maintenance surface; first-turn cold-start is slow.
|
|
81
|
+
|
|
82
|
+
### Alt 3 — Two tiers (kernel + load-on-trigger, rejected)
|
|
83
|
+
|
|
84
|
+
Skip the `tier-1` description-stub layer.
|
|
85
|
+
|
|
86
|
+
**Why rejected:** the stub layer carries 70 % of the "does this turn
|
|
87
|
+
need this rule?" signal at < 5 % of the body cost. Removing it
|
|
88
|
+
forces the host agent to either over-load (cost spike) or
|
|
89
|
+
mis-trigger (correctness loss).
|
|
90
|
+
|
|
91
|
+
### Alt 4 — Three-tier with frontmatter declaration (accepted)
|
|
92
|
+
|
|
93
|
+
The chosen path. Kernel + tier-1 stubs (balanced + full profiles) +
|
|
94
|
+
tier-2 (full profile only). Cost stays bounded; trigger declarations
|
|
95
|
+
diff cleanly in PRs.
|
|
96
|
+
|
|
97
|
+
## Consequences
|
|
98
|
+
|
|
99
|
+
- **Positive:** every rule declares its activation cost; the kernel
|
|
100
|
+
cap is enforceable; the host agent's session-start cost is one
|
|
101
|
+
JSON read; the `routes_to:` link makes "where does this rule's
|
|
102
|
+
body live?" answerable without grep.
|
|
103
|
+
- **Negative:** two layers of indirection (rule → stub → body)
|
|
104
|
+
raise the bar for new contributors. Mitigated by
|
|
105
|
+
[`rule-router.md`](../../contracts/rule-router.md) being the
|
|
106
|
+
single citable contract and the linter catching shape errors.
|
|
107
|
+
- **Reversal cost:** flatten by removing tier-1 / tier-2 distinction
|
|
108
|
+
in the compiler — `router.json` becomes a list of all rules. The
|
|
109
|
+
rule frontmatter stays valid (extra fields are tolerated by
|
|
110
|
+
Draft-07 once `additionalProperties` is relaxed).
|
|
111
|
+
|
|
112
|
+
## References
|
|
113
|
+
|
|
114
|
+
- [`docs/contracts/rule-router.md`](../../contracts/rule-router.md) — frontmatter contract.
|
|
115
|
+
- [`docs/contracts/kernel-membership.md`](../../contracts/kernel-membership.md) — kernel cap.
|
|
116
|
+
- [`router.json`](../../../router.json) — compiled output.
|
|
117
|
+
- [`scripts/compile_router.py`](../../../scripts/compile_router.py) — compiler.
|
|
118
|
+
- [`scripts/schemas/rule.schema.json`](../../../scripts/schemas/rule.schema.json) — schema.
|
|
119
|
+
- [`agents/roadmaps/step-11-ruflo-parity.md`](../../../agents/roadmaps/step-11-ruflo-parity.md) Phase 4 Step 3 — origin.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# ADRs — `router`
|
|
2
|
+
|
|
3
|
+
> router.json shape, tier semantics, dispatch precedence.
|
|
4
|
+
|
|
5
|
+
Contract: [`docs/contracts/rule-router.md`](../../../docs/contracts/rule-router.md).
|
|
6
|
+
|
|
7
|
+
| # | Title | Status | Date | Supersedes |
|
|
8
|
+
|---|---|---|---|---|
|
|
9
|
+
| [0001](0001-three-tier-routing.md) | Three Tier Routing | — | — | — |
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# ADR 0001 — JSON Schema as the frontmatter source of truth
|
|
2
|
+
|
|
3
|
+
> Area: `schema` · Status: accepted · Date: 2026-05-16 · Type: retrospective
|
|
4
|
+
> Roadmap: `agents/roadmaps/step-11-ruflo-parity.md` Phase 4 Step 3
|
|
5
|
+
> Supersedes: —
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
Skills, rules, commands, and personas all declare YAML frontmatter
|
|
10
|
+
with required and optional keys. Validation needs to be:
|
|
11
|
+
|
|
12
|
+
1. Machine-checkable on every PR (no "guideline" enforcement).
|
|
13
|
+
2. Diff-readable so the contract drift is visible.
|
|
14
|
+
3. Tool-agnostic — the same artefacts ship to Claude, Cursor, Cline,
|
|
15
|
+
Windsurf, and Augment, all of which parse the same YAML.
|
|
16
|
+
|
|
17
|
+
The contract is documented for humans in
|
|
18
|
+
[`agents/docs/frontmatter-contract.md`](../../../agents/docs/frontmatter-contract.md);
|
|
19
|
+
the question this ADR records is **how that contract is enforced**.
|
|
20
|
+
|
|
21
|
+
## Decision
|
|
22
|
+
|
|
23
|
+
**JSON Schema (Draft-07) files in
|
|
24
|
+
[`scripts/schemas/`](../../../scripts/schemas/) are the
|
|
25
|
+
machine-readable source of truth.** The human contract document
|
|
26
|
+
defers to the schema (`$comment` in each schema file pins
|
|
27
|
+
`agents/docs/frontmatter-contract.md` as the source).
|
|
28
|
+
|
|
29
|
+
### Schema files
|
|
30
|
+
|
|
31
|
+
| Type | Schema | Validator entry-point |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| Skill | `scripts/schemas/skill.schema.json` | `scripts/skill_linter.py` |
|
|
34
|
+
| Rule | `scripts/schemas/rule.schema.json` | `scripts/skill_linter.py` |
|
|
35
|
+
| Command | `scripts/schemas/command.schema.json` | `scripts/validate_frontmatter.py` |
|
|
36
|
+
| Persona | `scripts/schemas/persona.schema.json` | `scripts/validate_frontmatter.py` |
|
|
37
|
+
|
|
38
|
+
### Required-key threshold
|
|
39
|
+
|
|
40
|
+
A key is **required** (in the schema's `required:` array) if ≥ 95 %
|
|
41
|
+
of files in the type declare it. Everything else is optional. The
|
|
42
|
+
threshold is documented inline in
|
|
43
|
+
[`frontmatter-contract.md`](../../../agents/docs/frontmatter-contract.md)
|
|
44
|
+
§ "Definition of required". Re-derive counts with
|
|
45
|
+
`python3 scripts/inventory_frontmatter.py`.
|
|
46
|
+
|
|
47
|
+
### Validation hooks
|
|
48
|
+
|
|
49
|
+
- `task lint-skills` — runs `skill_linter.py` against all skills + rules.
|
|
50
|
+
- `task ci` — wraps `lint-skills` plus router + smoke smokes.
|
|
51
|
+
- Smoke contract `scripts/smoke/schema.sh` — fast random-sample check
|
|
52
|
+
for PRs touching `.agent-src.uncompressed/**` (see
|
|
53
|
+
[`docs/contracts/smoke-contracts.md`](../../contracts/smoke-contracts.md)).
|
|
54
|
+
|
|
55
|
+
## Considered alternatives
|
|
56
|
+
|
|
57
|
+
### Alt 1 — Inline regex in the linter (rejected)
|
|
58
|
+
|
|
59
|
+
Hard-code shape checks in `skill_linter.py`.
|
|
60
|
+
|
|
61
|
+
**Why rejected:** the linter becomes the contract, the contract is
|
|
62
|
+
hidden in Python, and the artefacts can't be validated by external
|
|
63
|
+
tools (CI, editors, IDE plugins). Cross-tool portability is the
|
|
64
|
+
whole point of YAML frontmatter — the schema must be portable too.
|
|
65
|
+
|
|
66
|
+
### Alt 2 — Pydantic / dataclass models (rejected)
|
|
67
|
+
|
|
68
|
+
Validate via typed Python models.
|
|
69
|
+
|
|
70
|
+
**Why rejected:** ties validation to Python runtime, prevents
|
|
71
|
+
JS/TS / Node tooling from reusing the same contract, and forces a
|
|
72
|
+
non-trivial dependency on every consumer that wants to validate
|
|
73
|
+
their own artefacts. JSON Schema is the lingua franca.
|
|
74
|
+
|
|
75
|
+
### Alt 3 — JSON Schema Draft-07 (accepted)
|
|
76
|
+
|
|
77
|
+
The chosen path. One source-of-truth file per artefact type,
|
|
78
|
+
referenced by Python linter today, reusable by Node / VS Code /
|
|
79
|
+
JetBrains / any JSON-Schema-aware tool tomorrow.
|
|
80
|
+
|
|
81
|
+
## Consequences
|
|
82
|
+
|
|
83
|
+
- **Positive:** schemas are diffable; new keys land via PR with
|
|
84
|
+
reviewable shape changes; non-Python tools can validate the same
|
|
85
|
+
contract; the linter stays thin.
|
|
86
|
+
- **Negative:** Draft-07 is older than Draft-2020-12; some keyword
|
|
87
|
+
niceties (`unevaluatedProperties`, conditional `then`/`else`) are
|
|
88
|
+
awkward. Mitigated by `additionalProperties: false` plus
|
|
89
|
+
`oneOf` / `if`-then composition where needed.
|
|
90
|
+
- **Reversal cost:** the linter is the only consumer today; replacing
|
|
91
|
+
the schema with Pydantic models would be a one-PR swap. The choice
|
|
92
|
+
is reversible without contract churn.
|
|
93
|
+
|
|
94
|
+
## References
|
|
95
|
+
|
|
96
|
+
- [`scripts/schemas/skill.schema.json`](../../../scripts/schemas/skill.schema.json) — skill contract.
|
|
97
|
+
- [`scripts/schemas/rule.schema.json`](../../../scripts/schemas/rule.schema.json) — rule contract.
|
|
98
|
+
- [`scripts/schemas/command.schema.json`](../../../scripts/schemas/command.schema.json) — command contract.
|
|
99
|
+
- [`scripts/schemas/persona.schema.json`](../../../scripts/schemas/persona.schema.json) — persona contract.
|
|
100
|
+
- [`agents/docs/frontmatter-contract.md`](../../../agents/docs/frontmatter-contract.md) — human-readable contract.
|
|
101
|
+
- [`scripts/skill_linter.py`](../../../scripts/skill_linter.py) — primary validator.
|
|
102
|
+
- [`agents/roadmaps/step-11-ruflo-parity.md`](../../../agents/roadmaps/step-11-ruflo-parity.md) Phase 4 Step 3 — origin.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# ADRs — `schema`
|
|
2
|
+
|
|
3
|
+
> Frontmatter schemas, v2 rigor, lint behaviour for skills / rules / commands.
|
|
4
|
+
|
|
5
|
+
Contract: [`agents/docs/frontmatter-contract.md`](../../../agents/docs/frontmatter-contract.md).
|
|
6
|
+
|
|
7
|
+
| # | Title | Status | Date | Supersedes |
|
|
8
|
+
|---|---|---|---|---|
|
|
9
|
+
| [0001](0001-json-schema-frontmatter.md) | Json Schema Frontmatter | — | — | — |
|