@event4u/agent-config 2.10.0 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/.agent-src/commands/agents.md +1 -0
  2. package/.agent-src/commands/challenge-me.md +1 -0
  3. package/.agent-src/commands/chat-history.md +1 -0
  4. package/.agent-src/commands/context.md +1 -0
  5. package/.agent-src/commands/council.md +1 -0
  6. package/.agent-src/commands/feature.md +1 -0
  7. package/.agent-src/commands/fix.md +1 -0
  8. package/.agent-src/commands/grill-me.md +1 -0
  9. package/.agent-src/commands/judge.md +1 -0
  10. package/.agent-src/commands/memory.md +1 -0
  11. package/.agent-src/commands/module.md +1 -0
  12. package/.agent-src/commands/onboard.md +32 -4
  13. package/.agent-src/commands/optimize.md +1 -0
  14. package/.agent-src/commands/override.md +1 -0
  15. package/.agent-src/commands/roadmap.md +1 -0
  16. package/.agent-src/commands/tests.md +1 -0
  17. package/.agent-src/skills/canvas-design/SKILL.md +132 -0
  18. package/.agent-src/skills/canvas-design/evals/triggers.json +16 -0
  19. package/.agent-src/skills/doc-coauthoring/SKILL.md +129 -0
  20. package/.agent-src/skills/doc-coauthoring/evals/triggers.json +16 -0
  21. package/.agent-src/skills/nextjs-patterns/SKILL.md +203 -0
  22. package/.agent-src/skills/skill-writing/SKILL.md +101 -16
  23. package/.agent-src/skills/sql-writing/SKILL.md +1 -1
  24. package/.agent-src/skills/symfony-workflow/SKILL.md +173 -0
  25. package/.agent-src/templates/scripts/work_engine/hook_bootstrap.py +4 -0
  26. package/.agent-src/templates/scripts/work_engine/hooks/builtin/__init__.py +3 -0
  27. package/.agent-src/templates/scripts/work_engine/hooks/builtin/decision_gate.py +162 -0
  28. package/.agent-src/templates/scripts/work_engine/hooks/settings.py +24 -6
  29. package/.agent-src/templates/scripts/work_engine/scoring/decision_engine.py +351 -0
  30. package/.claude-plugin/marketplace.json +5 -1
  31. package/CHANGELOG.md +68 -0
  32. package/README.md +37 -8
  33. package/config/agent-settings.template.yml +66 -0
  34. package/docs/architecture.md +1 -1
  35. package/docs/contracts/STABILITY.md +16 -0
  36. package/docs/contracts/adr-chat-history-split.md +1 -0
  37. package/docs/contracts/adr-forecast-construction-shape.md +1 -0
  38. package/docs/contracts/adr-gtm-context-spine.md +1 -0
  39. package/docs/contracts/adr-level-6-productization.md +147 -0
  40. package/docs/contracts/adr-settings-sync-engine.md +1 -0
  41. package/docs/contracts/adr-wing4-context-spine.md +1 -0
  42. package/docs/contracts/agent-memory-contract.md +1 -0
  43. package/docs/contracts/agents-md-tech-stack.md +1 -0
  44. package/docs/contracts/audit-log-v1.md +1 -0
  45. package/docs/contracts/command-clusters.md +1 -0
  46. package/docs/contracts/command-surface-tiers.md +1 -0
  47. package/docs/contracts/context-paths.md +1 -0
  48. package/docs/contracts/cost-profile-defaults.md +105 -0
  49. package/docs/contracts/cross-wing-handoff.md +1 -0
  50. package/docs/contracts/decision-engine-gates.md +115 -0
  51. package/docs/contracts/decision-trace-v1.md +1 -0
  52. package/docs/contracts/file-ownership-matrix.md +1 -0
  53. package/docs/contracts/hook-architecture-v1.md +1 -0
  54. package/docs/contracts/implement-ticket-flow.md +1 -0
  55. package/docs/contracts/installed-tools-lockfile.md +1 -0
  56. package/docs/contracts/kernel-membership.md +1 -0
  57. package/docs/contracts/linear-ai-rules-inclusion.md +1 -0
  58. package/docs/contracts/linear-ai-three-layers.md +1 -0
  59. package/docs/contracts/linter-structural-model.md +1 -0
  60. package/docs/contracts/load-context-budget-model.md +1 -0
  61. package/docs/contracts/load-context-schema.md +1 -0
  62. package/docs/contracts/memory-visibility-v1.md +1 -0
  63. package/docs/contracts/one-off-script-lifecycle.md +1 -0
  64. package/docs/contracts/orchestration-dsl-v1.md +1 -0
  65. package/docs/contracts/package-self-orientation.md +1 -0
  66. package/docs/contracts/persona-schema.md +1 -0
  67. package/docs/contracts/release-trunk-sync.md +104 -0
  68. package/docs/contracts/roadmap-complexity-standard.md +1 -0
  69. package/docs/contracts/rule-classification.md +1 -0
  70. package/docs/contracts/rule-interactions.md +26 -0
  71. package/docs/contracts/rule-priority-hierarchy.md +1 -0
  72. package/docs/contracts/rule-router.md +1 -0
  73. package/docs/contracts/settings-sync-yaml-subset.md +1 -0
  74. package/docs/contracts/skill-domains.md +1 -0
  75. package/docs/contracts/tier-3-contrib-plugin.md +1 -0
  76. package/docs/contracts/ui-stack-extension.md +1 -0
  77. package/docs/contracts/ui-track-flow.md +1 -0
  78. package/docs/customization.md +1 -1
  79. package/docs/getting-started.md +3 -1
  80. package/docs/installation.md +8 -6
  81. package/package.json +1 -1
  82. package/scripts/ai_council/clients.py +17 -4
  83. package/scripts/ai_council/orchestrator.py +6 -2
  84. package/scripts/check_beta_review_markers.py +127 -0
  85. package/scripts/check_references.py +25 -0
  86. package/scripts/check_release_trunk_sync.py +152 -0
  87. package/scripts/council_cli.py +36 -5
  88. package/scripts/install.py +3 -3
  89. package/scripts/run_skill_evals.py +185 -0
  90. package/scripts/schemas/command.schema.json +5 -0
  91. package/scripts/schemas/skill.schema.json +4 -0
  92. package/scripts/skill_linter.py +82 -3
  93. package/scripts/smoke_quickstart.py +134 -0
  94. package/scripts/validate_decision_engine.py +124 -0
