@event4u/agent-config 2.12.0 → 2.14.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/council/analysis.md +142 -0
- package/.agent-src/commands/council/debate.md +129 -0
- package/.agent-src/commands/council/default.md +8 -0
- package/.agent-src/commands/council/design.md +16 -12
- package/.agent-src/commands/council/optimize.md +16 -15
- package/.agent-src/commands/council/pr.md +12 -12
- package/.agent-src/commands/council.md +48 -2
- package/.agent-src/commands/memory/learn-low-impact.md +143 -0
- package/.agent-src/personas/advisors/contrarian.md +95 -0
- package/.agent-src/personas/advisors/executor.md +99 -0
- package/.agent-src/personas/advisors/expansionist.md +98 -0
- package/.agent-src/personas/advisors/first-principles.md +98 -0
- package/.agent-src/personas/advisors/outsider.md +102 -0
- package/.agent-src/rules/ask-when-uncertain.md +10 -6
- package/.agent-src/rules/copilot-routing.md +19 -0
- package/.agent-src/rules/devcontainer-routing.md +20 -0
- package/.agent-src/rules/external-reference-deep-dive.md +1 -1
- package/.agent-src/rules/fast-path-marker-visibility.md +38 -0
- package/.agent-src/rules/laravel-routing.md +20 -0
- package/.agent-src/rules/low-impact-corpus-privacy-floor.md +74 -0
- package/.agent-src/rules/symfony-routing.md +20 -0
- package/.agent-src/skills/ai-council/SKILL.md +388 -10
- package/.agent-src/skills/copilot-config/SKILL.md +1 -1
- package/.agent-src/skills/devcontainer/SKILL.md +1 -1
- package/.agent-src/skills/laravel/SKILL.md +1 -1
- package/.agent-src/skills/project-analysis-core/SKILL.md +1 -1
- package/.agent-src/skills/project-analyzer/SKILL.md +1 -1
- package/.agent-src/skills/symfony-workflow/SKILL.md +1 -1
- package/.agent-src/skills/universal-project-analysis/SKILL.md +1 -1
- package/.agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/.claude-plugin/marketplace.json +4 -1
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +346 -124
- package/CONTRIBUTING.md +5 -0
- package/README.md +6 -6
- package/config/agent-settings.template.yml +5 -93
- package/config/gitignore-block.txt +6 -0
- package/docs/architecture/multi-tool-projection.md +53 -0
- package/docs/architecture/{compression.md → source-projection.md} +21 -3
- package/docs/architecture.md +15 -15
- package/docs/archive/CHANGELOG-pre-2.11.0.md +141 -0
- package/docs/catalog.md +25 -12
- package/docs/contracts/adr-architectural-consensus-mechanism.md +68 -0
- package/docs/contracts/adr-level-6-productization.md +7 -9
- package/docs/contracts/ai-council-config.md +658 -0
- package/docs/contracts/command-clusters.md +58 -2
- package/docs/contracts/command-surface-tiers.md +3 -2
- package/docs/contracts/cost-profile-defaults.md +5 -0
- package/docs/contracts/decision-engine-gates.md +5 -0
- package/docs/contracts/decision-trace-v1.md +2 -2
- package/docs/contracts/file-ownership-matrix.json +1735 -72
- package/docs/contracts/installed-tools-lockfile.md +2 -1
- package/docs/contracts/low-impact-corpus-format.md +95 -0
- package/docs/contracts/mcp-beta-criteria.md +6 -5
- package/docs/contracts/mcp-cloud-scope.md +5 -4
- package/docs/contracts/multi-tool-projection-fidelity.md +115 -0
- package/docs/contracts/release-trunk-sync.md +4 -3
- package/docs/contracts/tier-3-contrib-plugin.md +5 -6
- package/docs/getting-started.md +2 -2
- package/docs/guidelines/agent-infra/installed-tools-manifest.md +2 -1
- package/docs/installation.md +32 -0
- package/package.json +1 -1
- package/scripts/_archive/README.md +59 -0
- package/scripts/_cli/cmd_doctor.py +134 -0
- package/scripts/ai_council/_default_prices.py +10 -1
- package/scripts/ai_council/advisors.py +148 -0
- package/scripts/ai_council/airgap.py +165 -0
- package/scripts/ai_council/cli_hints.py +123 -0
- package/scripts/ai_council/clients.py +959 -5
- package/scripts/ai_council/compile_corpus.py +178 -0
- package/scripts/ai_council/confidence_gate.py +156 -0
- package/scripts/ai_council/config.py +1364 -0
- package/scripts/ai_council/consensus.py +329 -0
- package/scripts/ai_council/events_log.py +137 -0
- package/scripts/ai_council/learn_low_impact_preview.py +252 -0
- package/scripts/ai_council/low_impact.py +714 -0
- package/scripts/ai_council/low_impact_corpus.py +466 -0
- package/scripts/ai_council/low_impact_intake.py +163 -0
- package/scripts/ai_council/modes.py +6 -1
- package/scripts/ai_council/necessity.py +782 -0
- package/scripts/ai_council/orchestrator.py +872 -20
- package/scripts/ai_council/probation_gate.py +152 -0
- package/scripts/ai_council/prompts.py +335 -0
- package/scripts/ai_council/redact_low_impact_entry.py +155 -0
- package/scripts/ai_council/replay.py +155 -0
- package/scripts/ai_council/session.py +19 -1
- package/scripts/ai_council/shadow_dispatch.py +235 -0
- package/scripts/ai_council/solo_dispatch.py +226 -0
- package/scripts/audit_cloud_compatibility.py +74 -0
- package/scripts/audit_command_surface.py +363 -0
- package/scripts/check_compressed_paths.py +6 -1
- package/scripts/check_council_layout.py +11 -0
- package/scripts/ci_time_ratio.py +168 -0
- package/scripts/council_cli.py +2005 -30
- package/scripts/install.sh +12 -0
- package/scripts/measure_projection_bytes.py +159 -0
- package/scripts/measure_roadmap_trajectory.py +112 -0
- package/scripts/probe_projection_fidelity.py +202 -0
- package/scripts/score_skill_selection.py +198 -0
- package/scripts/skill_collision_clusters.py +162 -0
- /package/scripts/{_backfill_skill_domains.py → _archive/_backfill_skill_domains.py} +0 -0
- /package/scripts/{_bootstrap_tier_frontmatter.py → _archive/_bootstrap_tier_frontmatter.py} +0 -0
- /package/scripts/{_p43_bodies.py → _archive/_p43_bodies.py} +0 -0
- /package/scripts/{_p43_compress.py → _archive/_p43_compress.py} +0 -0
- /package/scripts/{_p4_migrate.py → _archive/_p4_migrate.py} +0 -0
- /package/scripts/{_phase2_shim_helper.py → _archive/_phase2_shim_helper.py} +0 -0
- /package/scripts/{_pilot_council_question.py → _archive/_pilot_council_question.py} +0 -0
|
@@ -12,7 +12,8 @@ repository.
|
|
|
12
12
|
- **Authoritative module:** [`scripts/_lib/installed_tools.py`](../../scripts/_lib/installed_tools.py)
|
|
13
13
|
- **ADR:** [`docs/decisions/ADR-008-installed-tools-manifest.md`](../decisions/ADR-008-installed-tools-manifest.md)
|
|
14
14
|
- **Workflow guide:** [`docs/guidelines/agent-infra/installed-tools-manifest.md`](../guidelines/agent-infra/installed-tools-manifest.md)
|
|
15
|
-
- **Active roadmap:** P1.1 of
|
|
15
|
+
- **Active roadmap:** P1.1 of the `road-to-multi-package-coexistence`
|
|
16
|
+
roadmap (see `agents/roadmaps/` for current status).
|
|
16
17
|
|
|
17
18
|
## Versions
|
|
18
19
|
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
stability: beta
|
|
3
|
+
keep-beta-until: 2026-08-13
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `low-impact-decisions.md` — corpus format contract (step-9 P4)
|
|
7
|
+
|
|
8
|
+
Parser-visible invariants for `agents/low-impact-decisions.md` and any
|
|
9
|
+
upstream seed at the same path. The hardened parser lives in
|
|
10
|
+
[`scripts/ai_council/low_impact_corpus.py`](../../scripts/ai_council/low_impact_corpus.py)
|
|
11
|
+
and ships in two modes:
|
|
12
|
+
|
|
13
|
+
| Mode | Entry point | Behaviour on drift |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| **Lenient** (routing hot-path) | `load_validated_phrases(path)` | Silently drops the offending line. Routing never blocks on a malformed corpus. |
|
|
16
|
+
| **Strict** (CI lint + intake) | `parse_corpus_strict(path)` | Raises `CorpusParseError` with a typed `reason` and 1-based `line` on the first anomaly. |
|
|
17
|
+
|
|
18
|
+
## Required sections
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
## On Probation
|
|
22
|
+
|
|
23
|
+
<!-- intake-anchor: probation -->
|
|
24
|
+
|
|
25
|
+
…
|
|
26
|
+
|
|
27
|
+
## Validated
|
|
28
|
+
|
|
29
|
+
<!-- intake-anchor: validated -->
|
|
30
|
+
|
|
31
|
+
…
|
|
32
|
+
|
|
33
|
+
## Anti-Examples (Always Ask User)
|
|
34
|
+
|
|
35
|
+
…
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
- Heading level **MUST** be `##` (two hashes). `###` → `heading_drift`.
|
|
39
|
+
- Trailing punctuation on a heading (`## Validated:`) → `heading_drift`.
|
|
40
|
+
- Sections may appear in any order; missing sections are tolerated by
|
|
41
|
+
both modes (an empty corpus is valid).
|
|
42
|
+
- The intake-anchor HTML comments **MUST** be present for the two
|
|
43
|
+
intake-bearing sections (`probation`, `validated`) once any section
|
|
44
|
+
body is present. Strict mode raises `missing_anchor` otherwise; the
|
|
45
|
+
lenient shim ignores anchors (anchors are for the intake writer, not
|
|
46
|
+
the routing reader).
|
|
47
|
+
|
|
48
|
+
## Bullet shape
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
- "<phrase>" — optional trailing metadata
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Strict invariants:
|
|
55
|
+
|
|
56
|
+
| Drift | `reason` | Example |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| Curly opening quote (`U+201C` / `U+2018`) | `curly_quotes` | `- “foo bar”` |
|
|
59
|
+
| Single-quoted phrase | `single_quotes` | `- 'foo bar'` |
|
|
60
|
+
| Non-dash list marker (`*`, `+`, `1.`) | `non_dash_bullet` | `* "foo bar"` |
|
|
61
|
+
| Opening `"` with no matching close on the same line | `unclosed_quote` | `- "foo bar — meta` |
|
|
62
|
+
| Phrase normalises to empty (whitespace / punctuation only) | `empty_phrase` | `- " …"` |
|
|
63
|
+
|
|
64
|
+
Trailing metadata (everything after the closing `"`) is preserved on
|
|
65
|
+
the `CorpusEntry.trailing_metadata` field but is **not** consulted for
|
|
66
|
+
routing — only the normalised phrase is.
|
|
67
|
+
|
|
68
|
+
## Phrase normalisation
|
|
69
|
+
|
|
70
|
+
A phrase is normalised before equality / similarity comparison:
|
|
71
|
+
|
|
72
|
+
1. Lowercase.
|
|
73
|
+
2. Replace every non-`[\w\s]` character with a single space.
|
|
74
|
+
3. Collapse runs of whitespace.
|
|
75
|
+
4. Strip leading / trailing whitespace.
|
|
76
|
+
|
|
77
|
+
This normalisation runs in both modes and is stable across the
|
|
78
|
+
routing classifier (`classify_impact_with_corpus`), the intake module
|
|
79
|
+
(`low_impact_intake`), and the probation gate.
|
|
80
|
+
|
|
81
|
+
## Failure-mode fixtures
|
|
82
|
+
|
|
83
|
+
The seven canonical failure cases ship as fixtures under
|
|
84
|
+
[`tests/fixtures/corpus-robust/`](../../tests/fixtures/corpus-robust/),
|
|
85
|
+
one file per `reason`. The strict-mode suite
|
|
86
|
+
[`tests/test_low_impact_corpus_robustness.py`](../../tests/test_low_impact_corpus_robustness.py)
|
|
87
|
+
asserts each fixture trips the matching `CorpusParseError.reason` and
|
|
88
|
+
that the lenient shim degrades silently for per-bullet drift.
|
|
89
|
+
|
|
90
|
+
## Cross-references
|
|
91
|
+
|
|
92
|
+
- Privacy floor — `.augment/rules/low-impact-corpus-privacy-floor.md`
|
|
93
|
+
- Routing — `scripts/ai_council/necessity.py § classify_impact_with_corpus`
|
|
94
|
+
- Intake — `scripts/ai_council/low_impact_intake.py`
|
|
95
|
+
- Promotion / pruning — `scripts/ai_council/probation_gate.py`
|
|
@@ -7,8 +7,8 @@ mcp_scope: lite
|
|
|
7
7
|
|
|
8
8
|
> **Status:** Active · governs the `experimental → beta` promotion for
|
|
9
9
|
> the MCP surface (`scripts/mcp_server/` local stdio kernel + the
|
|
10
|
-
> hosted `workers/mcp/` bridge). Owned by Phase 3 of
|
|
11
|
-
>
|
|
10
|
+
> hosted `workers/mcp/` bridge). Owned by Phase 3 of the
|
|
11
|
+
> `road-to-surface-discipline` roadmap (see `agents/roadmaps/`).
|
|
12
12
|
> Companion contract:
|
|
13
13
|
> [`mcp-phase-1-scope.md`](mcp-phase-1-scope.md) (local) ·
|
|
14
14
|
> [`mcp-cloud-scope.md`](mcp-cloud-scope.md) (hosted).
|
|
@@ -91,8 +91,9 @@ ping. Evidence: the workflow file (`.github/workflows/mcp-no-drift.yml`)
|
|
|
91
91
|
1. Open a release-candidate branch named `release/mcp-beta-rcN`.
|
|
92
92
|
2. Run `./agent-config doctor --check mcp-beta-readiness` — must
|
|
93
93
|
print all six gates green.
|
|
94
|
-
3. Flip the wording in the **five** surfaces inventoried in
|
|
95
|
-
|
|
94
|
+
3. Flip the wording in the **five** surfaces inventoried in the
|
|
95
|
+
`road-to-surface-discipline` roadmap (Phase 3 Step 1, under
|
|
96
|
+
`agents/roadmaps/`):
|
|
96
97
|
`docs/mcp-server.md` (status banner + Remote-MCP sub-claim),
|
|
97
98
|
`README.md` (pointer line), `scripts/mcp_server/server.py`
|
|
98
99
|
(initialize-result `serverInfo.name`),
|
|
@@ -125,5 +126,5 @@ delta for Phase 3: ≤ 0.
|
|
|
125
126
|
- [`STABILITY.md`](STABILITY.md) — stability tier definitions
|
|
126
127
|
(`experimental` / `beta` / `stable`) and what wording each tier may
|
|
127
128
|
use in user-visible surfaces.
|
|
128
|
-
-
|
|
129
|
+
- The `road-to-surface-discipline` roadmap (under `agents/roadmaps/`)
|
|
129
130
|
— Phase 3 acceptance criteria and step-level evidence pointers.
|
|
@@ -31,9 +31,9 @@ alongside auth).
|
|
|
31
31
|
|
|
32
32
|
The package ships **two MCP surfaces** governed by named scopes. Every
|
|
33
33
|
MCP-related doc, ADR, and code path carries `mcp_scope: lite|full|deferred`
|
|
34
|
-
in its frontmatter (Phase 1 Step 6 of
|
|
35
|
-
`agents/roadmaps
|
|
36
|
-
|
|
34
|
+
in its frontmatter (Phase 1 Step 6 of the distribution-maturity roadmap,
|
|
35
|
+
under `agents/roadmaps/`) so the boundary is machine-checkable, not
|
|
36
|
+
prose-only.
|
|
37
37
|
|
|
38
38
|
### `mcp_scope: lite` — hosted, read-only knowledge surfaces
|
|
39
39
|
|
|
@@ -239,7 +239,8 @@ The README MCP section may **only** name modes that this `## Auth
|
|
|
239
239
|
surface` section declares. This contract must declare every mode the
|
|
240
240
|
README names. The drift test
|
|
241
241
|
`tests/test_mcp_contract_readme_sync.py` enforces both directions
|
|
242
|
-
per Phase 1 Step 4 of
|
|
242
|
+
per Phase 1 Step 4 of the distribution-maturity roadmap (under
|
|
243
|
+
`agents/roadmaps/`).
|
|
243
244
|
|
|
244
245
|
## A0-cloud invariants
|
|
245
246
|
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
stability: beta
|
|
3
|
+
keep-beta-until: 2026-08-13
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Multi-Tool Projection Fidelity Contract
|
|
7
|
+
|
|
8
|
+
**Status:** beta · **Phase 4 of the `step-1-v2-feedback-followup`
|
|
9
|
+
roadmap** (under `agents/roadmaps/`).
|
|
10
|
+
|
|
11
|
+
Names the **per-tool guarantees** the projection pipeline (`scripts/compress.py --sync` + `scripts/compress.py --generate-tools`) actually delivers. Byte-equivalence is not behaviour-fidelity — each consumer tool has its own frontmatter grammar, its own activation model, and its own surface for skills / rules / commands.
|
|
12
|
+
|
|
13
|
+
## Source of truth
|
|
14
|
+
|
|
15
|
+
Every projection starts from `.agent-src/` (compressed) which is generated from `.agent-src.uncompressed/`. The projection layer **never** writes to source; it only reads.
|
|
16
|
+
|
|
17
|
+
## Per-tool projection map
|
|
18
|
+
|
|
19
|
+
| Tool | Rules surface | Skills surface | Commands surface | Frontmatter grammar |
|
|
20
|
+
|---|---|---|---|---|
|
|
21
|
+
| **Augment** (host) | `.augment/rules/*.md` (copies; symlink opt-in via `augment.rules_use_symlinks`) | `.augment/skills/<name>/SKILL.md` (symlink → `.agent-src/skills/`) | `.augment/commands/*.md` | full source frontmatter preserved |
|
|
22
|
+
| **Claude** (Code + Desktop) | `.claude/rules/*.md` | `.claude/skills/<name>/SKILL.md` | `.claude/skills/<name>/SKILL.md` (commands rendered as skills) | full source frontmatter preserved |
|
|
23
|
+
| **Cursor** | `.cursor/rules/*.mdc` + legacy `.md` symlinks (130 files = 65 × 2) | **not projected** | `.cursor/commands/*.md` | `description`, `globs`, `alwaysApply` only — `triggers`, `routes_to`, `tier`, `type` are **dropped** |
|
|
24
|
+
| **Windsurf** | `.windsurfrules` (single concatenated file) + `.windsurf/rules/*.md` (per-rule) | **not projected** | `.windsurf/workflows/*.md` | concatenated body; per-rule frontmatter only retained in `.windsurf/rules/`, not in the legacy `.windsurfrules` single-file |
|
|
25
|
+
| **Cline** | `.clinerules/*.md` | **not projected** | **not projected** | full router frontmatter preserved (`type`, `tier`, `description`, `triggers`, `routes_to`) |
|
|
26
|
+
| **Gemini** | `GEMINI.md` (single-file digest) | embedded inline | embedded inline | digest only — no per-rule frontmatter |
|
|
27
|
+
| **Copilot** | `AGENTS.md` / `copilot-instructions.md` | embedded inline | embedded inline | digest only |
|
|
28
|
+
|
|
29
|
+
`AGENTS.md` is the **tool-agnostic root pointer** and exists at workspace root regardless of which projections are enabled.
|
|
30
|
+
|
|
31
|
+
## Fidelity guarantees per axis
|
|
32
|
+
|
|
33
|
+
### 1. Rule body fidelity
|
|
34
|
+
|
|
35
|
+
| Tool | Body identical to source? |
|
|
36
|
+
|---|---|
|
|
37
|
+
| Augment | yes (copy or symlink) |
|
|
38
|
+
| Claude | yes (copy) |
|
|
39
|
+
| Cursor `.mdc` | yes |
|
|
40
|
+
| Cline | yes |
|
|
41
|
+
| Windsurf single-file | concatenated, separator `---` between rules |
|
|
42
|
+
| Windsurf per-rule | yes |
|
|
43
|
+
| Gemini / Copilot digest | summarised — **no fidelity guarantee** |
|
|
44
|
+
|
|
45
|
+
### 2. Trigger fidelity (`triggers:` keyword / `path_prefix`)
|
|
46
|
+
|
|
47
|
+
| Tool | `triggers:` preserved? |
|
|
48
|
+
|---|---|
|
|
49
|
+
| Augment, Claude, Cline, Windsurf-per-rule | **yes** — the host LLM sees the trigger set verbatim |
|
|
50
|
+
| Cursor `.mdc` | **no** — Cursor's frontmatter grammar does not honour `triggers:`; activation falls back to `globs:` + `alwaysApply: <bool>` + description match |
|
|
51
|
+
| Windsurf single-file `.windsurfrules` | **no** — concatenated body strips per-rule frontmatter |
|
|
52
|
+
| Gemini, Copilot | **no** — digest format |
|
|
53
|
+
|
|
54
|
+
**Consequence:** rules that depend on `triggers:` for activation (tier-2a path-prefix routing, tier-3 keyword routing) **silently degrade on Cursor and on the Windsurf single-file**. They still appear in body, but the host must infer activation from prose.
|
|
55
|
+
|
|
56
|
+
### 3. `routes_to:` fidelity
|
|
57
|
+
|
|
58
|
+
Same matrix as `triggers:` — preserved on Augment, Claude, Cline, Windsurf-per-rule; **dropped** on Cursor `.mdc` and Windsurf single-file.
|
|
59
|
+
|
|
60
|
+
**Consequence:** the four tier-3 routing rules (`laravel-routing`, `symfony-routing`, `copilot-routing`, `devcontainer-routing`) added in Phase 3.3 will route deterministically on Augment / Claude / Cline; on Cursor / Windsurf-single-file the host must rely on description matching alone.
|
|
61
|
+
|
|
62
|
+
### 4. Skill surface
|
|
63
|
+
|
|
64
|
+
Cursor, Windsurf, Cline, Gemini, Copilot have **no native skill surface**. Skills are projected only for Augment and Claude. Consumers on the other tools see skill content only indirectly (via rule bodies that cite skills, or via the catalogue in `AGENTS.md`).
|
|
65
|
+
|
|
66
|
+
### 5. Command surface
|
|
67
|
+
|
|
68
|
+
| Tool | Where commands appear |
|
|
69
|
+
|---|---|
|
|
70
|
+
| Augment | `.augment/commands/*.md` (native slash-command surface) |
|
|
71
|
+
| Claude | `.claude/skills/<command>/SKILL.md` (commands rendered as skills with `disable-model-invocation: true`) |
|
|
72
|
+
| Cursor | `.cursor/commands/*.md` (106 files) |
|
|
73
|
+
| Windsurf | `.windsurf/workflows/*.md` (106 files) |
|
|
74
|
+
| Cline | none |
|
|
75
|
+
| Gemini, Copilot | listed only inside `AGENTS.md` / `GEMINI.md` digest |
|
|
76
|
+
|
|
77
|
+
## Automated probe — `task lint-projection-fidelity`
|
|
78
|
+
|
|
79
|
+
`scripts/probe_projection_fidelity.py` reads `tests/fixtures/projection_fidelity/fixtures.yml` and asserts the per-tool guarantees above against the actual projected trees. The fixture covers five representative artefacts:
|
|
80
|
+
|
|
81
|
+
| Fixture entry | Tier | Stress-tests |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| `rule:non-destructive-by-default` | kernel | always-active body fidelity across all five rule surfaces |
|
|
84
|
+
| `rule:laravel-translations` | tier-2a | `path_prefix:` trigger preservation (Cline) vs drop (Cursor) |
|
|
85
|
+
| `rule:laravel-routing` | tier-3 | `routes_to:` preservation (Cline) vs drop (Cursor, Windsurf-single) |
|
|
86
|
+
| `skill:laravel` | skill | Augment + Claude only; rationale for absence on others |
|
|
87
|
+
| `command:commit` | command | per-tool command surface divergence |
|
|
88
|
+
|
|
89
|
+
Run: `python3 scripts/probe_projection_fidelity.py` — exits non-zero on any divergence. Report at `agents/reports/projection-fidelity.json`.
|
|
90
|
+
|
|
91
|
+
## Known divergences (do not file as bugs)
|
|
92
|
+
|
|
93
|
+
These are **architectural facts**, not regressions. They are documented so installers and consumers know what to expect.
|
|
94
|
+
|
|
95
|
+
1. **Cursor `.mdc` drops router metadata.** Cursor's third-party rule format only honours `description`, `globs`, `alwaysApply`. Adding `triggers:` or `routes_to:` to a Cursor rule has no effect at activation time. The body still loads when the description matches; the deterministic routing layer does not.
|
|
96
|
+
2. **Windsurf single-file (`.windsurfrules`) strips per-rule frontmatter.** Legacy compatibility surface. The new `.windsurf/rules/*.md` per-rule files preserve the full frontmatter — consumers should prefer those.
|
|
97
|
+
3. **Skills do not project to Cursor / Windsurf / Cline / Gemini / Copilot.** These tools have no native skill loader. Skill content reaches consumers indirectly via rule bodies and the `AGENTS.md` catalogue.
|
|
98
|
+
4. **Augment historically did not load symlinked rules.** Default is to **copy** rules into `.augment/rules/`. Opt into symlinks via `augment.rules_use_symlinks: true` in `.agent-settings.yml`.
|
|
99
|
+
5. **`task generate-tools` does not refresh `.augment/rules/`.** Only `task sync` (== `scripts/compress.py --sync`) copies rules into the Augment tree. Investigators who edit a rule, run only `generate-tools`, and then `ls .augment/rules/` will see stale state.
|
|
100
|
+
|
|
101
|
+
## Acceptance criteria for this contract
|
|
102
|
+
|
|
103
|
+
- [x] Fixture under `tests/fixtures/projection_fidelity/`
|
|
104
|
+
- [x] Probe script under `scripts/probe_projection_fidelity.py`
|
|
105
|
+
- [x] Report under `agents/reports/projection-fidelity.json`
|
|
106
|
+
- [x] Per-tool guarantee table above
|
|
107
|
+
- [x] Known-divergence list above
|
|
108
|
+
|
|
109
|
+
## Related
|
|
110
|
+
|
|
111
|
+
- [`source-projection`](../architecture/source-projection.md) — pipeline A (source compression)
|
|
112
|
+
- [`augment-projection`](../architecture/augment-projection.md) — pipeline B (Augment-specific)
|
|
113
|
+
- [`multi-tool-projection`](../architecture/multi-tool-projection.md) — pipeline C (the per-tool emitters)
|
|
114
|
+
- [`rule-router`](rule-router.md) — the `triggers:` / `routes_to:` grammar this contract pins
|
|
115
|
+
- [`agents/council-sessions/2026-05-14-v2-analysis/feedback/09-cross-tool-projection-fidelity.md`](../../agents/council-sessions/2026-05-14-v2-analysis/feedback/09-cross-tool-projection-fidelity.md) — origin council feedback <!-- council-ref-allowed: contract origin trace -->
|
|
@@ -11,7 +11,8 @@ keep-beta-until: 2026-08-12
|
|
|
11
11
|
> points across the 2.x cycle. External readers landing on `main`
|
|
12
12
|
> consistently saw stale README counts and missing skill catalogues
|
|
13
13
|
> relative to the npm/Packagist artefact.
|
|
14
|
-
> **Closes:**
|
|
14
|
+
> **Closes:** the `road-to-productization` roadmap § P1.2 (under
|
|
15
|
+
> `agents/roadmaps/`).
|
|
15
16
|
|
|
16
17
|
## Decision
|
|
17
18
|
|
|
@@ -100,5 +101,5 @@ not orphan the convention.
|
|
|
100
101
|
- [`.github/workflows/release-guard.yml`](../../.github/workflows/release-guard.yml)
|
|
101
102
|
— tag/version-file integrity gate (orthogonal: this contract handles
|
|
102
103
|
trunk position, release-guard handles version-string integrity).
|
|
103
|
-
-
|
|
104
|
-
|
|
104
|
+
- The `road-to-productization` roadmap § Phase 1 (under
|
|
105
|
+
`agents/roadmaps/`).
|
|
@@ -26,10 +26,9 @@ Last refreshed: 2026-05-12.
|
|
|
26
26
|
| **Tier-2** | Shipped | Named in roadmaps + has plausible audience | Imperative bridge, same pattern as Tier-1 |
|
|
27
27
|
| **Tier-3** | **Deferred** | Named in scoping/council but zero user demand | Manifest YAML in `agents/manifests/contrib/` (not yet implemented) |
|
|
28
28
|
|
|
29
|
-
Phase 2.1 + 2.2 of
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
overflow bucket.
|
|
29
|
+
Phase 2.1 + 2.2 of the `road-to-global-first-install` roadmap
|
|
30
|
+
(under `agents/roadmaps/`) closed Tier-1 and Tier-2 at **16 AIs**.
|
|
31
|
+
Tier-3 is the explicit overflow bucket.
|
|
33
32
|
|
|
34
33
|
## Candidate list (frozen at proposal time)
|
|
35
34
|
|
|
@@ -126,5 +125,5 @@ not "preemptively scaffold" Tier-3 entries.
|
|
|
126
125
|
- [`ADR-008`](../decisions/ADR-008-installed-tools-manifest.md) —
|
|
127
126
|
`agents/installed-tools.lock` for per-project state, distinct
|
|
128
127
|
from this maintainer-side contract.
|
|
129
|
-
-
|
|
130
|
-
Phase 2.6 — completion trigger for this contract.
|
|
128
|
+
- The `road-to-global-first-install` roadmap (under
|
|
129
|
+
`agents/roadmaps/`) Phase 2.6 — completion trigger for this contract.
|
package/docs/getting-started.md
CHANGED
|
@@ -106,7 +106,7 @@ Your agent is now:
|
|
|
106
106
|
- **Respecting your codebase** — no conflicting patterns
|
|
107
107
|
- **Following standards** — consistent code quality
|
|
108
108
|
|
|
109
|
-
This is enforced automatically by
|
|
109
|
+
This is enforced automatically by 67 rules. No configuration needed.
|
|
110
110
|
|
|
111
111
|
---
|
|
112
112
|
|
|
@@ -146,7 +146,7 @@ Your agent now understands slash commands:
|
|
|
146
146
|
| `/quality-fix` | Run and fix all quality checks |
|
|
147
147
|
| `/chat-history` | Inspect the persistent chat-history log (read-only `show`) |
|
|
148
148
|
|
|
149
|
-
→ [Browse all
|
|
149
|
+
→ [Browse all 109 active commands](../.agent-src/commands/)
|
|
150
150
|
|
|
151
151
|
---
|
|
152
152
|
|
|
@@ -4,7 +4,8 @@ Project-committed bill of materials for AI tooling. Answers the
|
|
|
4
4
|
question "which AIs does this project use, where do their bridges live,
|
|
5
5
|
and is everyone on the team on the same set?". Canonical schema is
|
|
6
6
|
ADR-008 ([`docs/decisions/ADR-008-installed-tools-manifest.md`](../../decisions/ADR-008-installed-tools-manifest.md)).
|
|
7
|
-
|
|
7
|
+
Delivered under the global-first-install roadmap (Phase 3) — see
|
|
8
|
+
`agents/roadmaps/` for current status.
|
|
8
9
|
|
|
9
10
|
This file lives at **`agents/installed-tools.lock`** — committed,
|
|
10
11
|
machine-managed, and orthogonal to `.agent-project-settings.yml`
|
package/docs/installation.md
CHANGED
|
@@ -646,6 +646,38 @@ the symlinks and regenerates derived files (`.windsurfrules`,
|
|
|
646
646
|
|
|
647
647
|
---
|
|
648
648
|
|
|
649
|
+
## AI Council local state
|
|
650
|
+
|
|
651
|
+
The AI Council ([`docs/contracts/ai-council-config.md`](contracts/ai-council-config.md))
|
|
652
|
+
writes two local-only files outside the repo contract:
|
|
653
|
+
|
|
654
|
+
- `~/.event4u/agent-config/cli-calls.json` — per-day call counter for
|
|
655
|
+
`mode: cli` members. Daily UTC reset. Inspect with
|
|
656
|
+
`agent-config council quota`; clear today's counter for one provider
|
|
657
|
+
with `agent-config council quota --reset <provider> --confirm`.
|
|
658
|
+
- `agents/council-events.log` — JSONL audit trail. One line per
|
|
659
|
+
necessity-gate decision and per quota block. Gitignored by the
|
|
660
|
+
installer (managed `.gitignore` block); never committed.
|
|
661
|
+
`original_ask` is hashed `sha256[:12]` before write — the raw prompt
|
|
662
|
+
is never persisted.
|
|
663
|
+
|
|
664
|
+
Both are opt-in by construction: the quota counter only fires when a
|
|
665
|
+
provider has `cli_call_budget.max_calls_per_day.<provider>` set, and
|
|
666
|
+
the events log is purely additive (deletable at any time).
|
|
667
|
+
|
|
668
|
+
### Kill-switches
|
|
669
|
+
|
|
670
|
+
Per-feature environment overrides for ephemeral worktrees, CI runners,
|
|
671
|
+
or sandbox testing:
|
|
672
|
+
|
|
673
|
+
- `AGENT_CONFIG_NO_EVENTS_LOG=1` — disables every write to
|
|
674
|
+
`agents/council-events.log` in-process. Quota counter and council
|
|
675
|
+
output stay untouched.
|
|
676
|
+
- `AGENT_CONFIG_LEGACY_ANCHOR=1` — opt back into the pre-step-7
|
|
677
|
+
legacy-anchor behaviour for `.agent-settings.yml` migration.
|
|
678
|
+
|
|
679
|
+
---
|
|
680
|
+
|
|
649
681
|
## Windows
|
|
650
682
|
|
|
651
683
|
Native Windows is not a first-class target. Use one of the following:
|
package/package.json
CHANGED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Script Archive — One-Shot Migrations
|
|
2
|
+
|
|
3
|
+
This directory preserves migration / bootstrap / back-fill scripts that have
|
|
4
|
+
already run to completion and are no longer invoked by any productive code
|
|
5
|
+
path. They are kept as forensic reference, mirroring the archival convention
|
|
6
|
+
used by [`agents/roadmaps/archive/`](../../agents/roadmaps/archive/).
|
|
7
|
+
|
|
8
|
+
**Do not run these scripts.** They are one-shot transformations whose
|
|
9
|
+
target state is already the working tree. Re-running them on the current
|
|
10
|
+
codebase is undefined behaviour.
|
|
11
|
+
|
|
12
|
+
## Provenance
|
|
13
|
+
|
|
14
|
+
Archived 2026-05-14 as part of [`agents/roadmaps/step-1-v2-feedback-followup.md`](../../agents/roadmaps/step-1-v2-feedback-followup.md)
|
|
15
|
+
Phase 1 Step 3, addressing audit finding F3 / council finding C3 from
|
|
16
|
+
[`agents/council-sessions/2026-05-14-v2-analysis/feedback/03-migration-scripts-archival.md`](../../agents/council-sessions/2026-05-14-v2-analysis/feedback/03-migration-scripts-archival.md).
|
|
17
|
+
|
|
18
|
+
## Inventory
|
|
19
|
+
|
|
20
|
+
| Script | Migration / phase served | What it did |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| [`_backfill_skill_domains.py`](_backfill_skill_domains.py) | B3 domain back-fill | Injected `domain:` frontmatter into every `SKILL.md`. Source of truth now lives in each skill's frontmatter directly. |
|
|
23
|
+
| [`_bootstrap_tier_frontmatter.py`](_bootstrap_tier_frontmatter.py) | Tier-frontmatter bootstrap | Injected `tier: N` frontmatter into every slash command during the kernel / tier-1 / tier-2 routing introduction. |
|
|
24
|
+
| [`_p43_bodies.py`](_p43_bodies.py) | Phase 4.3 — rule-body compression | Wrote compressed rule bodies after `_p43_compress.py` produced the manifest. Paired with `_p43_compress.py`. |
|
|
25
|
+
| [`_p43_compress.py`](_p43_compress.py) | Phase 4.3 — rule-body compression | Surgical compression of 22 `compress-and-keep` auto-rules; produced the manifest consumed by `_p43_bodies.py`. |
|
|
26
|
+
| [`_p4_migrate.py`](_p4_migrate.py) | Phase 4.1 + 4.2 — rule reclassification | Migrated rules into the skill / guideline / command / contract-stub split that the package ships today. |
|
|
27
|
+
| [`_phase2_shim_helper.py`](_phase2_shim_helper.py) | Phase 2 — deprecation shim | One-shot helper that injected `superseded_by:` + `deprecated_in:` + deprecation warning into rules retired during Phase 2. |
|
|
28
|
+
| [`_pilot_council_question.py`](_pilot_council_question.py) | Phase 1 pilot — kernel-membership council prep | Built the Phase-1 council question file used for the kernel-membership R1/R2 cross-check. The resulting council artefacts live under `agents/council-sessions/20260506T*`. |
|
|
29
|
+
|
|
30
|
+
## Why these stayed live and were NOT archived
|
|
31
|
+
|
|
32
|
+
The 2026-05-14 audit (F3) listed 9 candidate scripts. Two of those turn out
|
|
33
|
+
to have productive (non-incestuous) references and remain in `scripts/`:
|
|
34
|
+
|
|
35
|
+
- **`scripts/_emit_domain_table.py`** — cited as the regeneration command in
|
|
36
|
+
[`docs/contracts/skill-domains.md`](../../docs/contracts/skill-domains.md)
|
|
37
|
+
("regenerate via `python3 scripts/_emit_domain_table.py`"). The
|
|
38
|
+
domain-table snapshot is a derived view that the contract doc explicitly
|
|
39
|
+
expects to be regenerable from this script.
|
|
40
|
+
- **`scripts/_pilot_measure.py`** — cited by
|
|
41
|
+
[`docs/contracts/kernel-membership.md`](../../docs/contracts/kernel-membership.md)
|
|
42
|
+
as the reproducibility-verification command for the kernel pilot SHAs, and
|
|
43
|
+
its algorithm is mirrored by [`scripts/iron_law_sha.py`](../iron_law_sha.py).
|
|
44
|
+
Both productive paths assume the script remains in place.
|
|
45
|
+
|
|
46
|
+
The audit's F3 framing ("zero productive references") was correct for the 7
|
|
47
|
+
archived scripts and wrong for these 2. Recorded here so the F3 finding is
|
|
48
|
+
not re-litigated without context.
|
|
49
|
+
|
|
50
|
+
## How to restore one (if a future migration needs it)
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
git mv scripts/_archive/<script>.py scripts/
|
|
54
|
+
git commit -m "chore(scripts): restore <script> for <reason>"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Restoration should come with an issue / PR explaining why the historical
|
|
58
|
+
one-shot is being reused — by construction these scripts assume their
|
|
59
|
+
pre-migration starting state.
|
|
@@ -36,6 +36,7 @@ import argparse
|
|
|
36
36
|
import hashlib
|
|
37
37
|
import json
|
|
38
38
|
import re
|
|
39
|
+
import shutil
|
|
39
40
|
import sys
|
|
40
41
|
from pathlib import Path
|
|
41
42
|
from typing import Any
|
|
@@ -287,6 +288,7 @@ CHECK_IDS = (
|
|
|
287
288
|
"offline-readiness",
|
|
288
289
|
"python-runtime",
|
|
289
290
|
"tier-usage-readiness",
|
|
291
|
+
"council-cli",
|
|
290
292
|
"unsupported-combos",
|
|
291
293
|
)
|
|
292
294
|
|
|
@@ -675,6 +677,137 @@ def _check_tier_usage_readiness(project_root: Path) -> dict[str, Any]:
|
|
|
675
677
|
}
|
|
676
678
|
|
|
677
679
|
|
|
680
|
+
#: Provider → (default binary, billable flag). Mirrors the
|
|
681
|
+
#: ``CliClient`` subclass attributes in ``scripts/ai_council/clients.py``
|
|
682
|
+
#: without importing them at module load time (keeps doctor lightweight
|
|
683
|
+
#: and robust if council deps fail to load).
|
|
684
|
+
_CLI_PROVIDER_META: dict[str, tuple[str, bool]] = {
|
|
685
|
+
"anthropic": ("claude", False),
|
|
686
|
+
"openai": ("codex", False),
|
|
687
|
+
"gemini": ("gemini", False),
|
|
688
|
+
"xai": ("grok", True),
|
|
689
|
+
"perplexity": ("perplexity", True),
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
def _check_council_cli(project_root: Path) -> dict[str, Any]:
|
|
694
|
+
"""Health-probe each enabled ``mode: cli`` council member.
|
|
695
|
+
|
|
696
|
+
For every CLI member in ``agents/.ai-council.yml`` reports binary
|
|
697
|
+
presence (via ``shutil.which``), billable flag, daily-quota state
|
|
698
|
+
(used/cap or used/—), and rolls up to a single status icon.
|
|
699
|
+
|
|
700
|
+
No subprocess is spawned: ``--version`` probes would defeat the
|
|
701
|
+
cheap-by-default contract and surface flaky network paths (Codex
|
|
702
|
+
talks home on first run). Binary presence + the cached
|
|
703
|
+
``cli-calls.json`` counter cover the actionable failure modes.
|
|
704
|
+
|
|
705
|
+
Status rules:
|
|
706
|
+
|
|
707
|
+
- ``ok`` — every enabled CLI member has its binary on PATH AND
|
|
708
|
+
(when capped) usage is below ``warn_at``.
|
|
709
|
+
- ``warn`` — at least one binary is missing OR usage crosses
|
|
710
|
+
``warn_at`` for at least one capped member.
|
|
711
|
+
- returns ``ok`` with "no council config" if
|
|
712
|
+
``agents/.ai-council.yml`` is absent (consumer project that
|
|
713
|
+
hasn't enabled the council yet).
|
|
714
|
+
"""
|
|
715
|
+
council_path = project_root / "agents" / ".ai-council.yml"
|
|
716
|
+
if not council_path.exists():
|
|
717
|
+
return {
|
|
718
|
+
"id": "council-cli", "status": "ok",
|
|
719
|
+
"message": "no council config (agents/.ai-council.yml not present)",
|
|
720
|
+
"remedy": "",
|
|
721
|
+
}
|
|
722
|
+
try:
|
|
723
|
+
from scripts.ai_council.clients import load_cli_call_counts
|
|
724
|
+
from scripts.ai_council.config import load_council_config
|
|
725
|
+
except Exception as exc: # noqa: BLE001 — defensive: doctor must not crash
|
|
726
|
+
return {
|
|
727
|
+
"id": "council-cli", "status": "warn",
|
|
728
|
+
"message": f"council deps unavailable ({type(exc).__name__})",
|
|
729
|
+
"remedy": "install PyYAML and ensure scripts/ai_council is importable",
|
|
730
|
+
}
|
|
731
|
+
try:
|
|
732
|
+
cfg = load_council_config(council_path)
|
|
733
|
+
except Exception as exc: # noqa: BLE001
|
|
734
|
+
return {
|
|
735
|
+
"id": "council-cli", "status": "warn",
|
|
736
|
+
"message": f"council config invalid: {exc}",
|
|
737
|
+
"remedy": "fix agents/.ai-council.yml and re-run doctor",
|
|
738
|
+
}
|
|
739
|
+
cli_members: list[tuple[str, Any]] = [
|
|
740
|
+
(name, m) for name, m in cfg.members.items()
|
|
741
|
+
if m.enabled and m.mode == "cli" and name in _CLI_PROVIDER_META
|
|
742
|
+
]
|
|
743
|
+
if not cli_members:
|
|
744
|
+
return {
|
|
745
|
+
"id": "council-cli", "status": "ok",
|
|
746
|
+
"message": "no enabled CLI-mode members",
|
|
747
|
+
"remedy": "",
|
|
748
|
+
}
|
|
749
|
+
counts = load_cli_call_counts()
|
|
750
|
+
caps = cfg.cli_call_budget.max_calls_per_day
|
|
751
|
+
warn_at = float(cfg.cli_call_budget.warn_at)
|
|
752
|
+
missing: list[str] = []
|
|
753
|
+
over_warn: list[str] = []
|
|
754
|
+
lines: list[str] = []
|
|
755
|
+
for name, member in cli_members:
|
|
756
|
+
default_bin, billable = _CLI_PROVIDER_META[name]
|
|
757
|
+
binary_name = member.binary or default_bin
|
|
758
|
+
resolved = shutil.which(binary_name)
|
|
759
|
+
binary_glyph = "✅" if resolved else "❌"
|
|
760
|
+
if resolved is None:
|
|
761
|
+
missing.append(name)
|
|
762
|
+
used = int(counts.get(name, 0))
|
|
763
|
+
cap = caps.get(name)
|
|
764
|
+
if cap is not None:
|
|
765
|
+
ratio = used / cap if cap > 0 else 0.0
|
|
766
|
+
quota_glyph = "⚠️" if ratio >= warn_at else "✅"
|
|
767
|
+
if ratio >= warn_at:
|
|
768
|
+
over_warn.append(name)
|
|
769
|
+
quota_str = f"{used}/{cap}"
|
|
770
|
+
else:
|
|
771
|
+
quota_glyph = "—"
|
|
772
|
+
quota_str = f"{used}/—"
|
|
773
|
+
billable_str = "billable" if billable else "subscription"
|
|
774
|
+
lines.append(
|
|
775
|
+
f"{name}: binary {binary_glyph} ({binary_name}) · "
|
|
776
|
+
f"quota {quota_glyph} {quota_str} · {billable_str}"
|
|
777
|
+
)
|
|
778
|
+
detail = " | ".join(lines)
|
|
779
|
+
if missing:
|
|
780
|
+
return {
|
|
781
|
+
"id": "council-cli", "status": "warn",
|
|
782
|
+
"message": (
|
|
783
|
+
f"{len(missing)}/{len(cli_members)} CLI member(s) missing binary "
|
|
784
|
+
f"({', '.join(missing)}) · {detail}"
|
|
785
|
+
),
|
|
786
|
+
"remedy": (
|
|
787
|
+
"install the missing CLI(s) — see `council:estimate` pre-flight "
|
|
788
|
+
"for per-provider install hints, or flip "
|
|
789
|
+
"ai_council.members.<name>.mode to 'api'"
|
|
790
|
+
),
|
|
791
|
+
}
|
|
792
|
+
if over_warn:
|
|
793
|
+
return {
|
|
794
|
+
"id": "council-cli", "status": "warn",
|
|
795
|
+
"message": (
|
|
796
|
+
f"{len(over_warn)}/{len(cli_members)} CLI member(s) at/over "
|
|
797
|
+
f"quota warn_at={warn_at} ({', '.join(over_warn)}) · {detail}"
|
|
798
|
+
),
|
|
799
|
+
"remedy": (
|
|
800
|
+
"wait for UTC rollover or run "
|
|
801
|
+
"`python3 scripts/council_cli.py quota --reset` to clear the counter"
|
|
802
|
+
),
|
|
803
|
+
}
|
|
804
|
+
return {
|
|
805
|
+
"id": "council-cli", "status": "ok",
|
|
806
|
+
"message": f"{len(cli_members)} CLI member(s) healthy · {detail}",
|
|
807
|
+
"remedy": "",
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
|
|
678
811
|
def _check_unsupported_combos(manifest: dict[str, Any]) -> dict[str, Any]:
|
|
679
812
|
"""Flag tools whose ``scope`` violates the global-only or project-only rules."""
|
|
680
813
|
global_only = {"droid", "qoder"}
|
|
@@ -720,6 +853,7 @@ def _run_checks(
|
|
|
720
853
|
"offline-readiness": lambda: _check_offline_readiness(),
|
|
721
854
|
"python-runtime": lambda: _check_python_runtime(),
|
|
722
855
|
"tier-usage-readiness": lambda: _check_tier_usage_readiness(project_root),
|
|
856
|
+
"council-cli": lambda: _check_council_cli(project_root),
|
|
723
857
|
"unsupported-combos": lambda: _check_unsupported_combos(manifest),
|
|
724
858
|
}
|
|
725
859
|
out: list[dict[str, Any]] = []
|
|
@@ -17,7 +17,7 @@ from __future__ import annotations
|
|
|
17
17
|
|
|
18
18
|
# YYYY-MM-DD of when this table was last hand-edited. Keep in sync with
|
|
19
19
|
# the test_default_prices freshness assertion if you bump this.
|
|
20
|
-
LAST_UPDATED = "2026-
|
|
20
|
+
LAST_UPDATED = "2026-05-14"
|
|
21
21
|
|
|
22
22
|
# (provider, model) -> (input_per_1m_usd, output_per_1m_usd)
|
|
23
23
|
DEFAULT_PRICES: dict[tuple[str, str], tuple[float, float]] = {
|
|
@@ -30,6 +30,15 @@ DEFAULT_PRICES: dict[tuple[str, str], tuple[float, float]] = {
|
|
|
30
30
|
("openai", "gpt-4o-mini"): (0.15, 0.60),
|
|
31
31
|
("openai", "o1"): (15.00, 60.00),
|
|
32
32
|
("openai", "o3-mini"): (1.10, 4.40),
|
|
33
|
+
# ── Google Gemini ────────────────────────────────────────────────
|
|
34
|
+
("gemini", "gemini-2.5-pro"): (1.25, 10.00),
|
|
35
|
+
("gemini", "gemini-2.5-flash"): (0.30, 2.50),
|
|
36
|
+
# ── xAI Grok ─────────────────────────────────────────────────────
|
|
37
|
+
("xai", "grok-4"): (3.00, 15.00),
|
|
38
|
+
("xai", "grok-3-mini"): (0.30, 0.50),
|
|
39
|
+
# ── Perplexity ───────────────────────────────────────────────────
|
|
40
|
+
("perplexity", "sonar-pro"): (3.00, 15.00),
|
|
41
|
+
("perplexity", "sonar"): (1.00, 1.00),
|
|
33
42
|
}
|
|
34
43
|
|
|
35
44
|
|