@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,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
stability: beta
|
|
3
|
+
keep-beta-until: 2026-08-14
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Profile System — Contract
|
|
7
|
+
|
|
8
|
+
> **Status:** beta · **Owner:** package maintainer · **Last reviewed:** 2026-05-16
|
|
9
|
+
>
|
|
10
|
+
> Schema and semantics for the **Profile** axis introduced in step-15
|
|
11
|
+
> Phase 1 item 1. Profile answers *who is the user?* — audience
|
|
12
|
+
> taxonomy that selects the default skill/command surface, README
|
|
13
|
+
> entry-paragraph, and persona pre-selection. Boundary against
|
|
14
|
+
> `preset.id`, `pack.id`, and `cost_profile`:
|
|
15
|
+
> [`ADR-010`](../decisions/ADR-010-profile-pack-preset-boundary.md).
|
|
16
|
+
|
|
17
|
+
## Decision
|
|
18
|
+
|
|
19
|
+
A **profile** declares the user's audience identity. Six seed profiles
|
|
20
|
+
ship; users can declare their own under
|
|
21
|
+
`.agent-src.uncompressed/profiles/<id>.yml`.
|
|
22
|
+
|
|
23
|
+
| `profile.id` | Audience | README entry-paragraph | Default `preset.id` |
|
|
24
|
+
|---|---|---|---|
|
|
25
|
+
| `founder` | Solo / early-stage founder; wears every hat | "Ship the company, not the codebase" | `fast` |
|
|
26
|
+
| `developer` | IC engineer; primary day-to-day user today | "Pair with a senior reviewer that never sleeps" | `balanced` |
|
|
27
|
+
| `content_creator` | Writers, ghostwriters, marketers | "Your voice, my hands" | `balanced` |
|
|
28
|
+
| `agency` | Multi-client delivery shop | "Same playbook across every client repo" | `strict` |
|
|
29
|
+
| `finance` | CFO / fractional finance / FP&A | "Forecasts and memos with the receipts attached" | `strict` |
|
|
30
|
+
| `ops` | RevOps, support, SRE-adjacent | "Procedures that get followed, not skipped" | `strict` |
|
|
31
|
+
|
|
32
|
+
The seed set is **fixed for v2.x**. Adding a seventh profile requires
|
|
33
|
+
an ADR — the contract surface that ships in the wizard
|
|
34
|
+
(`/onboard` role-selection) treats this set as exhaustive.
|
|
35
|
+
|
|
36
|
+
## Profile shape
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
profile:
|
|
40
|
+
id: developer
|
|
41
|
+
audience:
|
|
42
|
+
label: "IC engineer"
|
|
43
|
+
readme_anchor: "developer" # selects README first-screen block
|
|
44
|
+
defaults:
|
|
45
|
+
preset_id: balanced # may be overridden by .agent-settings.yml
|
|
46
|
+
personas: [reviewer, security] # pre-selected persona ids
|
|
47
|
+
skills_hint: [developer-like-execution, verify-before-complete, minimal-safe-diff]
|
|
48
|
+
surface:
|
|
49
|
+
commands_hint: [work, implement-ticket, review-changes, fix]
|
|
50
|
+
docs_first_pointer: "docs/getting-started-by-role.md#developer"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Per [ADR-010](../decisions/ADR-010-profile-pack-preset-boundary.md), a
|
|
54
|
+
profile **MAY** set `defaults.preset_id` but **MAY NOT** set any
|
|
55
|
+
preset-owned knob directly. The lint task (`task lint-config-schema`)
|
|
56
|
+
enforces this.
|
|
57
|
+
|
|
58
|
+
## Loader contract
|
|
59
|
+
|
|
60
|
+
The Phase 1 loader lives at `scripts/config/profiles.py`. Resolution
|
|
61
|
+
chain (last writer wins):
|
|
62
|
+
|
|
63
|
+
1. `pack.profile_id` (if pack active) → `profile.id`.
|
|
64
|
+
2. `.agent-settings.yml` top-level `profile:` block → `profile.id`
|
|
65
|
+
and any user overrides for `audience` / `defaults` / `surface`.
|
|
66
|
+
3. Environment variable `AGENT_CONFIG_PROFILE_ID` → `profile.id`.
|
|
67
|
+
4. Runtime CLI flag `--profile=<id>` → `profile.id`, single session.
|
|
68
|
+
|
|
69
|
+
If no profile resolves, the loader **does not pick a default
|
|
70
|
+
silently** — it falls back to `developer` only when
|
|
71
|
+
`.agent-settings.yml` is missing entirely (fresh install before
|
|
72
|
+
`/onboard`). With a settings file present but no `profile:` block,
|
|
73
|
+
the loader raises a structured warning pointing to `/onboard`.
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
RATIONALE: a silent default would hide the "I never picked an audience"
|
|
77
|
+
state from the wizard, breaking the council v3 observation that audience
|
|
78
|
+
choice must be a deliberate act of the user, not an agent inference.
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Resolution outcome
|
|
82
|
+
|
|
83
|
+
After the loader runs, the session has:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
{
|
|
87
|
+
"id": "developer",
|
|
88
|
+
"audience": {"label": "IC engineer", "readme_anchor": "developer"},
|
|
89
|
+
"preset_id": "balanced",
|
|
90
|
+
"personas": ["reviewer", "security"],
|
|
91
|
+
"skills_hint": ["developer-like-execution", ...],
|
|
92
|
+
"commands_hint": ["work", "implement-ticket", ...],
|
|
93
|
+
"source": "user-settings | env | runtime | pack | default",
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The `source` field is mandatory and feeds the
|
|
98
|
+
`/agent-config explain`
|
|
99
|
+
command (Phase 1 item 3).
|
|
100
|
+
|
|
101
|
+
## User-defined profiles
|
|
102
|
+
|
|
103
|
+
A consumer project MAY ship a custom profile under
|
|
104
|
+
`.agent-src.uncompressed/profiles/<id>.yml`. Constraints:
|
|
105
|
+
|
|
106
|
+
- `id` MUST be unique across seed + user-defined profiles.
|
|
107
|
+
- Shape MUST match the seed contract above (audience / defaults / surface).
|
|
108
|
+
- `defaults.preset_id` MUST reference an existing preset
|
|
109
|
+
([`config-presets.md`](config-presets.md)).
|
|
110
|
+
- The lint task hard-fails on schema violations.
|
|
111
|
+
|
|
112
|
+
User-defined profiles do **not** require an ADR — they are project-local.
|
|
113
|
+
Only changes to the **seed set** require an ADR.
|
|
114
|
+
|
|
115
|
+
## Drift detection
|
|
116
|
+
|
|
117
|
+
`task lint-config-schema` (added in Phase 1) hard-fails when:
|
|
118
|
+
|
|
119
|
+
- A profile YAML names a preset-owned knob (cost cap, autonomy,
|
|
120
|
+
confidence, risk).
|
|
121
|
+
- A profile YAML references a non-existent `preset_id`.
|
|
122
|
+
- The seed-profile count diverges from this contract's table.
|
|
123
|
+
- `defaults.personas` references a persona id that does not exist
|
|
124
|
+
under `.agent-src.uncompressed/personas/`.
|
|
125
|
+
|
|
126
|
+
## Non-goals
|
|
127
|
+
|
|
128
|
+
- This contract does **not** define preset knobs. See
|
|
129
|
+
[`config-presets.md`](config-presets.md).
|
|
130
|
+
- It does **not** define packs. See `workflow-packs.md` (Phase 2 item 7).
|
|
131
|
+
- It does **not** override `cost_profile`. The rule-tier loader keeps
|
|
132
|
+
its independent axis per
|
|
133
|
+
[`cost-profile-defaults.md`](cost-profile-defaults.md).
|
|
134
|
+
- It does **not** ship a UI. Profile selection happens in `/onboard`
|
|
135
|
+
(step-15 Phase 1 item 2).
|
|
136
|
+
|
|
137
|
+
## See also
|
|
138
|
+
|
|
139
|
+
- [`ADR-010`](../decisions/ADR-010-profile-pack-preset-boundary.md) — axis boundary.
|
|
140
|
+
- [`config-presets.md`](config-presets.md) — preset knobs.
|
|
141
|
+
- [`cost-profile-defaults.md`](cost-profile-defaults.md) — rule-tier axis (orthogonal).
|
|
142
|
+
- `step-15-product-refinement` — Phase 1 item 1.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
stability: beta
|
|
3
|
+
keep-beta-until: 2026-08-12
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Universal safety model
|
|
7
|
+
|
|
8
|
+
> **Status:** beta — first draft 2026-05-16 (Phase 2 Item 9 of
|
|
9
|
+
> `step-15-product-refinement`).
|
|
10
|
+
>
|
|
11
|
+
> **Baseline:** [`docs/architecture/current-safety-behavior.md`](../architecture/current-safety-behavior.md)
|
|
12
|
+
> documents the pre-step-15 surface this contract replaces.
|
|
13
|
+
|
|
14
|
+
A **per-profile, per-domain safety policy** declared as a single
|
|
15
|
+
machine-readable table. Replaces the legacy "one autonomy switch for
|
|
16
|
+
everything" model documented in the baseline. Does **not** weaken the
|
|
17
|
+
four non-overridable floors — those keep their universal scope and
|
|
18
|
+
are referenced by id, not redeclared here.
|
|
19
|
+
|
|
20
|
+
## The Iron Floor
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
NO POLICY ENTRY MAY WIDEN AN EXISTING FLOOR.
|
|
24
|
+
ANY ENTRY THAT WOULD ALLOW A FLOOR-BLOCKED ACTION IS REJECTED AT LINT.
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The four floors are listed in
|
|
28
|
+
[`current-safety-behavior § The four non-overridable floors`](../architecture/current-safety-behavior.md#the-four-non-overridable-floors):
|
|
29
|
+
`non-destructive-by-default`, `scope-control § git-ops`,
|
|
30
|
+
`commit-policy`, `security-sensitive-stop`. Floor membership is
|
|
31
|
+
maintained in [`kernel-membership`](kernel-membership.md); a domain
|
|
32
|
+
listed there cannot be set to `allow` here.
|
|
33
|
+
|
|
34
|
+
## Schema
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
# .agent-src.uncompressed/profiles/<id>.yml — new top-level key
|
|
38
|
+
profile:
|
|
39
|
+
id: <profile.id>
|
|
40
|
+
# ... existing fields ...
|
|
41
|
+
safety:
|
|
42
|
+
domains:
|
|
43
|
+
<domain-id>:
|
|
44
|
+
policy: <deny | ask | allow>
|
|
45
|
+
rationale: "<= 280 chars — why this policy for this profile>"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Domain registry
|
|
49
|
+
|
|
50
|
+
Domains are declared in this contract, **not** invented per profile.
|
|
51
|
+
A profile may only reference an id from the table below.
|
|
52
|
+
|
|
53
|
+
| Domain id | What it gates | Floor reference |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| `prod_data` | Reads / writes against production data stores. | `non-destructive-by-default` |
|
|
56
|
+
| `prod_infra` | Terraform / k8s / cloud config touching prod. | `non-destructive-by-default` |
|
|
57
|
+
| `secrets` | Secret values in env, config, or output. | `security-sensitive-stop` |
|
|
58
|
+
| `auth_changes` | Auth, session, tenant-boundary, IAM edits. | `security-sensitive-stop` |
|
|
59
|
+
| `billing` | Pricing, invoicing, refund, payout logic. | `security-sensitive-stop` |
|
|
60
|
+
| `bulk_delete` | `rm -rf`, `DROP`, `TRUNCATE`, ≥ 5-file deletion. | `non-destructive-by-default` |
|
|
61
|
+
| `git_push` | `git push` to any remote. | `scope-control § git-ops` |
|
|
62
|
+
| `git_branch` | branch create / switch / delete. | `scope-control § git-ops` |
|
|
63
|
+
| `commit` | Any git commit. | `commit-policy` |
|
|
64
|
+
| `mcp_call_costly` | MCP / web / model call ≥ preset's `per_call_max_usd`. | — (advisory) |
|
|
65
|
+
| `pii_redact` | PII redaction in support / finance / recruiting / marketing outputs. | `domain-safety-pii-*` |
|
|
66
|
+
| `pii_log` | Logging of raw PII. | `domain-safety-logging-pii-floor` |
|
|
67
|
+
| `legal_advice` | Output shaped as legal advice. | `domain-safety-disclaimer-legal` |
|
|
68
|
+
| `medical_advice` | Output shaped as medical advice. | `domain-safety-disclaimer-medical` |
|
|
69
|
+
| `financial_advice` | Investment / tax / valuation positions. | `domain-safety-disclaimer-financial` |
|
|
70
|
+
| `pr_create` | Pull-request open / close / retarget. | `scope-control § git-ops` |
|
|
71
|
+
| `deploy` | Deploy / release / tag / pipeline trigger. | `non-destructive-by-default` |
|
|
72
|
+
|
|
73
|
+
### Policy semantics
|
|
74
|
+
|
|
75
|
+
| Policy | Behaviour | Floor interaction |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| `deny` | The agent refuses. Numbered-option block surfaces the refusal and the rationale field; no override path. | `deny` is the default for every floor domain — it cannot be relaxed. |
|
|
78
|
+
| `ask` | The agent stops and asks a single numbered question per [`user-interaction`](../../.agent-src/rules/user-interaction.md). One question per turn. | `ask` is the default for every floor domain in a profile that has not opted out — the floor remains operative even when `policy=allow` is set elsewhere. |
|
|
79
|
+
| `allow` | The agent proceeds without asking. Trivial-question suppression applies. | `allow` is **forbidden** on any domain whose `Floor reference` column is non-empty. Linter rejects it. |
|
|
80
|
+
|
|
81
|
+
The legacy single switch (`personal.autonomy`) is preserved as a
|
|
82
|
+
**fallback** for any domain a profile does not declare — keeping
|
|
83
|
+
existing installs functional while profiles migrate.
|
|
84
|
+
|
|
85
|
+
## Resolution
|
|
86
|
+
|
|
87
|
+
Order (last writer wins, subject to the Iron Floor):
|
|
88
|
+
|
|
89
|
+
1. Domain default = `ask` for floor domains, `allow` otherwise.
|
|
90
|
+
2. Profile `safety.domains.<id>.policy`.
|
|
91
|
+
3. Active pack's profile (if `--pack <id>` is active).
|
|
92
|
+
4. `.agent-settings.yml` user override under `profile.safety.domains`.
|
|
93
|
+
|
|
94
|
+
The explain command at [`explain config`](../../.agent-src/scripts/agent-config)
|
|
95
|
+
(Phase 1 Item 3 deliverable) surfaces the resolved policy per domain,
|
|
96
|
+
with the writer source per row.
|
|
97
|
+
|
|
98
|
+
## Validation
|
|
99
|
+
|
|
100
|
+
`scripts/lint_safety_model.py` (Phase 2 deliverable — not yet
|
|
101
|
+
shipped) fails CI on:
|
|
102
|
+
|
|
103
|
+
- Unknown domain id.
|
|
104
|
+
- `allow` on a floor-referenced domain.
|
|
105
|
+
- Missing `rationale` (≤ 280 chars, plain prose).
|
|
106
|
+
- Profile declaring `safety` without at least one entry.
|
|
107
|
+
|
|
108
|
+
Until the linter lands, profiles are reviewed by hand at PR time.
|
|
109
|
+
|
|
110
|
+
## What this contract does **not** do
|
|
111
|
+
|
|
112
|
+
- **Does not** introduce new safety rules. Every domain row maps to
|
|
113
|
+
an existing rule or to advisory cost guidance.
|
|
114
|
+
- **Does not** ship the loader. `scripts/config/safety.py` is a
|
|
115
|
+
Phase 2 deliverable deferred to its own step.
|
|
116
|
+
- **Does not** override domain-safety output floors. PII redaction
|
|
117
|
+
and disclaimer rules apply regardless of `safety.domains.*` —
|
|
118
|
+
`policy=allow` on `pii_redact` means "do not ask before redacting",
|
|
119
|
+
not "skip redaction".
|
|
120
|
+
- **Does not** authorize per-tool MCP overrides. Cost caps live in
|
|
121
|
+
[`config-presets`](config-presets.md).
|
|
122
|
+
|
|
123
|
+
## See also
|
|
124
|
+
|
|
125
|
+
- [`current-safety-behavior`](../architecture/current-safety-behavior.md) — pre-step-15 baseline (what this replaces)
|
|
126
|
+
- [`config-presets`](config-presets.md) — cost caps and enforcement
|
|
127
|
+
- [`profile-system`](profile-system.md) — profile axis
|
|
128
|
+
- [`workflow-packs`](workflow-packs.md) — pack-level overrides
|
|
129
|
+
- `step-15-product-refinement` § Phase 2 Item 9
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
---
|
|
2
|
+
stability: beta
|
|
3
|
+
keep-beta-until: 2026-08-14
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Smoke Contracts — Phase 3 of step-11-ruflo-parity
|
|
7
|
+
|
|
8
|
+
> **Status:** active · **Owner:** step-11 Phase 3 · **Sibling:**
|
|
9
|
+
> [`measurement-baseline.md`](measurement-baseline.md) (snapshot semantics)
|
|
10
|
+
> · [`cost-enforcement.md`](cost-enforcement.md) (cost ladder)
|
|
11
|
+
|
|
12
|
+
Per-tier smoke scripts validate the system's structural baselines on
|
|
13
|
+
every PR that touches the tier. Each script is **fast** (≤ 30 s wall),
|
|
14
|
+
**deterministic** (same input → same exit), and **measured** (baseline
|
|
15
|
+
numbers come from `task smoke:*` on `main` at lock-in, not from claims).
|
|
16
|
+
|
|
17
|
+
## § 1 — Runtime budget
|
|
18
|
+
|
|
19
|
+
Every `scripts/smoke/<tier>.sh` honours:
|
|
20
|
+
|
|
21
|
+
| Limit | Value | Rationale |
|
|
22
|
+
|---|---:|---|
|
|
23
|
+
| Wall time | ≤ 30 s | CI matrix slot; local dev iteration |
|
|
24
|
+
| External I/O | none beyond filesystem | no network, no MCP |
|
|
25
|
+
| Output | last line is the **baseline declaration** | parseable by CI summary |
|
|
26
|
+
|
|
27
|
+
A smoke that approaches 30 s should be split into sub-smokes, not
|
|
28
|
+
optimised in place.
|
|
29
|
+
|
|
30
|
+
## § 2 — Path-trigger globs
|
|
31
|
+
|
|
32
|
+
CI's `.github/workflows/smoke.yml` dispatches the right scripts based on
|
|
33
|
+
the paths touched in the PR:
|
|
34
|
+
|
|
35
|
+
| Tier | Globs that trigger | Script |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| kernel | `.agent-src.uncompressed/rules/**`, `.agent-src/rules/**`, `router.json`, `scripts/measure_rule_budget.py` | `scripts/smoke/kernel.sh` |
|
|
38
|
+
| router | `router.json`, `.agent-src.uncompressed/rules/**`, `.agent-src.uncompressed/skills/**`, `docs/contracts/**`, `docs/guidelines/**` | `scripts/smoke/router.sh` |
|
|
39
|
+
| schema | `.agent-src.uncompressed/skills/**`, `.agent-src.uncompressed/rules/**`, `scripts/schemas/**`, `scripts/skill_linter.py`, `scripts/validate_frontmatter.py` | `scripts/smoke/schema.sh` |
|
|
40
|
+
| skills | `.agent-src.uncompressed/skills/**` | `scripts/smoke/skills.sh` |
|
|
41
|
+
|
|
42
|
+
`task smoke` runs all four locally regardless of paths.
|
|
43
|
+
|
|
44
|
+
## § 3 — Baseline declarations (locked 2026-05-16)
|
|
45
|
+
|
|
46
|
+
Smoke baselines are **measured today**, not aspirational. They lock
|
|
47
|
+
**regression**: a smoke goes red only if the count drifts the wrong way.
|
|
48
|
+
Drift toward the ideal (fewer breaches, more fences) updates the
|
|
49
|
+
constant in the script body and the row below.
|
|
50
|
+
|
|
51
|
+
### § 3.1 — Kernel (`scripts/smoke/kernel.sh`)
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
9 kernel rules · 8 carry Iron-Law fences · 1 dispatch index · ≤ 2 budget breaches
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- **9 kernel rules** — fixed by [`kernel-membership.md`](kernel-membership.md).
|
|
58
|
+
- **8 carry Iron-Law fences** — measured 2026-05-16. `agent-authority`
|
|
59
|
+
is the **dispatch index** (priority table pointing at the other four
|
|
60
|
+
authority rules); it is structurally exempt from the Iron-Law-fence
|
|
61
|
+
requirement and listed in the script's `EXEMPT_FROM_FENCE` set.
|
|
62
|
+
- **≤ 2 budget breaches** — `python3 scripts/measure_rule_budget.py
|
|
63
|
+
--kernel-budget-check` currently reports 2 breaches
|
|
64
|
+
(`kernel-bucket > 26000`, `no-cheap-questions > 4000`). The smoke
|
|
65
|
+
asserts the count does not grow; reductions update `EXPECTED_BREACHES`
|
|
66
|
+
in `scripts/smoke/kernel.sh`. See
|
|
67
|
+
`road-to-kernel-and-router.md`
|
|
68
|
+
for the path back to zero.
|
|
69
|
+
|
|
70
|
+
### § 3.2 — Router (`scripts/smoke/router.sh`)
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
75 router ids · 0 broken rule pointers · 35 routes_to refs · 2 missing contracts
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- **75 ids** — 9 kernel + 24 tier_1 + 42 tier_2; every id resolves to
|
|
77
|
+
`.agent-src/rules/<id>.md`.
|
|
78
|
+
- **0 broken rule pointers** — hard assertion; smoke fails on any miss.
|
|
79
|
+
- **35 routes_to refs** across tier_1 + tier_2; resolver honours the
|
|
80
|
+
four prefixes (`skill:`, `command:`, `guideline:`, `contract:`).
|
|
81
|
+
- **2 missing contracts** — measured 2026-05-16:
|
|
82
|
+
`contract:artifact-engagement-flow`,
|
|
83
|
+
`contract:command-suggestion-flow`. Tracked separately under
|
|
84
|
+
``step-11` Phase 4 (ADR layout)`;
|
|
85
|
+
smoke asserts the count is `≤ EXPECTED_MISSING_CONTRACTS=2`.
|
|
86
|
+
|
|
87
|
+
### § 3.3 — Schema (`scripts/smoke/schema.sh`)
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
438 lintable artefacts · 0 schema FAILs · ≤ 92 warns
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
- **0 FAILs** — hard assertion. `scripts/skill_linter.py --all` returns
|
|
94
|
+
exit 0/1 (warns) but never 2 (fail).
|
|
95
|
+
- **≤ 92 warns** — measured 2026-05-16; locks regression. Warns
|
|
96
|
+
trending down updates the constant.
|
|
97
|
+
- **v2 schema (step-5) deferred** — when
|
|
98
|
+
`step-5-schema-rigor.md`
|
|
99
|
+
Phase 1 closes, this smoke gains a `model_tier` presence assertion;
|
|
100
|
+
Phase 3 adds `schema_version: "2"`. Until then, v1 schema in
|
|
101
|
+
`scripts/schemas/skill.schema.json` is the contract.
|
|
102
|
+
|
|
103
|
+
### § 3.4 — Skills (`scripts/smoke/skills.sh`)
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
5/5 random skills resolve · frontmatter parses · name matches directory
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
- **5 random skills** picked deterministically (seed = epoch day) from
|
|
110
|
+
`.agent-src.uncompressed/skills/*/SKILL.md` and re-validated via
|
|
111
|
+
`scripts/validate_frontmatter.py`. `agent-config explain skill` is
|
|
112
|
+
**not** invoked — `explain` only supports `{config,rule,route}` today
|
|
113
|
+
([`scripts/agent-config/cmd_explain.py`](../../scripts/agent-config/cmd_explain.py));
|
|
114
|
+
filesystem-resolution is the contract.
|
|
115
|
+
|
|
116
|
+
## § 4 — Local invocation
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
task smoke # all four
|
|
120
|
+
task smoke:kernel # individual tiers
|
|
121
|
+
task smoke:router
|
|
122
|
+
task smoke:schema
|
|
123
|
+
task smoke:skills
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Every script honours `SMOKE_QUIET=1` (suppresses table output, keeps
|
|
127
|
+
the final baseline line) for CI summary parsing.
|
|
128
|
+
|
|
129
|
+
## § 5 — Failure modes
|
|
130
|
+
|
|
131
|
+
| Symptom | Likely cause | Fix |
|
|
132
|
+
|---|---|---|
|
|
133
|
+
| `kernel.sh` reports > 8 missing fences | Kernel rule lost its Iron Law block during edit | Restore the fence; update `EXEMPT_FROM_FENCE` only for new dispatch indexes |
|
|
134
|
+
| `router.sh` reports > 0 broken pointers | `router.json` references an id without a rule file | Add the rule or remove the route — never edit the smoke baseline up |
|
|
135
|
+
| `schema.sh` reports FAILs | A skill / rule lost a required field | Restore via [`scripts/schemas/skill.schema.json`](../../scripts/schemas/skill.schema.json) |
|
|
136
|
+
| `skills.sh` 5/5 random sample fails | Hand-edit broke frontmatter or renamed directory without updating `name:` | Restore filename ↔ slug coupling |
|
|
137
|
+
|
|
138
|
+
## § 6 — See also
|
|
139
|
+
|
|
140
|
+
- [`measurement-baseline.md`](measurement-baseline.md) — measurement substrate.
|
|
141
|
+
- [`cost-enforcement.md`](cost-enforcement.md) — cost ladder, sibling smoke surface.
|
|
142
|
+
- [`kernel-membership.md`](kernel-membership.md) — the 9-rule kernel set.
|
|
143
|
+
- [`rule-router.md`](rule-router.md) — router contract.
|
|
144
|
+
- `road-to-kernel-and-router.md` — kernel budget reduction path.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
stability: beta
|
|
3
|
+
keep-beta-until: 2026-08-12
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Workflow packs
|
|
7
|
+
|
|
8
|
+
> **Status:** beta — first draft 2026-05-16 (Phase 2 Item 7 of
|
|
9
|
+
> `step-15-product-refinement`).
|
|
10
|
+
|
|
11
|
+
A **workflow pack** bundles a `(profile + preset + command-set +
|
|
12
|
+
skill-allowlist)` combination into a single YAML so a user can adopt
|
|
13
|
+
the full opinionated stance for their role without picking five
|
|
14
|
+
independent settings.
|
|
15
|
+
|
|
16
|
+
Packs do **not** introduce new commands, skills, or rules. They are
|
|
17
|
+
a **composition contract** — every reference must resolve to an
|
|
18
|
+
existing artefact that has already passed its own contract / linter
|
|
19
|
+
gates.
|
|
20
|
+
|
|
21
|
+
## Schema
|
|
22
|
+
|
|
23
|
+
```yaml
|
|
24
|
+
# .agent-src.uncompressed/packs/<pack-id>.yml
|
|
25
|
+
pack:
|
|
26
|
+
id: <pack-id> # kebab-case, file name without .yml
|
|
27
|
+
audience:
|
|
28
|
+
label: "<human-readable>"
|
|
29
|
+
one_liner: "<= 120 chars, what the pack does for the user>"
|
|
30
|
+
composition:
|
|
31
|
+
profile_id: <profile.id> # MUST exist in profiles/
|
|
32
|
+
preset_id: <preset.id> # MUST exist in presets/
|
|
33
|
+
surface:
|
|
34
|
+
commands_allowed: # ≤ 12 — slash-command names without leading slash
|
|
35
|
+
- <command>
|
|
36
|
+
skills_allowed: # ≤ 15 — skill IDs from skills-catalog
|
|
37
|
+
- <skill>
|
|
38
|
+
personas: # ≤ 4 — persona IDs from personas/
|
|
39
|
+
- <persona>
|
|
40
|
+
rationale: # why this combination, not free-form notes
|
|
41
|
+
why_this_profile: "<one paragraph>"
|
|
42
|
+
why_this_preset: "<one paragraph>"
|
|
43
|
+
why_these_commands: "<one paragraph>"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Field semantics
|
|
47
|
+
|
|
48
|
+
| Field | Type | Required | Notes |
|
|
49
|
+
|---|---|:-:|---|
|
|
50
|
+
| `pack.id` | string | yes | Matches file stem. No collision with `profile.id` or `preset.id`. |
|
|
51
|
+
| `composition.profile_id` | string | yes | Override applied to the chain documented in [`profile-system`](profile-system.md). Pack-supplied id wins over `.agent-settings.yml` only when the user explicitly opts in via `/onboard --pack <id>`. |
|
|
52
|
+
| `composition.preset_id` | string | yes | Override applied to the chain documented in [`config-presets`](config-presets.md). Same opt-in semantics. |
|
|
53
|
+
| `surface.commands_allowed` | list[string] | yes | Cap = **12**. Items must appear in [`command-clusters`](command-clusters.md). The pack does **not** disable other commands — the cap is for the wizard's first-screen rendering, not enforcement. |
|
|
54
|
+
| `surface.skills_allowed` | list[string] | yes | Cap = **15**. Items must appear in `docs/skills-catalog.md`. Same render-only semantics. |
|
|
55
|
+
| `surface.personas` | list[string] | yes | Cap = **4**. Items must appear in `.agent-src.uncompressed/personas/`. |
|
|
56
|
+
| `rationale.*` | string | yes | Forces every pack to justify its composition in plain prose; reviewed at PR time, not at runtime. |
|
|
57
|
+
|
|
58
|
+
## Resolution chain
|
|
59
|
+
|
|
60
|
+
Packs are an **opt-in layer above the profile + preset chain**. The
|
|
61
|
+
loader at `scripts/config/packs.py` (Phase 2 deliverable — not yet
|
|
62
|
+
shipped) reads the pack iff:
|
|
63
|
+
|
|
64
|
+
1. `--pack <id>` flag passed to `/onboard` or `agent-config init`, **or**
|
|
65
|
+
2. `pack.id` set in `.agent-settings.yml` (written by `/onboard --pack`).
|
|
66
|
+
|
|
67
|
+
When a pack is active:
|
|
68
|
+
|
|
69
|
+
- `composition.profile_id` is passed to `profiles.load()` as
|
|
70
|
+
`pack_profile_id` (already wired — see `scripts/config/profiles.py`).
|
|
71
|
+
- `composition.preset_id` is passed to `presets.load()` analogously.
|
|
72
|
+
- `surface.*` lists override the rendered command / skill lists in
|
|
73
|
+
`/onboard` and in the README "Six entry paths" surface **for the
|
|
74
|
+
duration of the active pack only**.
|
|
75
|
+
|
|
76
|
+
Removing a pack (`/onboard --pack none`) reverts to the underlying
|
|
77
|
+
profile + preset defaults; **no data is lost**.
|
|
78
|
+
|
|
79
|
+
## Validation
|
|
80
|
+
|
|
81
|
+
`scripts/lint_packs.py` (Phase 2 deliverable — not yet shipped) fails
|
|
82
|
+
CI on:
|
|
83
|
+
|
|
84
|
+
- Missing required field.
|
|
85
|
+
- `profile_id` / `preset_id` / `commands_allowed` / `skills_allowed`
|
|
86
|
+
/ `personas` referencing an artefact that does not exist.
|
|
87
|
+
- Cap violation (commands > 12, skills > 15, personas > 4).
|
|
88
|
+
- `pack.id` collision with another pack, profile, or preset id.
|
|
89
|
+
|
|
90
|
+
Until the linter lands, packs are reviewed by hand at PR time against
|
|
91
|
+
this schema.
|
|
92
|
+
|
|
93
|
+
## What packs do **not** do
|
|
94
|
+
|
|
95
|
+
- **Do not** declare new commands. Use [`command-clusters`](command-clusters.md).
|
|
96
|
+
- **Do not** modify rules. Use the kernel-rule edit process.
|
|
97
|
+
- **Do not** override safety floors. Domain-safety rules
|
|
98
|
+
(`.agent-src.uncompressed/rules/domain-safety-*.md`) apply
|
|
99
|
+
unconditionally — packs cannot widen the deny-list.
|
|
100
|
+
- **Do not** ship telemetry or usage hints. Packs are pure composition.
|
|
101
|
+
|
|
102
|
+
## Seed packs
|
|
103
|
+
|
|
104
|
+
Three packs ship at Phase 2 Item 7 close:
|
|
105
|
+
|
|
106
|
+
| Pack id | Profile | Preset | One-liner |
|
|
107
|
+
|---|---|---|---|
|
|
108
|
+
| `founder-mvp` | `founder` | `fast` | Ship the MVP and the pitch deck in the same week. |
|
|
109
|
+
| `content-engine` | `content_creator` | `balanced` | Editorial calendar, brand voice, and ghostwriter on one loop. |
|
|
110
|
+
| `agency-delivery` | `agency` | `strict` | Multi-client refine → estimate → deliver with audit-grade trace. |
|
|
111
|
+
|
|
112
|
+
Each pack lives at `.agent-src.uncompressed/packs/<id>.yml` and is
|
|
113
|
+
covered by the validation rules above.
|
|
114
|
+
|
|
115
|
+
## See also
|
|
116
|
+
|
|
117
|
+
- [`profile-system`](profile-system.md) — profile axis (audience defaults)
|
|
118
|
+
- [`config-presets`](config-presets.md) — preset axis (risk appetite)
|
|
119
|
+
- [`command-clusters`](command-clusters.md) — verb axis (invocation)
|
|
120
|
+
- [`command-taxonomy`](command-taxonomy.md) — discoverability axis
|
|
121
|
+
- `step-15-product-refinement` § Phase 2 Item 7
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
adr: 010
|
|
3
|
+
status: proposed
|
|
4
|
+
date: 2026-05-16
|
|
5
|
+
decision: profile-pack-preset-boundary
|
|
6
|
+
supersedes: —
|
|
7
|
+
superseded_by: —
|
|
8
|
+
phase: v2.x · step-15 Phase 1 prerequisite
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# ADR-010 — Profile / Pack / Preset Boundary
|
|
12
|
+
|
|
13
|
+
## Status
|
|
14
|
+
|
|
15
|
+
**Proposed** · 2026-05-16 · pending Phase 1 of
|
|
16
|
+
[`agents/roadmaps/step-15-product-refinement.md`](../../agents/roadmaps/step-15-product-refinement.md).
|
|
17
|
+
Council v3 action #2 (`agents/council-responses/2026-05-16-step-15-product-refinement-v3.json`): <!-- council-ref-allowed: ADR decision-trace to originating council response -->
|
|
18
|
+
**"Profile / Pack / Preset boundary is undefined; Phase 2 will duplicate
|
|
19
|
+
Phase 1 abstractions"**. Promoted from Phase 2 to Phase 1 prerequisite —
|
|
20
|
+
the profile loader (Phase 1 item 1) cannot ship without the boundary.
|
|
21
|
+
|
|
22
|
+
## Context
|
|
23
|
+
|
|
24
|
+
Step-15 introduces three new configuration concepts:
|
|
25
|
+
|
|
26
|
+
- **Profile** — Phase 1 item 1: `profile.id` ∈ {`founder`, `developer`,
|
|
27
|
+
`content_creator`, `agency`, `finance`, `ops`}.
|
|
28
|
+
- **Preset** — Phase 1 item 4: `preset.id` ∈ {`fast`, `balanced`,
|
|
29
|
+
`strict`} bundling 12+ governance knobs (cost caps, confidence band,
|
|
30
|
+
block-on-risk, …).
|
|
31
|
+
- **Pack** — Phase 2 item 7: workflow bundles (`founder-mvp`,
|
|
32
|
+
`content-engine`, `agency-delivery`) of `(profile + preset +
|
|
33
|
+
command-set + skill-allowlist)`.
|
|
34
|
+
|
|
35
|
+
A pre-existing fourth concept is in play:
|
|
36
|
+
|
|
37
|
+
- **`cost_profile`** — current setting in `.agent-settings.yml`, values
|
|
38
|
+
`minimal` / `balanced` / `full` / `custom`. Owns **rule-tier loading**
|
|
39
|
+
(kernel · kernel + tier-1 · kernel + tier-1 + tier-2). Contract:
|
|
40
|
+
[`docs/contracts/cost-profile-defaults.md`](../contracts/cost-profile-defaults.md).
|
|
41
|
+
|
|
42
|
+
Without a written boundary, three failure modes are predictable:
|
|
43
|
+
|
|
44
|
+
1. The preset loader re-implements rule-tier gating (overlap with
|
|
45
|
+
`cost_profile`).
|
|
46
|
+
2. Packs ship duplicate `profile` + `preset` defaults that drift from
|
|
47
|
+
the canonical source.
|
|
48
|
+
3. Three teams add knobs to three places, and a user picking
|
|
49
|
+
`developer + strict + founder-mvp` discovers contradicting values
|
|
50
|
+
at runtime.
|
|
51
|
+
|
|
52
|
+
## Decision
|
|
53
|
+
|
|
54
|
+
Four orthogonal axes, four owners, one resolution chain.
|
|
55
|
+
|
|
56
|
+
| Axis | Answers | Owns | Identity key |
|
|
57
|
+
|---|---|---|---|
|
|
58
|
+
| **Profile** | *Who is the user?* (audience taxonomy) | Default skill/command surface; README entry-paragraph; persona pre-selection | `profile.id` |
|
|
59
|
+
| **Preset** | *How cautious is this run?* (risk + cost + autonomy budget) | The 12+ governance knobs (per-call $ ceiling, confidence band, block-on-risk, autonomy default, council escalation, …) | `preset.id` |
|
|
60
|
+
| **Pack** | *What bundle of skills + commands?* (workflow recipe) | A frozen `(profile, preset, allow_skills, allow_commands)` 4-tuple; nothing more | `pack.id` |
|
|
61
|
+
| **Cost Profile** | *How many rules load?* (token budget) | Rule-tier loading at session start (kernel · +tier-1 · +tier-2) | `cost_profile` |
|
|
62
|
+
|
|
63
|
+
### Resolution chain (read order, last writer wins)
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
pack → profile → preset → cost_profile → user/env/runtime overrides
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
- A **pack** declares defaults for `profile`, `preset`, and the
|
|
70
|
+
skill / command allowlists. It cannot set `cost_profile` (that
|
|
71
|
+
axis belongs to the rule-tier loader and is governed separately).
|
|
72
|
+
- A **profile** declares defaults for `preset`, audience-specific
|
|
73
|
+
README pointer, persona pre-selection. It cannot set any preset
|
|
74
|
+
knob directly — only `preset.id`.
|
|
75
|
+
- A **preset** owns the 12+ knobs. No other axis writes them.
|
|
76
|
+
- A **cost_profile** owns rule-tier loading. No other axis writes it.
|
|
77
|
+
- The user's `.agent-settings.yml`, environment variables, and
|
|
78
|
+
runtime CLI flags override every axis above them.
|
|
79
|
+
|
|
80
|
+
### Non-overlap rules (Iron Law)
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
A KNOB BELONGS TO EXACTLY ONE AXIS.
|
|
84
|
+
DUPLICATION ACROSS AXES IS A CONTRACT VIOLATION.
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
- A pack **may not** override a preset knob; it overrides `preset.id`.
|
|
88
|
+
- A profile **may not** override a preset knob; it overrides `preset.id`.
|
|
89
|
+
- A preset **may not** override `cost_profile`; the user does that.
|
|
90
|
+
- The CI `task lint-config-schema` (added in Phase 1) hard-fails on a
|
|
91
|
+
pack/profile YAML that names any preset-owned knob.
|
|
92
|
+
|
|
93
|
+
## Consequences
|
|
94
|
+
|
|
95
|
+
### Positive
|
|
96
|
+
|
|
97
|
+
- Phase 1 ships the profile loader against a fixed surface (`profile.id`
|
|
98
|
+
→ audience + `preset.id` + persona). No 12-knob inheritance ambiguity.
|
|
99
|
+
- Phase 1 item 4 (Config Presets) owns the knobs alone. The "Cost
|
|
100
|
+
Enforcement" section in [`config-presets.md`](../contracts/config-presets.md)
|
|
101
|
+
has a single home.
|
|
102
|
+
- Phase 2 item 7 (Workflow Packs) is a 4-tuple, not a re-implementation
|
|
103
|
+
of profile + preset. Pack YAML stays under 30 lines.
|
|
104
|
+
- `cost_profile` keeps its single-axis charter; this ADR explicitly
|
|
105
|
+
refuses to fold it into the preset layer.
|
|
106
|
+
|
|
107
|
+
### Negative
|
|
108
|
+
|
|
109
|
+
- One more concept on the install screen (`profile` + `preset` + `pack`
|
|
110
|
+
+ `cost_profile` = four axes). Mitigated by: the wizard (Phase 1 item
|
|
111
|
+
2) only asks for **profile** + **stack** + **risk appetite** and
|
|
112
|
+
derives the rest. Packs are opt-in; `cost_profile` keeps its
|
|
113
|
+
`balanced` default.
|
|
114
|
+
- A skill-allowlist conflict between a pack and a runtime CLI flag is
|
|
115
|
+
resolved by "runtime wins". Users on a pack who shadow-disable a
|
|
116
|
+
skill will not see it again until the override is removed.
|
|
117
|
+
|
|
118
|
+
### Neutral
|
|
119
|
+
|
|
120
|
+
- This ADR records the boundary; it does **not** specify the seed
|
|
121
|
+
values for any axis. Profile IDs live in
|
|
122
|
+
[`docs/contracts/profile-system.md`](../contracts/profile-system.md)
|
|
123
|
+
(Phase 1 item 1). Preset knobs live in
|
|
124
|
+
[`docs/contracts/config-presets.md`](../contracts/config-presets.md)
|
|
125
|
+
(Phase 1 item 4). Pack shape lives in `docs/contracts/workflow-packs.md`
|
|
126
|
+
(Phase 2 item 7).
|
|
127
|
+
|
|
128
|
+
## See also
|
|
129
|
+
|
|
130
|
+
- [`docs/contracts/cost-profile-defaults.md`](../contracts/cost-profile-defaults.md) — the existing `cost_profile` contract this ADR explicitly does **not** touch.
|
|
131
|
+
- [`agents/roadmaps/step-15-product-refinement.md`](../../agents/roadmaps/step-15-product-refinement.md) — Phase 1 items 1, 4 and Phase 2 item 7.
|
|
132
|
+
- [`agents/council-responses/2026-05-16-step-15-product-refinement-v3.json`](../../agents/council-responses/2026-05-16-step-15-product-refinement-v3.json) — Council v3 action #2 (origin). <!-- council-ref-allowed: ADR decision-trace to originating council response -->
|
package/docs/decisions/INDEX.md
CHANGED
|
@@ -13,6 +13,7 @@ _Auto-generated by `scripts/adr/regenerate_index.py`. Do not edit._
|
|
|
13
13
|
| [ADR-007](ADR-007-agent-discovery-scopes.md) | Global Default Install With Export Subcommand | accepted | 2026-05-12 | — |
|
|
14
14
|
| [ADR-008](ADR-008-installed-tools-manifest.md) | Committed Installed Tools Manifest Separate From Settings | proposed | 2026-05-12 | — |
|
|
15
15
|
| [ADR-009](ADR-009-event4u-namespace.md) | Event4U Namespace And Claude Desktop Zip Bundles | accepted | 2026-05-13 | — |
|
|
16
|
+
| [ADR-010](ADR-010-profile-pack-preset-boundary.md) | Profile Pack Preset Boundary | proposed | 2026-05-16 | — |
|
|
16
17
|
|
|
17
18
|
## Unnumbered (legacy)
|
|
18
19
|
|