@@ -0,0 +1,115 @@
1
+ # Decision-engine gates (v1)
2
+
3
+ **Status:** beta — landed 2026-05-14 via `road-to-productization.md` Phase 2.
4
+ **Owners:** `work_engine` maintainers.
5
+ **Scope:** the optional `decision_engine:` block in `.agent-settings.yml`.
6
+
7
+ ## Purpose
8
+
9
+ Cross the package from **observable** (Level-5) to **controllable**
10
+ (Level-6). The engine has scored confidence-bands, risk-classes, and
11
+ memory-hits since Phase 4 of `road-to-decision-trace`; this contract
12
+ turns those signals into refusal gates the user opts into.
13
+
14
+ Absent block = unchanged behaviour. Enforcement is opt-in only; the
15
+ engine never silently halts on a signal the user did not configure.
16
+
17
+ ## Schema
18
+
19
+ All keys optional. Unknown keys are rejected hard by
20
+ `scripts/validate_decision_engine.py` and by
21
+ `work_engine.scoring.decision_engine.parse`.
22
+
23
+ | Key | Type | Default | Notes |
24
+ |------------------------|-----------------|---------|-------|
25
+ | `surface_traces` | bool | `false` | Mirrored to `DecisionTraceHook`. Predates the gates; lives here so the block has one schema. |
26
+ | `min_confidence` | enum | `off` | `low` \| `medium` \| `high` \| `off`. Phase=Plan floor. |
27
+ | `block_on_risk` | enum | `off` | `low` \| `medium` \| `high` \| `off`. Phase=Implement ceiling. |
28
+ | `require_memory_hits` | bool | `false` | Phase=Refine demands `memory_hits >= 1`. |
29
+ | `on_block` | enum | `stop` | `stop` \| `ask` \| `warn`. Action when a gate fires. |
30
+ | `ask_timeout_seconds` | int (>= 0) | `30` | Non-TTY wait before applying `on_block_fallback`. |
31
+ | `on_block_fallback` | enum | `stop` | `stop` \| `warn`. Resolution after `ask_timeout`. |
32
+
33
+ ## Gate-to-phase mapping
34
+
35
+ Each gate fires on exactly one phase. The dispatcher emits gate
36
+ decisions on `AFTER_STEP` for that phase only.
37
+
38
+ | Gate | Phase | Signal compared | Fires when |
39
+ |-----------------------|-----------|-----------------------------|-------------------------------------|
40
+ | `min_confidence` | Plan | `confidence_band` | actual < floor |
41
+ | `require_memory_hits` | Refine | `state.memory.hits` | hits < 1 |
42
+ | `block_on_risk` | Implement | `risk_class` | actual >= ceiling |
43
+
44
+ `low` < `medium` < `high` for both confidence and risk. `off` disables
45
+ the gate.
46
+
47
+ ## Conflict matrix
48
+
49
+ Only one gate fires per phase, so cross-phase conflicts are impossible
50
+ by construction. Within a phase, **only the highest-impact gate
51
+ applies**; downstream gates are evaluated against the same phase but
52
+ skipped if a higher-priority gate already fired.
53
+
54
+ Priority (highest → lowest):
55
+
56
+ 1. `block_on_risk` (Implement)
57
+ 2. `require_memory_hits` (Refine)
58
+ 3. `min_confidence` (Plan)
59
+
60
+ This priority surfaces only when a future schema adds gates that
61
+ overlap on the same phase; today each gate owns a unique phase and the
62
+ priority is documentary. The order is locked so future additions
63
+ inherit the contract.
64
+
65
+ ### Worked examples
66
+
67
+ | Config | Phase | confidence | risk | hits | Outcome |
68
+ |---------------------------------------------------------------------------------------|-----------|------------|----------|------|----------------------------------|
69
+ | `min_confidence: medium` | Plan | `low` | - | - | `min_confidence` fires, action=stop |
70
+ | `min_confidence: medium` | Plan | `high` | - | - | no fire — band at/above floor |
71
+ | `block_on_risk: medium` | Implement | - | `high` | - | `block_on_risk` fires, action=stop |
72
+ | `block_on_risk: high` | Implement | - | `medium` | - | no fire — below ceiling |
73
+ | `require_memory_hits: true` | Refine | - | - | 0 | `require_memory_hits` fires |
74
+ | `require_memory_hits: true` | Refine | - | - | 2 | no fire |
75
+ | `min_confidence: high, block_on_risk: low, require_memory_hits: true` (all on) | Plan | `low` | `low` | 0 | `min_confidence` fires (Plan-owning gate) — Refine/Implement gates inert this phase |
76
+
77
+ ## Non-TTY timeout protocol
78
+
79
+ `on_block=ask` is interactive. In a non-interactive context the
80
+ engine cannot block waiting for keystrokes that will never arrive.
81
+ Detection follows two signals (either disables interactivity):
82
+
83
+ - environment variable `CI` set to `1`, `true`, `yes` (case-insensitive)
84
+ - `sys.stdin.isatty()` or `sys.stdout.isatty()` returns false
85
+
86
+ When non-interactive, `on_block=ask` collapses to action `ask_timeout`.
87
+ The consumer (CLI / dispatcher) is expected to:
88
+
89
+ 1. wait `ask_timeout_seconds` for a stdin response;
90
+ 2. apply `on_block_fallback` (`stop` or `warn`) when the timeout
91
+ elapses or stdin is closed;
92
+ 3. surface `block_reason=ask_timeout` on the decision trace so the
93
+ reason is replay-visible.
94
+
95
+ Default fallback is `stop` (fail-safe). Flip to `warn` only when CI
96
+ explicitly wants advisory gates.
97
+
98
+ ## Rollback
99
+
100
+ The block is config-only. Remove the `decision_engine:` block and
101
+ the engine reverts to observe-only behaviour — no migration, no DB
102
+ state, no schema lock. Per-key removal also works (each key has a
103
+ safe default).
104
+
105
+ ## Test surface
106
+
107
+ Coverage lives in `tests/work_engine/scoring/test_decision_engine.py`:
108
+
109
+ - schema parser: defaults, unknown-key rejection, bad-type rejection;
110
+ - gate evaluation: per-phase, per-signal, conflict isolation;
111
+ - TTY detection: env-var detection, fallback to `ask_timeout`;
112
+ - action resolution: `stop` / `warn` short-circuit interactivity.
113
+
114
+ Wiring tests (dispatcher + hook) live in
115
+ `tests/work_engine/test_decision_gate_hook.py`.
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # Decision-trace v1
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # File-ownership matrix
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # Hook architecture v1
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # `/implement-ticket` — Flow Contract
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # Installed-Tools Lockfile — Wire Contract
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
 
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # Linear AI — rules inclusion list
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # Linear AI — three-layer split rationale
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # Linter Structural Model
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # `load_context:` Budget Accounting Model
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # `load_context:` Frontmatter Schema
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # Memory-visibility v1
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # One-off-script lifecycle
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # Orchestration DSL v1
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # Package Self-Orientation
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # Persona Schema — two-tier (Core / Specialist)
@@ -0,0 +1,104 @@
1
+ ---
2
+ stability: beta
3
+ keep-beta-until: 2026-08-12
4
+ ---
5
+
6
+ # ADR — Release-trunk sync: main fast-forwards on every tag
7
+
8
+ > **Status:** Decided · 2026-05-14
9
+ > **Context:** PR #43 feedback (Level-5/6 product rating) and PR #143
10
+ > revealed `main` lagging the latest tag by N skills + rules at multiple
11
+ > points across the 2.x cycle. External readers landing on `main`
12
+ > consistently saw stale README counts and missing skill catalogues
13
+ > relative to the npm/Packagist artefact.
14
+ > **Closes:** [Road to Productization](../../agents/roadmaps/road-to-productization.md) § P1.2.
15
+
16
+ ## Decision
17
+
18
+ Every tagged release (`X.Y.Z`) **fast-forwards `main` to the tag's
19
+ commit as the final step of the release pipeline**. No exceptions. No
20
+ grace period.
21
+
22
+ The fast-forward is owned by [`scripts/release.py`](../../scripts/release.py)
23
+ and runs after the GitHub Release is published. The release pipeline
24
+ is **not green** until `main == <new-tag>` at the remote.
25
+
26
+ `main` is therefore a **moving stable trunk pointer**, not a feature
27
+ branch. External readers (README, AGENTS.md, marketplace metadata, npm
28
+ tarball provenance) reading `main` see the artefact that was last
29
+ published, not work-in-progress.
30
+
31
+ ## Protocol
32
+
33
+ 1. `scripts/release.py` cuts `release/X.Y.Z`, bumps version files,
34
+ opens a release PR against `main`, waits for CI, merges.
35
+ 2. The merge commit on `main` becomes the tag's commit; the tag is
36
+ pushed.
37
+ 3. `publish-npm.yml` and the marketplace flow trigger on the tag.
38
+ 4. The release pipeline asserts `git rev-parse origin/main ==
39
+ git rev-parse refs/tags/X.Y.Z` before exit-0.
40
+ 5. If a hotfix lands on `release/X.Y.Z` after step 1 but before step 4,
41
+ the FF still happens — release-branch commits are part of the
42
+ release, not a separate trunk.
43
+
44
+ ### Why fast-forward, not merge
45
+
46
+ Fast-forward keeps `main` linear with the tag history. A merge-commit
47
+ on top of the tag would put `main` at a SHA that is **not** the tag's
48
+ SHA, re-introducing the exact divergence this contract closes.
49
+
50
+ If a fast-forward is impossible (force-push to `main`, divergent
51
+ history, abandoned release-prep), the pipeline **fails loudly**; the
52
+ operator either resets `main` manually with an audit trail or aborts
53
+ the release.
54
+
55
+ ## CI Gate (P1.3)
56
+
57
+ [`scripts/check_release_trunk_sync.py`](../../scripts/check_release_trunk_sync.py)
58
+ runs on every `release/X.Y.Z` branch (detected by `git rev-parse
59
+ --abbrev-ref HEAD` matching `^release/\d+\.\d+\.\d+$`).
60
+
61
+ It enforces: **`main` is at most ONE tagged release behind the
62
+ release-prep branch's target version.**
63
+
64
+ - On `release/2.11.0`: `main` may be at `2.10.0` or `2.11.0`. `2.9.0`
65
+ or older → **hard fail**.
66
+ - On any other branch class (feature, fix, chore, docs, the agent's
67
+ own `feat/road-to-productization` branch): the check is a **no-op**
68
+ exit-0 — feature branches never trip the gate.
69
+ - Wired into `task ci` as `check-release-trunk-sync`. No warning-only
70
+ mode; the exit code is the gate.
71
+
72
+ ### Bootstrap mode
73
+
74
+ When the repo state does not yet match the gate (transitional first
75
+ run after this contract lands), the check reads
76
+ `docs/contracts/release-trunk-sync.bootstrap` for an opt-out window
77
+ keyed by current version. The bootstrap file is purged at the next
78
+ release. Absence of the file = gate is live.
79
+
80
+ ## Rollback
81
+
82
+ Revertible by removing `check-release-trunk-sync` from `Taskfile.yml`
83
+ and deleting `scripts/check_release_trunk_sync.py`. No state, no
84
+ schema, no migration. Branch-detection key (`release/X.Y.Z`) is
85
+ already used by `scripts/release.py` so removing this contract does
86
+ not orphan the convention.
87
+
88
+ ## Risks
89
+
90
+ | # | Risk | Mitigation |
91
+ |---|---|---|
92
+ | 1 | Gate fires on feature branches mid-PR | Branch-name regex; non-`release/` branches no-op exit-0 |
93
+ | 2 | Hotfix release leaves `main` behind | FF runs **after** hotfix commits land on the release branch |
94
+ | 3 | Manual tag (no `scripts/release.py`) skips the FF | Out of scope of this contract — covered by `release-guard.yml` which fails on tag/version mismatch; manual tags already break the pipeline |
95
+ | 4 | Detached HEAD or shallow checkout breaks detection | Check gracefully exits-0 with a `::warning::` line when `git rev-parse --abbrev-ref HEAD == HEAD` (detached) |
96
+
97
+ ## See also
98
+
99
+ - [`scripts/release.py`](../../scripts/release.py) — release pipeline owner.
100
+ - [`.github/workflows/release-guard.yml`](../../.github/workflows/release-guard.yml)
101
+ — tag/version-file integrity gate (orthogonal: this contract handles
102
+ trunk position, release-guard handles version-string integrity).
103
+ - [`agents/roadmaps/road-to-productization.md`](../../agents/roadmaps/road-to-productization.md)
104
+ § Phase 1.
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # Roadmap Complexity Standard
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
 
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # Rule-Interaction Matrix
@@ -99,6 +100,31 @@ junior (yields). For `complements`, ordering is documentary only.
99
100
  in the rule files.
