@event4u/agent-config 2.18.0 → 2.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-status.md +29 -0
- package/.agent-src/commands/onboard.md +221 -81
- package/.agent-src/commands/refine-ticket.md +3 -0
- 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/personas/README.md +8 -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/refine-ticket/SKILL.md +3 -0
- 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/.agent-src/user-types/README.md +124 -0
- package/.agent-src/user-types/_template/user-type.md +95 -0
- package/.agent-src/user-types/galabau-field-crew.md +100 -0
- package/.agent-src/user-types/metalworking-shop.md +105 -0
- package/.agent-src/user-types/truck-driver.md +113 -0
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +91 -30
- 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/contracts/adr-layout.md +108 -0
- package/docs/contracts/adr-mcp-runtime.md +128 -0
- package/docs/contracts/adr-user-types-axis.md +127 -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/user-type-schema.md +146 -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/docs/recruits/_template.md +81 -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/compress.py +48 -2
- 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/schemas/user-type.schema.json +35 -0
- package/scripts/skill_linter.py +139 -4
- package/scripts/skill_overlap.py +204 -0
- package/scripts/skill_tools/audit_user_type_coverage.py +148 -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,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 | — | — | — |
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# ADR 0001 — Per-tier smoke scripts (kernel · router · schema · skills)
|
|
2
|
+
|
|
3
|
+
> Area: `smoke` · 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
|
+
The North-Star audit
|
|
10
|
+
([`external-findings.md § 5`](../../../agents/audit-2026-05-14-north-star/external-findings.md))
|
|
11
|
+
flagged "smoke contracts" as an absorbed Ruflo pattern: every
|
|
12
|
+
high-traffic tier needs a fast, deterministic, measurable check that
|
|
13
|
+
runs in CI and surfaces regressions before they reach the rules /
|
|
14
|
+
router / schema / skill linter pipelines.
|
|
15
|
+
|
|
16
|
+
The full `task ci` run is ≥ 90 s and exercises every linter. That's
|
|
17
|
+
fine for merge gates; it's too slow for path-change feedback on PRs
|
|
18
|
+
that touch one tier in isolation.
|
|
19
|
+
|
|
20
|
+
## Decision
|
|
21
|
+
|
|
22
|
+
**One smoke script per tier, each ≤ 30 s, each emitting a baseline
|
|
23
|
+
declaration as its last stdout line.** Scripts live under
|
|
24
|
+
[`scripts/smoke/`](../../../scripts/smoke/):
|
|
25
|
+
|
|
26
|
+
| Tier | Script | Validates | Path-trigger globs |
|
|
27
|
+
|---|---|---|---|
|
|
28
|
+
| Kernel | [`kernel.sh`](../../../scripts/smoke/kernel.sh) | 9 kernel rules present, char-budget respected | `.agent-src.uncompressed/rules/**`, `docs/contracts/kernel-membership.md` |
|
|
29
|
+
| Router | [`router.sh`](../../../scripts/smoke/router.sh) | `router.json` compiles, all `routes_to:` resolve | `router.json`, `.agent-src.uncompressed/rules/**` |
|
|
30
|
+
| Schema | [`schema.sh`](../../../scripts/smoke/schema.sh) | Random skill / rule sample validates against JSON Schema | `scripts/schemas/**`, `.agent-src.uncompressed/{rules,skills}/**` |
|
|
31
|
+
| Skills | [`skills.sh`](../../../scripts/smoke/skills.sh) | 5 random skills pass frontmatter + `name == dir` | `.agent-src.uncompressed/skills/**` |
|
|
32
|
+
|
|
33
|
+
### Runtime contract
|
|
34
|
+
|
|
35
|
+
Per [`smoke-contracts.md`](../../contracts/smoke-contracts.md) § 1:
|
|
36
|
+
|
|
37
|
+
| Limit | Value |
|
|
38
|
+
|---|---:|
|
|
39
|
+
| Wall time | ≤ 30 s |
|
|
40
|
+
| External I/O | filesystem only — no network, no MCP |
|
|
41
|
+
| Output | last stdout line = baseline declaration |
|
|
42
|
+
| Exit code | non-zero on baseline regression |
|
|
43
|
+
|
|
44
|
+
### CI wiring
|
|
45
|
+
|
|
46
|
+
[`.github/workflows/smoke.yml`](../../../.github/workflows/smoke.yml)
|
|
47
|
+
dispatches each smoke independently on path-trigger match. Local
|
|
48
|
+
aggregator: `task smoke` (sub-tasks `task smoke:{kernel,router,schema,skills}`)
|
|
49
|
+
wired in [`taskfiles/engine.yml`](../../../taskfiles/engine.yml).
|
|
50
|
+
|
|
51
|
+
### Baseline declarations (lock-in 2026-05-16)
|
|
52
|
+
|
|
53
|
+
- Kernel: `9 rules · 23 / 26 kB used (88 %) · 0 fence breaches`.
|
|
54
|
+
- Router: `tier_1: N · tier_2: M · 0 unresolved routes`.
|
|
55
|
+
- Schema: deterministic seed = epoch day · 10 random files validated.
|
|
56
|
+
- Skills: deterministic seed = epoch day · `210 skills · 5/5 pass`.
|
|
57
|
+
|
|
58
|
+
## Considered alternatives
|
|
59
|
+
|
|
60
|
+
### Alt 1 — One monolithic smoke (rejected)
|
|
61
|
+
|
|
62
|
+
Single `task smoke` running every check.
|
|
63
|
+
|
|
64
|
+
**Why rejected:** path-change PRs pay the full cost every time;
|
|
65
|
+
flaky tier-X regression masks tier-Y signal; output is harder to
|
|
66
|
+
diff. The per-tier split costs four files and saves CI minutes.
|
|
67
|
+
|
|
68
|
+
### Alt 2 — Inline-in-`task ci` only (rejected)
|
|
69
|
+
|
|
70
|
+
Skip the smoke layer; rely on `task ci` for everything.
|
|
71
|
+
|
|
72
|
+
**Why rejected:** `task ci` is the merge gate, not the feedback
|
|
73
|
+
loop. Smokes are the cheap-and-fast layer between push and review.
|
|
74
|
+
|
|
75
|
+
### Alt 3 — Per-tier, ≤ 30 s budget, baseline-declaring (accepted)
|
|
76
|
+
|
|
77
|
+
The chosen path. One script per tier, declared budget, declared
|
|
78
|
+
baseline, CI-dispatched on path-trigger.
|
|
79
|
+
|
|
80
|
+
## Consequences
|
|
81
|
+
|
|
82
|
+
- **Positive:** PRs touching one tier get tier-specific feedback in
|
|
83
|
+
≤ 30 s; baseline declarations are diff-readable so regressions
|
|
84
|
+
surface in PR descriptions; the `task ci` merge gate stays the
|
|
85
|
+
authoritative full-run.
|
|
86
|
+
- **Negative:** four scripts to maintain, one workflow file, one
|
|
87
|
+
taskfile entry. Mitigated by the runtime contract — a smoke that
|
|
88
|
+
approaches 30 s gets split, not optimised in place.
|
|
89
|
+
- **Reversal cost:** delete `smoke.yml`; the scripts stay as opt-in
|
|
90
|
+
local checks (`task smoke:*`). No contract churn.
|
|
91
|
+
|
|
92
|
+
## References
|
|
93
|
+
|
|
94
|
+
- [`docs/contracts/smoke-contracts.md`](../../contracts/smoke-contracts.md) — runtime + path-trigger contract.
|
|
95
|
+
- [`scripts/smoke/`](../../../scripts/smoke/) — four scripts.
|
|
96
|
+
- [`.github/workflows/smoke.yml`](../../../.github/workflows/smoke.yml) — CI dispatch.
|
|
97
|
+
- [`taskfiles/engine.yml`](../../../taskfiles/engine.yml) — local aggregator.
|
|
98
|
+
- [`agents/audit-2026-05-14-north-star/external-findings.md`](../../../agents/audit-2026-05-14-north-star/external-findings.md) § 5 — origin pattern.
|
|
99
|
+
- [`agents/roadmaps/step-11-ruflo-parity.md`](../../../agents/roadmaps/step-11-ruflo-parity.md) Phase 3 (delivery) + Phase 4 Step 3 (this ADR).
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# ADRs — `smoke`
|
|
2
|
+
|
|
3
|
+
> Per-tier smoke contracts, baseline locks, regression gates.
|
|
4
|
+
|
|
5
|
+
Contract: [`docs/contracts/smoke-contracts.md`](../../../docs/contracts/smoke-contracts.md).
|
|
6
|
+
|
|
7
|
+
| # | Title | Status | Date | Supersedes |
|
|
8
|
+
|---|---|---|---|---|
|
|
9
|
+
| [0001](0001-per-tier-smoke-scripts.md) | Per Tier Smoke Scripts | — | — | — |
|