100
101
  - Skill ↔ rule interactions — the matrix is rule-only. Skills are
101
102
  invoked, not always-active.
103
+ - **Orchestration-layer surfaces** (AI Council, Memory, Work-Engine /
104
+ Decision-Engine): these are runtime systems, not `always`-rules.
105
+ Their interactions are governed by their own contracts and stay
106
+ out of this matrix by design — see "Out of scope" below.
107
+
108
+ ## Out of scope — orchestration surfaces (Council × Memory × Work-Engine)
109
+
110
+ The matrix is **rule-only**. The orchestration layer is governed by
111
+ dedicated contracts; cross-referencing them here would duplicate the
112
+ source of truth and weaken it. Canonical contracts:
113
+
114
+ | Surface | Canonical contract |
115
+ |---|---|
116
+ | Decision-Engine gates (`min_confidence`, `block_on_risk`, `require_memory_hits`, `on_block`) | [`decision-engine-gates.md`](decision-engine-gates.md) |
117
+ | Decision-trace shape (what the engine emits per phase) | [`decision-trace-v1.md`](decision-trace-v1.md) |
118
+ | Memory contract (entries, scopes, retention) | [`agent-memory-contract.md`](agent-memory-contract.md) |
119
+ | Memory visibility in the trace (`affected` keys) | [`memory-visibility-v1.md`](memory-visibility-v1.md) |
120
+ | AI-Council consultation flow | [`../skills/ai-council/SKILL.md`](../../.agent-src.uncompressed/skills/ai-council/SKILL.md) |
121
+
122
+ Where an `always`-rule **does** interact with one of these surfaces
123
+ (e.g. `non-destructive-by-default` gating a memory-driven action), the
124
+ gate lives in the rule and the precedence is captured in this matrix
125
+ as a rule-pair (the orchestration surface is the *occasion*, not a
126
+ participant). For Council ↔ Memory ↔ Work-Engine interactions among
127
+ themselves, the dedicated contracts above are authoritative.
102
128
 
103
129
  ## See also
104
130
 
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # Rule Priority Hierarchy
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
 
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # Settings-sync YAML subset
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # Skill Domains — 6-domain taxonomy
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # Tier-3 contrib plugin pattern
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # UI Stack Extension — adding a new frontend stack to the UI track
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  stability: beta
3
+ keep-beta-until: 2026-08-12
3
4
  ---
4
5
 
5
6
  # UI Track — Flow Contract
@@ -139,7 +139,7 @@ Rules:
139
139
  | Setting | Default | Description |
140
140
  |---|---|---|
141
141
  | `agent_config_version` | *(empty)* | Exact semver pin of the agent-config release (see above). Empty = unpinned. |
142
- | `cost_profile` | `minimal` | Token budget (`minimal`, `balanced`, `full`, `custom`) |
142
+ | `cost_profile` | `balanced` | Token budget (`minimal`, `balanced`, `full`, `custom`) — rationale: [`docs/contracts/cost-profile-defaults.md`](contracts/cost-profile-defaults.md) |
143
143
  | `personal.user_name` | *(empty)* | User's first name for personalized responses |
144
144
  | `personal.minimal_output` | `true` | Suppress intermediate output |
145
145
  | `personal.play_by_play` | `false` | Share intermediate findings during analysis |
@@ -123,9 +123,11 @@ The system supports four configuration profiles:
123
123
  Set your profile in `.agent-settings.yml`:
124
124
 
125
125
  ```yaml
126
- cost_profile: minimal
126
+ cost_profile: balanced
127
127
  ```
128
128
 
129
+ `balanced` is the default — kernel + tier-1 auto-rules. Rationale:
130
+ [`docs/contracts/cost-profile-defaults.md`](contracts/cost-profile-defaults.md).
129
131
  You can override any individual setting. See [Customization](customization.md) for details.
130
132
 
131
133
  ---
@@ -240,8 +240,8 @@ wrapper (`./agent-config`) can fall through to it when no
240
240
  The orchestrator chains payload sync and bridge generation:
241
241
 
242
242
  ```bash
243
- bash scripts/install # defaults to cost_profile=minimal
244
- bash scripts/install --profile=balanced
243
+ bash scripts/install # defaults to cost_profile=balanced
244
+ bash scripts/install --profile=minimal
245
245
  bash scripts/install --force # overwrite existing bridges
246
246
  bash scripts/install --skip-bridges # payload only
247
247
  bash scripts/install --skip-sync # bridges only
@@ -287,7 +287,7 @@ regardless of which AI tool they use.** No per-developer plugin installation nee
287
287
  After initial setup, commit these files:
288
288
 
289
289
  ```
290
- .agent-settings.yml ← shared profile (e.g., cost_profile: minimal)
290
+ .agent-settings.yml ← shared profile (e.g., cost_profile: balanced)
291
291
  agents/installed-tools.lock ← AI bill of materials (ADR-008, Phase 3)
292
292
  .augment/ ← rules, skills, commands (symlinks)
293
293
  .cursor/rules/ ← Cursor rules (symlinks)
@@ -517,16 +517,18 @@ The system works immediately with sensible defaults. Optionally, create `.agent-
517
517
  to choose a profile:
518
518
 
519
519
  ```yaml
520
- cost_profile: minimal
520
+ cost_profile: balanced
521
521
  ```
522
522
 
523
523
  | Profile | What's active | For whom |
524
524
  |---|---|---|
525
- | `minimal` (default) | Rules + Skills only, zero overhead | New users, solo devs |
525
+ | `minimal` | Kernel only Iron-Law floor, zero router | Token-constrained agents |
526
526
  | `balanced` | + Runtime dispatcher + shell handler | Most teams |
527
527
  | `full` | + Tool adapters (GitHub, Jira) | Platform teams |
528
528
 
529
- No profile configured = `minimal` behavior. → [Full profile details](customization.md)
529
+ No profile configured = `balanced` behavior (default). Rationale:
530
+ [`docs/contracts/cost-profile-defaults.md`](contracts/cost-profile-defaults.md).
531
+ → [Full profile details](customization.md)
530
532
 
531
533
  ---
532
534
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@event4u/agent-config",
3
- "version": "2.10.0",
3
+ "version": "2.12.0",
4
4
  "description": "Shared agent configuration \u2014 skills, rules, commands, guidelines, and templates for AI coding tools",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -53,6 +53,19 @@ def _resolve_key_path(filename: str) -> Path:
53
53
  DEFAULT_ANTHROPIC_MODEL = "claude-sonnet-4-5"
54
54
  DEFAULT_OPENAI_MODEL = "gpt-4o"
55
55
 
56
+ #: Per-call output budget when no caller-supplied value reaches `ask()`.
57
+ #: The CLI resolves the live default from `ai_council.max_output_tokens`
58
+ #: in `.agent-settings.yml`; this constant is only the abstract-base /
59
+ #: direct-API fallback when nothing else is wired up.
60
+ DEFAULT_MAX_TOKENS = 2048
61
+
62
+ #: Expansion target when the user sets `max_output_tokens: 0` ("unlimited")
63
+ #: in settings. Anthropic requires `max_tokens` to be a positive integer,
64
+ #: so 0 is widened to this safe ceiling before the SDK call. Big enough
65
+ #: for current frontier models (Sonnet/GPT-4o headroom ≥ 16k); raise
66
+ #: explicitly in settings if a larger budget is genuinely needed.
67
+ UNLIMITED_TOKENS_FALLBACK = 16384
68
+
56
69
  # OpenAI reasoning models (o1, o3, o4 families) reject `max_tokens` and the
57
70
  # `system` role; they require `max_completion_tokens` and accept only `user`
58
71
  # (and `developer`) messages.
@@ -128,7 +141,7 @@ class ExternalAIClient(ABC):
128
141
  self,
129
142
  system_prompt: str,
130
143
  user_prompt: str,
131
- max_tokens: int = 1024,
144
+ max_tokens: int = DEFAULT_MAX_TOKENS,
132
145
  ) -> CouncilResponse:
133
146
  """Send one independent query. Must never raise on network/API
134
147
  failure — return a `CouncilResponse` with `error` set instead.
@@ -162,7 +175,7 @@ class AnthropicClient(ExternalAIClient):
162
175
  ) from exc
163
176
  self._client = anthropic.Anthropic(api_key=api_key)
164
177
 
165
- def ask(self, system_prompt: str, user_prompt: str, max_tokens: int = 1024) -> CouncilResponse:
178
+ def ask(self, system_prompt: str, user_prompt: str, max_tokens: int = DEFAULT_MAX_TOKENS) -> CouncilResponse:
166
179
  t0 = time.monotonic()
167
180
  try:
168
181
  response = self._client.messages.create(
@@ -218,7 +231,7 @@ class OpenAIClient(ExternalAIClient):
218
231
  ) from exc
219
232
  self._client = openai.OpenAI(api_key=api_key)
220
233
 
221
- def ask(self, system_prompt: str, user_prompt: str, max_tokens: int = 1024) -> CouncilResponse:
234
+ def ask(self, system_prompt: str, user_prompt: str, max_tokens: int = DEFAULT_MAX_TOKENS) -> CouncilResponse:
222
235
  t0 = time.monotonic()
223
236
  kwargs: dict[str, object] = {"model": self.model}
224
237
  if _is_reasoning_model(self.model):
@@ -316,7 +329,7 @@ class ManualClient(ExternalAIClient):
316
329
  self,
317
330
  system_prompt: str,
318
331
  user_prompt: str,
319
- max_tokens: int = 1024, # noqa: ARG002 — accepted for ABC parity
332
+ max_tokens: int = DEFAULT_MAX_TOKENS, # noqa: ARG002 — accepted for ABC parity
320
333
  ) -> CouncilResponse:
321
334
  t0 = time.monotonic()
322
335
  rounds: list[str] = []
@@ -27,7 +27,11 @@ from scripts.ai_council.budget_guard import (
27
27
  today_spend_usd as _today_spend_usd,
28
28
  would_exceed as _would_exceed_daily,
29
29
  )
30
- from scripts.ai_council.clients import CouncilResponse, ExternalAIClient
30
+ from scripts.ai_council.clients import (
31
+ DEFAULT_MAX_TOKENS,
32
+ CouncilResponse,
33
+ ExternalAIClient,
34
+ )
31
35
  from scripts.ai_council.pricing import (
32
36
  CostEstimate,
33
37
  PriceTable,
@@ -51,7 +55,7 @@ class CostBudget:
51
55
  class CouncilQuestion:
52
56
  mode: str # one of: prompt, roadmap, diff, files
53
57
  user_prompt: str # bundled artefact text
54
- max_tokens: int = 1024
58
+ max_tokens: int = DEFAULT_MAX_TOKENS
55
59
 
56
60
 
57
61
  @dataclass