@event4u/agent-config 1.16.0 → 1.17.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/{agents-audit.md → agents/audit.md} +4 -3
- package/.agent-src/commands/{agents-cleanup.md → agents/cleanup.md} +12 -6
- package/.agent-src/commands/{agents-prepare.md → agents/prepare.md} +4 -3
- package/.agent-src/commands/agents.md +46 -0
- package/.agent-src/commands/{chat-history-checkpoint.md → chat-history/checkpoint.md} +4 -4
- package/.agent-src/commands/{chat-history-clear.md → chat-history/clear.md} +4 -4
- package/.agent-src/commands/{chat-history-resume.md → chat-history/resume.md} +4 -4
- package/.agent-src/commands/chat-history/show.md +107 -0
- package/.agent-src/commands/chat-history.md +33 -89
- package/.agent-src/commands/{commit-in-chunks.md → commit/in-chunks.md} +15 -13
- package/.agent-src/commands/commit.md +22 -2
- package/.agent-src/commands/{context-create.md → context/create.md} +4 -3
- package/.agent-src/commands/{context-refactor.md → context/refactor.md} +4 -3
- package/.agent-src/commands/context.md +44 -0
- package/.agent-src/commands/{copilot-agents-init.md → copilot-agents/init.md} +4 -3
- package/.agent-src/commands/{copilot-agents-optimize.md → copilot-agents/optimize.md} +4 -3
- package/.agent-src/commands/copilot-agents.md +44 -0
- package/.agent-src/commands/council/default.md +221 -0
- package/.agent-src/commands/{council-design.md → council/design.md} +6 -5
- package/.agent-src/commands/{council-optimize.md → council/optimize.md} +7 -6
- package/.agent-src/commands/{council-pr.md → council/pr.md} +6 -5
- package/.agent-src/commands/council.md +47 -212
- package/.agent-src/commands/{create-pr-description.md → create-pr/description-only.md} +4 -2
- package/.agent-src/commands/create-pr.md +26 -5
- package/.agent-src/commands/{feature-dev.md → feature/dev.md} +5 -10
- package/.agent-src/commands/{feature-explore.md → feature/explore.md} +4 -8
- package/.agent-src/commands/{feature-plan.md → feature/plan.md} +4 -8
- package/.agent-src/commands/{feature-refactor.md → feature/refactor.md} +4 -8
- package/.agent-src/commands/{feature-roadmap.md → feature/roadmap.md} +6 -10
- package/.agent-src/commands/feature.md +6 -12
- package/.agent-src/commands/{fix-ci.md → fix/ci.md} +4 -8
- package/.agent-src/commands/{fix-portability.md → fix/portability.md} +4 -8
- package/.agent-src/commands/{fix-pr-bot-comments.md → fix/pr-bots.md} +4 -8
- package/.agent-src/commands/{fix-pr-developer-comments.md → fix/pr-developers.md} +4 -8
- package/.agent-src/commands/{fix-pr-comments.md → fix/pr.md} +7 -11
- package/.agent-src/commands/{fix-references.md → fix/refs.md} +4 -8
- package/.agent-src/commands/{fix-seeder.md → fix/seeder.md} +4 -8
- package/.agent-src/commands/fix.md +7 -13
- package/.agent-src/commands/{do-and-judge.md → judge/on-diff.md} +4 -3
- package/.agent-src/commands/judge/solo.md +90 -0
- package/.agent-src/commands/{do-in-steps.md → judge/steps.md} +4 -3
- package/.agent-src/commands/judge.md +35 -70
- package/.agent-src/commands/{memory-add.md → memory/add.md} +4 -3
- package/.agent-src/commands/{memory-full.md → memory/load.md} +4 -3
- package/.agent-src/commands/{memory-promote.md → memory/promote.md} +4 -3
- package/.agent-src/commands/{propose-memory.md → memory/propose.md} +4 -3
- package/.agent-src/commands/memory.md +48 -0
- package/.agent-src/commands/{module-create.md → module/create.md} +4 -3
- package/.agent-src/commands/{module-explore.md → module/explore.md} +4 -3
- package/.agent-src/commands/module.md +44 -0
- package/.agent-src/commands/{optimize-agents.md → optimize/agents.md} +4 -8
- package/.agent-src/commands/{optimize-augmentignore.md → optimize/augmentignore.md} +4 -9
- package/.agent-src/commands/{optimize-rtk-filters.md → optimize/rtk.md} +4 -8
- package/.agent-src/commands/{optimize-skills.md → optimize/skills.md} +4 -8
- package/.agent-src/commands/optimize.md +4 -10
- package/.agent-src/commands/{override-create.md → override/create.md} +4 -3
- package/.agent-src/commands/{override-manage.md → override/manage.md} +4 -3
- package/.agent-src/commands/override.md +44 -0
- package/.agent-src/commands/{roadmap-create.md → roadmap/create.md} +4 -3
- package/.agent-src/commands/{roadmap-execute.md → roadmap/execute.md} +4 -3
- package/.agent-src/commands/roadmap.md +44 -0
- package/.agent-src/commands/{tests-create.md → tests/create.md} +4 -3
- package/.agent-src/commands/{tests-execute.md → tests/execute.md} +4 -3
- package/.agent-src/commands/tests.md +44 -0
- package/.agent-src/contexts/communication/rules-auto/artifact-engagement-recording-mechanics.md +72 -0
- package/.agent-src/contexts/communication/rules-auto/augment-portability-mechanics.md +79 -0
- package/.agent-src/contexts/communication/rules-auto/augment-source-of-truth-mechanics.md +98 -0
- package/.agent-src/contexts/communication/rules-auto/cli-output-handling-mechanics.md +87 -0
- package/.agent-src/contexts/communication/rules-auto/command-suggestion-policy-mechanics.md +62 -0
- package/.agent-src/contexts/communication/rules-auto/docs-sync-mechanics.md +78 -0
- package/.agent-src/contexts/communication/rules-auto/package-ci-checks-mechanics.md +85 -0
- package/.agent-src/contexts/communication/rules-auto/review-routing-awareness-mechanics.md +65 -0
- package/.agent-src/contexts/communication/rules-auto/roadmap-progress-sync-mechanics.md +78 -0
- package/.agent-src/contexts/communication/rules-auto/skill-quality-mechanics.md +62 -0
- package/.agent-src/contexts/communication/rules-auto/slash-command-routing-policy-mechanics.md +55 -0
- package/.agent-src/contexts/communication/rules-auto/ui-audit-gate-mechanics.md +53 -0
- package/.agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +77 -0
- package/.agent-src/contexts/judges/no-consolidate-rationale.md +102 -0
- package/.agent-src/contexts/judges/persona-voice-rubric.md +140 -0
- package/.agent-src/rules/artifact-engagement-recording.md +13 -69
- package/.agent-src/rules/ask-when-uncertain.md +27 -42
- package/.agent-src/rules/augment-portability.md +15 -61
- package/.agent-src/rules/augment-source-of-truth.md +27 -93
- package/.agent-src/rules/cli-output-handling.md +10 -76
- package/.agent-src/rules/command-suggestion-policy.md +18 -59
- package/.agent-src/rules/commit-conventions.md +17 -14
- package/.agent-src/rules/direct-answers.md +34 -49
- package/.agent-src/rules/docker-commands.md +5 -5
- package/.agent-src/rules/docs-sync.md +15 -69
- package/.agent-src/rules/language-and-tone.md +48 -72
- package/.agent-src/rules/missing-tool-handling.md +28 -22
- package/.agent-src/rules/no-cheap-questions.md +45 -52
- package/.agent-src/rules/no-roadmap-references.md +73 -0
- package/.agent-src/rules/package-ci-checks.md +21 -61
- package/.agent-src/rules/preservation-guard.md +64 -29
- package/.agent-src/rules/review-routing-awareness.md +24 -43
- package/.agent-src/rules/roadmap-progress-sync.md +10 -71
- package/.agent-src/rules/security-sensitive-stop.md +8 -8
- package/.agent-src/rules/skill-quality.md +16 -48
- package/.agent-src/rules/slash-command-routing-policy.md +7 -4
- package/.agent-src/rules/think-before-action.md +52 -42
- package/.agent-src/rules/tool-safety.md +19 -16
- package/.agent-src/rules/ui-audit-gate.md +24 -38
- package/.agent-src/rules/user-interaction.md +13 -68
- package/.agent-src/skills/ai-council/SKILL.md +2 -0
- package/.agent-src/skills/api-testing/SKILL.md +1 -1
- package/.agent-src/skills/check-refs/SKILL.md +59 -40
- package/.agent-src/skills/conventional-commits-writing/SKILL.md +86 -28
- package/.agent-src/skills/copilot-agents-optimization/SKILL.md +5 -5
- package/.agent-src/skills/developer-like-execution/SKILL.md +4 -4
- package/.agent-src/skills/finishing-a-development-branch/SKILL.md +101 -65
- package/.agent-src/skills/flux/SKILL.md +30 -10
- package/.agent-src/skills/github-ci/SKILL.md +2 -2
- package/.agent-src/skills/judge-code-quality/SKILL.md +7 -8
- package/.agent-src/skills/judge-security-auditor/SKILL.md +4 -5
- package/.agent-src/skills/judge-test-coverage/SKILL.md +3 -4
- package/.agent-src/skills/lint-skills/SKILL.md +57 -39
- package/.agent-src/skills/md-language-check/SKILL.md +61 -39
- package/.agent-src/skills/override-management/SKILL.md +5 -5
- package/.agent-src/skills/quality-tools/SKILL.md +2 -2
- package/.agent-src/skills/react-shadcn-ui/SKILL.md +116 -43
- package/.agent-src/skills/readme-reviewer/SKILL.md +30 -29
- package/.agent-src/skills/readme-writing/SKILL.md +78 -53
- package/.agent-src/skills/readme-writing-package/SKILL.md +50 -47
- package/.agent-src/skills/receiving-code-review/SKILL.md +52 -47
- package/.agent-src/skills/refine-prompt/SKILL.md +0 -1
- package/.agent-src/skills/requesting-code-review/SKILL.md +35 -30
- package/.agent-src/skills/security/SKILL.md +7 -2
- package/.agent-src/skills/security-audit/SKILL.md +7 -3
- package/.agent-src/skills/systematic-debugging/SKILL.md +68 -60
- package/.agent-src/skills/test-driven-development/SKILL.md +59 -57
- package/.agent-src/skills/test-performance/SKILL.md +0 -1
- package/.agent-src/skills/traefik/SKILL.md +4 -4
- package/.agent-src/skills/verify-completion-evidence/SKILL.md +28 -26
- package/.claude-plugin/marketplace.json +22 -11
- package/AGENTS.md +2 -2
- package/CHANGELOG.md +90 -1
- package/README.md +18 -17
- package/docs/architecture.md +4 -6
- package/docs/catalog.md +67 -39
- package/docs/contracts/STABILITY.md +13 -7
- package/docs/contracts/adr-chat-history-split.md +1 -3
- package/docs/contracts/adr-command-suggestion.md +0 -2
- package/docs/contracts/adr-implement-ticket-runtime.md +1 -2
- package/docs/contracts/adr-product-ui-track.md +3 -6
- package/docs/contracts/adr-prompt-driven-execution.md +3 -4
- package/docs/contracts/agent-memory-contract.md +6 -11
- package/docs/contracts/artifact-engagement-flow.md +6 -9
- package/docs/contracts/command-clusters.md +56 -46
- package/docs/contracts/command-suggestion-flow.md +1 -3
- package/docs/contracts/context-paths.md +99 -0
- package/docs/contracts/file-ownership-matrix.json +6722 -0
- package/docs/contracts/file-ownership-matrix.md +134 -0
- package/docs/contracts/implement-ticket-flow.md +6 -9
- package/docs/contracts/linear-ai-rules-inclusion.md +0 -1
- package/docs/contracts/linear-ai-three-layers.md +0 -2
- package/docs/contracts/load-context-budget-model.md +178 -0
- package/docs/contracts/load-context-schema.md +1 -3
- package/docs/contracts/rule-interactions.md +0 -1
- package/docs/contracts/rule-priority-hierarchy.md +1 -1
- package/docs/contracts/ui-track-flow.md +7 -17
- package/docs/customization.md +2 -0
- package/docs/getting-started.md +5 -4
- package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +100 -0
- package/package.json +1 -1
- package/scripts/_one_off_phase4_dispatch_latency.py +108 -0
- package/scripts/_one_off_phase6_trigger_jaccard.py +92 -0
- package/scripts/_phase2_shim_helper.py +109 -0
- package/scripts/agent-config +10 -0
- package/scripts/ai_council/_one_off_2a4_acceptance.py +208 -0
- package/scripts/ai_council/_one_off_context_layer_v1_estimate.py +67 -0
- package/scripts/ai_council/_one_off_context_layer_v1_review.py +292 -0
- package/scripts/ai_council/_one_off_followups_review.py +259 -0
- package/scripts/ai_council/_one_off_nondestructive_inline_audit.py +209 -0
- package/scripts/ai_council/_one_off_phase_2a_budget_rebalance.py +257 -0
- package/scripts/ai_council/_one_off_phase_2a_post_revert.py +197 -0
- package/scripts/ai_council/_one_off_rule_hardening_v1.py +251 -0
- package/scripts/ai_council/_one_off_structural_open_questions.py +232 -0
- package/scripts/ai_council/_one_off_structural_optimization.py +144 -0
- package/scripts/ai_council/_one_off_structural_v3_gaps.py +252 -0
- package/scripts/ai_council/_one_off_structural_v3_review.py +240 -0
- package/scripts/check_always_budget.py +363 -45
- package/scripts/check_cluster_patterns.py +159 -0
- package/scripts/check_command_count_messaging.py +14 -7
- package/scripts/check_context_paths.py +201 -0
- package/scripts/check_no_roadmap_refs.py +155 -0
- package/scripts/check_phase_coupling.py +148 -0
- package/scripts/check_portability.py +2 -0
- package/scripts/check_references.py +29 -2
- package/scripts/check_safety_floor_untouched.py +125 -0
- package/scripts/command_suggester/loader.py +4 -1
- package/scripts/compress.py +59 -13
- package/scripts/generate_index.py +6 -2
- package/scripts/generate_ownership_matrix.py +323 -0
- package/scripts/hooks/augment-roadmap-progress.sh +57 -0
- package/scripts/install.py +49 -28
- package/scripts/lint_no_new_atomic_commands.py +12 -11
- package/scripts/requirements-evals.txt +1 -0
- package/scripts/roadmap_progress_hook.py +159 -0
- package/scripts/schemas/command.schema.json +4 -3
- package/scripts/skill_linter.py +1 -0
- package/scripts/sync_agent_settings.py +25 -2
- package/scripts/update_counts.py +7 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"""Council review of road-to-rule-hardening.md v1.
|
|
2
|
+
|
|
3
|
+
Three independent self-check rules silently skipped within one
|
|
4
|
+
session despite being valid, loaded, and active. Host agent drafted
|
|
5
|
+
a 6-phase lightweight roadmap proposing a 3-tier hardening model
|
|
6
|
+
(Mechanical / Nudge / Inherent-soft).
|
|
7
|
+
|
|
8
|
+
Council task: validate the architecture and the pilot order before
|
|
9
|
+
the host agent autonomously implements Tier 1 hooks.
|
|
10
|
+
|
|
11
|
+
Invocation:
|
|
12
|
+
.venv/bin/python -m scripts.ai_council._one_off_rule_hardening_v1
|
|
13
|
+
"""
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import sys
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
|
|
19
|
+
from scripts.ai_council.bundler import bundle_prompt
|
|
20
|
+
from scripts.ai_council.clients import (
|
|
21
|
+
AnthropicClient,
|
|
22
|
+
OpenAIClient,
|
|
23
|
+
load_anthropic_key,
|
|
24
|
+
load_openai_key,
|
|
25
|
+
)
|
|
26
|
+
from scripts.ai_council.orchestrator import (
|
|
27
|
+
CostBudget,
|
|
28
|
+
CouncilQuestion,
|
|
29
|
+
consult,
|
|
30
|
+
estimate,
|
|
31
|
+
)
|
|
32
|
+
from scripts.ai_council.pricing import estimate_cost, load_prices
|
|
33
|
+
from scripts.ai_council.project_context import detect_project_context
|
|
34
|
+
from scripts.ai_council.session import SessionManifest, save as save_session
|
|
35
|
+
|
|
36
|
+
REPO_ROOT = Path(__file__).resolve().parents[2]
|
|
37
|
+
ROADMAP_PATH = REPO_ROOT / "agents/roadmaps/road-to-rule-hardening.md"
|
|
38
|
+
|
|
39
|
+
ORIGINAL_ASK = (
|
|
40
|
+
"Three independent self-check rules silently skipped within one "
|
|
41
|
+
"session: model-recommendation (task-start gate), context-hygiene "
|
|
42
|
+
"(turn-count handoff), roadmap-progress-sync (file-write side "
|
|
43
|
+
"effect). All valid, loaded, active. Host agent drafted a 6-phase "
|
|
44
|
+
"lightweight roadmap proposing a 3-tier hardening model. Council "
|
|
45
|
+
"task: validate the architecture and the pilot ordering before "
|
|
46
|
+
"implementation."
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
PROMPT_HEADER = """\
|
|
50
|
+
# Council Review — road-to-rule-hardening.md v1
|
|
51
|
+
|
|
52
|
+
## Background (verbatim, do not re-frame)
|
|
53
|
+
|
|
54
|
+
Within a single session the host agent observed three rules failing
|
|
55
|
+
the same way:
|
|
56
|
+
|
|
57
|
+
| Rule | Trigger that should have fired | What happened |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| `model-recommendation` | Opus recommendation at task-start | silently skipped |
|
|
60
|
+
| `context-hygiene` | Handoff at turn-count >= 20/40/60 | silently skipped |
|
|
61
|
+
| `roadmap-progress-sync` | Regenerate dashboard on roadmap touch | silently skipped |
|
|
62
|
+
|
|
63
|
+
All three are valid auto-load rules in `.augment/rules/`, all three
|
|
64
|
+
are part of the active rule set surfaced to the agent. None of them
|
|
65
|
+
fired. Hypothesis: they share a structural property — the trigger
|
|
66
|
+
is observable only inside the agent, the check runs in the agent's
|
|
67
|
+
head, no deterministic gate sits between decision and output. When
|
|
68
|
+
the agent is in flow (multi-tool work, file edits, council
|
|
69
|
+
orchestration), the self-check is the first thing to be dropped.
|
|
70
|
+
|
|
71
|
+
The host agent drafted a 6-phase lightweight roadmap proposing a
|
|
72
|
+
3-tier model:
|
|
73
|
+
|
|
74
|
+
- **Tier 1 — Mechanical.** Hook + deterministic check.
|
|
75
|
+
Agent-independent.
|
|
76
|
+
- **Tier 2 — Nudge.** Hook detects, marker injected, agent
|
|
77
|
+
formulates the response.
|
|
78
|
+
- **Tier 3 — Inherent soft.** No platform mechanism exists. Either
|
|
79
|
+
accept as self-check, convert to user-invoked `/`-command, or
|
|
80
|
+
deprecate.
|
|
81
|
+
|
|
82
|
+
Pilot order proposed by user: roadmap-progress-sync (1) → onboarding-gate
|
|
83
|
+
(3) → context-hygiene (2). Hook surface available today: Augment
|
|
84
|
+
PostToolUse / Stop, Claude Code Stop / SessionStart. Cursor / Cline /
|
|
85
|
+
Windsurf parity is explicitly out of scope for this roadmap.
|
|
86
|
+
|
|
87
|
+
Existing precedent: `chat-history-cadence` is the only rule already
|
|
88
|
+
mechanically hardened (heartbeat marker pattern). Inventory:
|
|
89
|
+
57 rules total, 18 contain self-check phrases (`MUST`, `MANDATORY`,
|
|
90
|
+
`pre-send`, `before drafting`), 6 mention hooks today.
|
|
91
|
+
|
|
92
|
+
## Your task
|
|
93
|
+
|
|
94
|
+
Review road-to-rule-hardening.md v1 (full text appended below).
|
|
95
|
+
Be adversarial — the host will autonomously execute the pilots, so
|
|
96
|
+
catch architectural mistakes now, not after Phase 4.
|
|
97
|
+
|
|
98
|
+
1. **Three-tier model:** is Mechanical / Nudge / Inherent-soft the
|
|
99
|
+
right partition, or does it collapse meaningful distinctions?
|
|
100
|
+
Specifically: should "Tier 2 Nudge" exist at all, or is it just a
|
|
101
|
+
weaker Tier 1?
|
|
102
|
+
2. **Pilot order (1, 3, 2):** does roadmap-progress-sync prove the
|
|
103
|
+
pattern, or is it too narrow to generalise? Is per-turn counter
|
|
104
|
+
(context-hygiene) actually feasible cross-platform, or should it
|
|
105
|
+
move to Tier 3?
|
|
106
|
+
3. **Failure-class generalisation:** are there self-check rules in
|
|
107
|
+
the inventory that the audit will MISS because they fire so
|
|
108
|
+
rarely the agent has not yet observed a skip? Name 1-2 likely
|
|
109
|
+
candidates.
|
|
110
|
+
4. **Cross-platform scope:** roadmap defers Cursor/Cline/Windsurf.
|
|
111
|
+
Is this honest scope or hidden tech debt that will silently
|
|
112
|
+
block Phase 4 rollout?
|
|
113
|
+
5. **Tier 3 disposition:** the roadmap allows accept-as-soft as a
|
|
114
|
+
valid disposition. Is that a real choice, or a way to declare
|
|
115
|
+
victory without solving anything?
|
|
116
|
+
|
|
117
|
+
## Output contract (STRICT)
|
|
118
|
+
|
|
119
|
+
For EACH of the six phases:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
### Phase N — <title>
|
|
123
|
+
|
|
124
|
+
**Verdict:** <ACCEPT | PARTIAL | REJECT>
|
|
125
|
+
**What v1 gets right (1 sentence):** ...
|
|
126
|
+
**What v1 misses or over-reaches (1-2 sentences):** ...
|
|
127
|
+
**Concrete change to v2 (binding):** ...
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Then five answers to the questions above (numbered 1-5, ≤ 3 sentences
|
|
131
|
+
each).
|
|
132
|
+
|
|
133
|
+
Then a final block:
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
### Greenlight verdict
|
|
137
|
+
|
|
138
|
+
<one of: FULL GREENLIGHT — proceed with pilots / CONDITIONAL GREENLIGHT
|
|
139
|
+
— apply N revisions then proceed / BLOCKED — major rework needed>
|
|
140
|
+
|
|
141
|
+
**Binding revisions for v2 (numbered, ≤ 6):** ...
|
|
142
|
+
**Pilot order recommendation:** <1,3,2 | 1,2,3 | 3,1,2 | other>
|
|
143
|
+
**One-line architectural risk you would still proceed with:** ...
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Total response budget: ≤ 1500 words. Do not re-write the roadmap.
|
|
147
|
+
"""
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def _read(path: Path) -> str:
|
|
151
|
+
return path.read_text(encoding="utf-8") if path.exists() else ""
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def main() -> int:
|
|
155
|
+
anthropic = AnthropicClient(api_key=load_anthropic_key(), model="claude-sonnet-4-5")
|
|
156
|
+
openai = OpenAIClient(api_key=load_openai_key(), model="gpt-4o")
|
|
157
|
+
members = [anthropic, openai]
|
|
158
|
+
|
|
159
|
+
roadmap_text = _read(ROADMAP_PATH)
|
|
160
|
+
if not roadmap_text:
|
|
161
|
+
print(f"[error] roadmap not found: {ROADMAP_PATH}", file=sys.stderr)
|
|
162
|
+
return 1
|
|
163
|
+
|
|
164
|
+
bundle_text = "\n\n---\n\n".join([
|
|
165
|
+
PROMPT_HEADER,
|
|
166
|
+
"## Roadmap v1 (verbatim, the artefact to validate)\n\n" + roadmap_text,
|
|
167
|
+
])
|
|
168
|
+
context = bundle_prompt(bundle_text)
|
|
169
|
+
project = detect_project_context(REPO_ROOT)
|
|
170
|
+
table = load_prices()
|
|
171
|
+
|
|
172
|
+
question = CouncilQuestion(
|
|
173
|
+
mode="prompt",
|
|
174
|
+
user_prompt=context.text,
|
|
175
|
+
max_tokens=4096,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
estimates = estimate(
|
|
179
|
+
question, members, table, project=project, original_ask=ORIGINAL_ASK,
|
|
180
|
+
)
|
|
181
|
+
print("=== ESTIMATE (single round, max tokens) ===")
|
|
182
|
+
total_est = 0.0
|
|
183
|
+
for c, e in zip(members, estimates):
|
|
184
|
+
print(f" {c.name}/{c.model}: ~{e.input_tokens} in + {e.output_tokens} out = ${e.total_usd:.4f}")
|
|
185
|
+
total_est += e.total_usd
|
|
186
|
+
print(f" TOTAL per round (max): ${total_est:.4f}")
|
|
187
|
+
print()
|
|
188
|
+
|
|
189
|
+
budget = CostBudget(
|
|
190
|
+
max_input_tokens=200_000,
|
|
191
|
+
max_output_tokens=80_000,
|
|
192
|
+
max_calls=20,
|
|
193
|
+
max_total_usd=2.50,
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
rounds_collected: list[list] = []
|
|
197
|
+
|
|
198
|
+
def _on_round_complete(round_idx: int, round_responses) -> None:
|
|
199
|
+
rounds_collected.append(list(round_responses))
|
|
200
|
+
print(f"=== ROUND {round_idx + 1} COMPLETE ===")
|
|
201
|
+
for r in round_responses:
|
|
202
|
+
if r.error:
|
|
203
|
+
print(f" [error] {r.provider}/{r.model}: {r.error}")
|
|
204
|
+
continue
|
|
205
|
+
actual = estimate_cost(r.provider, r.model, r.input_tokens, r.output_tokens, table)
|
|
206
|
+
print(f" [done] {r.provider}/{r.model}: {r.input_tokens} in / "
|
|
207
|
+
f"{r.output_tokens} out · {r.latency_ms} ms · ${actual.total_usd:.4f}")
|
|
208
|
+
print()
|
|
209
|
+
|
|
210
|
+
print("=== CONSULT (1 round) ===")
|
|
211
|
+
consult(
|
|
212
|
+
members, question, budget,
|
|
213
|
+
rounds=1,
|
|
214
|
+
on_round_complete=_on_round_complete,
|
|
215
|
+
table=table, project=project, original_ask=ORIGINAL_ASK,
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
if not rounds_collected:
|
|
219
|
+
print("[error] no rounds completed", file=sys.stderr)
|
|
220
|
+
return 1
|
|
221
|
+
|
|
222
|
+
actual_total = 0.0
|
|
223
|
+
for round_responses in rounds_collected:
|
|
224
|
+
for r in round_responses:
|
|
225
|
+
if r.error:
|
|
226
|
+
continue
|
|
227
|
+
actual = estimate_cost(r.provider, r.model, r.input_tokens, r.output_tokens, table)
|
|
228
|
+
actual_total += actual.total_usd
|
|
229
|
+
print(f"=== TOTAL ACTUAL: ${actual_total:.4f} ===")
|
|
230
|
+
|
|
231
|
+
final_round = rounds_collected[-1]
|
|
232
|
+
if not [r for r in final_round if not r.error]:
|
|
233
|
+
return 1
|
|
234
|
+
|
|
235
|
+
manifest = SessionManifest(
|
|
236
|
+
mode="prompt",
|
|
237
|
+
artefact=str(ROADMAP_PATH.relative_to(REPO_ROOT)),
|
|
238
|
+
original_ask=ORIGINAL_ASK,
|
|
239
|
+
members=[f"{r.provider}/{r.model}" for r in final_round],
|
|
240
|
+
rounds=len(rounds_collected),
|
|
241
|
+
cost_usd_estimated=total_est,
|
|
242
|
+
cost_usd_actual=actual_total,
|
|
243
|
+
extra={"purpose": "Council review of road-to-rule-hardening v1"},
|
|
244
|
+
)
|
|
245
|
+
session_dir = save_session(manifest=manifest, responses=rounds_collected)
|
|
246
|
+
print(f"[saved] {session_dir.relative_to(REPO_ROOT)}/")
|
|
247
|
+
return 1 if any(r.error for round_r in rounds_collected for r in round_r) else 0
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
if __name__ == "__main__":
|
|
251
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"""One-off council run for the three open questions in road-to-structural-optimization.md v2.
|
|
2
|
+
|
|
3
|
+
Forces a STRUCTURED multiple-choice verdict per question across 2 rounds
|
|
4
|
+
(debate mode). Saves the session under agents/council-sessions/.
|
|
5
|
+
|
|
6
|
+
Invocation:
|
|
7
|
+
.venv/bin/python -m scripts.ai_council._one_off_structural_open_questions
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import sys
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
from scripts.ai_council.bundler import bundle_roadmap
|
|
15
|
+
from scripts.ai_council.clients import (
|
|
16
|
+
AnthropicClient,
|
|
17
|
+
OpenAIClient,
|
|
18
|
+
load_anthropic_key,
|
|
19
|
+
load_openai_key,
|
|
20
|
+
)
|
|
21
|
+
from scripts.ai_council.orchestrator import (
|
|
22
|
+
CostBudget,
|
|
23
|
+
CouncilQuestion,
|
|
24
|
+
consult,
|
|
25
|
+
estimate,
|
|
26
|
+
)
|
|
27
|
+
from scripts.ai_council.pricing import estimate_cost, load_prices
|
|
28
|
+
from scripts.ai_council.project_context import detect_project_context
|
|
29
|
+
from scripts.ai_council.session import SessionManifest, save as save_session
|
|
30
|
+
|
|
31
|
+
REPO_ROOT = Path(__file__).resolve().parents[2]
|
|
32
|
+
ROADMAP_PATH = REPO_ROOT / "agents/roadmaps/road-to-structural-optimization.md"
|
|
33
|
+
|
|
34
|
+
ORIGINAL_ASK = (
|
|
35
|
+
"Lock the three open design questions on road-to-structural-optimization.md v2 "
|
|
36
|
+
"with binding A/B verdicts + 2-3 sentence rationale each. The roadmap text "
|
|
37
|
+
"is the context. Be decisive — say A or B (or C with new option). Avoid "
|
|
38
|
+
"'depends' or 'further investigation needed'."
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
OPEN_QUESTIONS_PROMPT = """\
|
|
42
|
+
# Lock-the-Decision Council Round
|
|
43
|
+
|
|
44
|
+
You have already reviewed road-to-structural-optimization.md v2 in two prior \
|
|
45
|
+
rounds (architectural / sequencing critique). The roadmap author now needs \
|
|
46
|
+
**binding verdicts** on the three open design questions. Stop re-reviewing the \
|
|
47
|
+
roadmap. Pick A, B, or propose C with explicit justification.
|
|
48
|
+
|
|
49
|
+
## Output Contract (STRICT)
|
|
50
|
+
|
|
51
|
+
For each question, produce exactly this block:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
### Q<n>: <short title>
|
|
55
|
+
|
|
56
|
+
**Verdict:** <A | B | C>
|
|
57
|
+
**Confidence:** <Low | Medium | High>
|
|
58
|
+
**Rationale (2-4 sentences):** <why this option, what failure mode of the other you avoid>
|
|
59
|
+
**Risk if wrong:** <one sentence — what breaks if your verdict is the wrong call>
|
|
60
|
+
**Rollback if wrong:** <one sentence — how to recover if production reveals the choice was bad>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
If you propose C (new option), keep the same block structure.
|
|
64
|
+
|
|
65
|
+
## Q1 — Phase 3a Skill Consolidation Shape
|
|
66
|
+
|
|
67
|
+
The four `judge-*` skills (`judge-bug-hunter`, `judge-code-quality`, \
|
|
68
|
+
`judge-security-auditor`, `judge-test-coverage`) share procedure but \
|
|
69
|
+
have distinct persona voices. Two consolidation shapes:
|
|
70
|
+
|
|
71
|
+
- **A.** Keep four separate skills. Extract the shared procedure to \
|
|
72
|
+
`contexts/judges/judge-shared-procedure.md`. Each skill's SKILL.md \
|
|
73
|
+
loads the context via `load_context:` and adds its persona-specific \
|
|
74
|
+
delta (review heuristics, persona prompt, examples).
|
|
75
|
+
- **B.** Single skill `judge` with `mode:` parameter \
|
|
76
|
+
(`mode: bug-hunter | code-quality | security-auditor | test-coverage`). \
|
|
77
|
+
One SKILL.md dispatches; persona contexts live at \
|
|
78
|
+
`contexts/judges/personas/<mode>.md` and are loaded based on `mode:`.
|
|
79
|
+
|
|
80
|
+
**Decision criterion:** which preserves persona voice better at LLM \
|
|
81
|
+
runtime, and which is more maintainable when a fifth judge persona is \
|
|
82
|
+
added in 6 months?
|
|
83
|
+
|
|
84
|
+
## Q2 — Phase 6 chat-history Rule Consolidation Shape
|
|
85
|
+
|
|
86
|
+
Three rules (`chat-history-cadence`, `chat-history-ownership`, \
|
|
87
|
+
`chat-history-visibility`) overlap on triggers and surface but each \
|
|
88
|
+
encodes a distinct concern. Two consolidation shapes:
|
|
89
|
+
|
|
90
|
+
- **A.** One rule `chat-history` + three contexts \
|
|
91
|
+
(`contexts/chat-history/cadence.md`, `.../ownership.md`, \
|
|
92
|
+
`.../visibility.md`). The rule body holds the unified trigger language \
|
|
93
|
+
and routes to the right context section based on the matched anchor.
|
|
94
|
+
- **B.** Router rule `chat-history` + three thin specialist rules \
|
|
95
|
+
(`chat-history-cadence` etc.) reduced to <30 LOC each. Router fires \
|
|
96
|
+
first, dispatches to one specialist based on signal type \
|
|
97
|
+
(heartbeat / ownership-detection / cadence-decision).
|
|
98
|
+
|
|
99
|
+
**Decision criterion:** which is more maintainable when a fourth concern \
|
|
100
|
+
(e.g., `chat-history-archive` for log rotation) is added in 12 months, \
|
|
101
|
+
and which has lower cognitive load for an agent reading the rule first \
|
|
102
|
+
time mid-task?
|
|
103
|
+
|
|
104
|
+
## Q3 — Phase 5 Safety-Floor Rule Endorsement
|
|
105
|
+
|
|
106
|
+
Phase 5 tightens the always-rule budget. The four safety-floor rules are:
|
|
107
|
+
|
|
108
|
+
- `non-destructive-by-default` (~4,607 chars)
|
|
109
|
+
- `commit-policy` (~2,800 chars)
|
|
110
|
+
- `scope-control` (~3,900 chars)
|
|
111
|
+
- `verify-before-complete` (~3,200 chars)
|
|
112
|
+
|
|
113
|
+
Should these be in scope for slimming?
|
|
114
|
+
|
|
115
|
+
- **A.** Endorse keeping all four UNTOUCHED. Slimming risks weakening Iron \
|
|
116
|
+
Laws under budget pressure. Phase 5 hits target without them.
|
|
117
|
+
- **B.** Allow slimming with stricter 2A.4-style obligation-diff (every \
|
|
118
|
+
MUST/NEVER preserved verbatim, mechanics moved to context). Treat them \
|
|
119
|
+
like normal always-rules.
|
|
120
|
+
|
|
121
|
+
**Decision criterion:** is the marginal budget gain worth the residual \
|
|
122
|
+
risk of an Iron Law regression slipping through the obligation-diff \
|
|
123
|
+
gate?
|
|
124
|
+
|
|
125
|
+
## Final Output
|
|
126
|
+
|
|
127
|
+
After the three blocks, add:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
### Cross-question coupling
|
|
131
|
+
|
|
132
|
+
<2-3 sentences: do your verdicts on Q1/Q2/Q3 reinforce or conflict with \
|
|
133
|
+
each other? Are there hidden dependencies between them?>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Do not write an executive summary. Do not re-review v2. Pick, justify, \
|
|
137
|
+
ship. Total response budget: ≤ 1500 words.
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def main() -> int:
|
|
142
|
+
anthropic = AnthropicClient(api_key=load_anthropic_key(), model="claude-sonnet-4-5")
|
|
143
|
+
openai = OpenAIClient(api_key=load_openai_key(), model="gpt-4o")
|
|
144
|
+
members = [anthropic, openai]
|
|
145
|
+
|
|
146
|
+
context = bundle_roadmap(ROADMAP_PATH)
|
|
147
|
+
project = detect_project_context(REPO_ROOT)
|
|
148
|
+
table = load_prices()
|
|
149
|
+
|
|
150
|
+
user_prompt = OPEN_QUESTIONS_PROMPT + "\n\n---\n\n" + context.text
|
|
151
|
+
|
|
152
|
+
question = CouncilQuestion(
|
|
153
|
+
mode="roadmap",
|
|
154
|
+
user_prompt=user_prompt,
|
|
155
|
+
max_tokens=4096,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
estimates = estimate(
|
|
159
|
+
question, members, table, project=project, original_ask=ORIGINAL_ASK,
|
|
160
|
+
)
|
|
161
|
+
print("=== ESTIMATE (single round, max tokens) ===")
|
|
162
|
+
total_est = 0.0
|
|
163
|
+
for c, e in zip(members, estimates):
|
|
164
|
+
print(f" {c.name}/{c.model}: ~{e.input_tokens} in + {e.output_tokens} out = ${e.total_usd:.4f}")
|
|
165
|
+
total_est += e.total_usd
|
|
166
|
+
print(f" TOTAL per round (max): ${total_est:.4f}")
|
|
167
|
+
print(f" TOTAL 2 rounds (max): ${total_est * 2:.4f}")
|
|
168
|
+
print()
|
|
169
|
+
|
|
170
|
+
budget = CostBudget(
|
|
171
|
+
max_input_tokens=200_000,
|
|
172
|
+
max_output_tokens=80_000,
|
|
173
|
+
max_calls=20,
|
|
174
|
+
max_total_usd=2.50,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
rounds_collected: list[list] = []
|
|
178
|
+
|
|
179
|
+
def _on_round_complete(round_idx: int, round_responses) -> None:
|
|
180
|
+
rounds_collected.append(list(round_responses))
|
|
181
|
+
print(f"=== ROUND {round_idx + 1} COMPLETE ===")
|
|
182
|
+
for r in round_responses:
|
|
183
|
+
if r.error:
|
|
184
|
+
print(f" [error] {r.provider}/{r.model}: {r.error}")
|
|
185
|
+
continue
|
|
186
|
+
actual = estimate_cost(r.provider, r.model, r.input_tokens, r.output_tokens, table)
|
|
187
|
+
print(f" [done] {r.provider}/{r.model}: {r.input_tokens} in / "
|
|
188
|
+
f"{r.output_tokens} out · {r.latency_ms} ms · ${actual.total_usd:.4f}")
|
|
189
|
+
print()
|
|
190
|
+
|
|
191
|
+
print("=== CONSULT (2 rounds, debate mode) ===")
|
|
192
|
+
consult(
|
|
193
|
+
members, question, budget,
|
|
194
|
+
rounds=2,
|
|
195
|
+
on_round_complete=_on_round_complete,
|
|
196
|
+
table=table, project=project, original_ask=ORIGINAL_ASK,
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
if not rounds_collected:
|
|
200
|
+
print("[error] no rounds completed", file=sys.stderr)
|
|
201
|
+
return 1
|
|
202
|
+
|
|
203
|
+
actual_total = 0.0
|
|
204
|
+
for round_responses in rounds_collected:
|
|
205
|
+
for r in round_responses:
|
|
206
|
+
if r.error:
|
|
207
|
+
continue
|
|
208
|
+
actual = estimate_cost(r.provider, r.model, r.input_tokens, r.output_tokens, table)
|
|
209
|
+
actual_total += actual.total_usd
|
|
210
|
+
print(f"=== TOTAL ACTUAL: ${actual_total:.4f} (across {len(rounds_collected)} rounds) ===")
|
|
211
|
+
|
|
212
|
+
final_round = rounds_collected[-1]
|
|
213
|
+
if not [r for r in final_round if not r.error]:
|
|
214
|
+
return 1
|
|
215
|
+
|
|
216
|
+
manifest = SessionManifest(
|
|
217
|
+
mode="roadmap",
|
|
218
|
+
artefact=str(ROADMAP_PATH.relative_to(REPO_ROOT)),
|
|
219
|
+
original_ask=ORIGINAL_ASK,
|
|
220
|
+
members=[f"{r.provider}/{r.model}" for r in final_round],
|
|
221
|
+
rounds=len(rounds_collected),
|
|
222
|
+
cost_usd_estimated=total_est * 2,
|
|
223
|
+
cost_usd_actual=actual_total,
|
|
224
|
+
extra={"purpose": "council lock on three open questions of structural-optimization v2"},
|
|
225
|
+
)
|
|
226
|
+
session_dir = save_session(manifest=manifest, responses=rounds_collected)
|
|
227
|
+
print(f"[saved] {session_dir.relative_to(REPO_ROOT)}/")
|
|
228
|
+
return 1 if any(r.error for round_r in rounds_collected for r in round_r) else 0
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
if __name__ == "__main__":
|
|
232
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""One-off council run for road-to-structural-optimization.md.
|
|
2
|
+
|
|
3
|
+
Invokes the council in `design` mode with Anthropic + OpenAI members.
|
|
4
|
+
Saves the session under agents/contexts/ai-council-sessions/.
|
|
5
|
+
|
|
6
|
+
Invocation:
|
|
7
|
+
.venv/bin/python -m scripts.ai_council._one_off_structural_optimization
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import sys
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
from scripts.ai_council.bundler import bundle_roadmap
|
|
15
|
+
from scripts.ai_council.clients import (
|
|
16
|
+
AnthropicClient,
|
|
17
|
+
OpenAIClient,
|
|
18
|
+
load_anthropic_key,
|
|
19
|
+
load_openai_key,
|
|
20
|
+
)
|
|
21
|
+
from scripts.ai_council.orchestrator import (
|
|
22
|
+
CostBudget,
|
|
23
|
+
CouncilQuestion,
|
|
24
|
+
consult,
|
|
25
|
+
estimate,
|
|
26
|
+
)
|
|
27
|
+
from scripts.ai_council.pricing import estimate_cost, load_prices
|
|
28
|
+
from scripts.ai_council.project_context import detect_project_context
|
|
29
|
+
from scripts.ai_council.session import SessionManifest, save as save_session
|
|
30
|
+
|
|
31
|
+
REPO_ROOT = Path(__file__).resolve().parents[2]
|
|
32
|
+
ROADMAP_PATH = REPO_ROOT / "agents/roadmaps/road-to-structural-optimization.md"
|
|
33
|
+
|
|
34
|
+
ORIGINAL_ASK = (
|
|
35
|
+
"Review road-to-structural-optimization.md DRAFT v2 (council-revised). "
|
|
36
|
+
"This is a SECOND independent review of a roadmap that already folded "
|
|
37
|
+
"in five convergence findings from a prior council pass (2026-05-03 "
|
|
38
|
+
"06:52 UTC, anthropic+openai). v2 changes vs. v1: 2A/2B split (always "
|
|
39
|
+
"vs. auto rules), Spike 3a.0 with kill criterion before 3a.1+, "
|
|
40
|
+
"obligation-diff contract 2A.4 with worked example, budget kill-switch "
|
|
41
|
+
"2A, Phase-6-before-2B sequencing, file-ownership matrix gate, per-skill "
|
|
42
|
+
"30%% LOC bar (not average). Three open questions remain: (1) Phase 3a "
|
|
43
|
+
"shape — separate skills + shared context vs. single dispatcher with "
|
|
44
|
+
"mode parameter; (2) Phase 6 shape — one rule + three contexts vs. "
|
|
45
|
+
"router + three thin specialists; (3) Phase 5 endorsement that safety-"
|
|
46
|
+
"floor rules (non-destructive-by-default, commit-policy, scope-control, "
|
|
47
|
+
"verify-before-complete) stay untouched. Mode: design — focus on "
|
|
48
|
+
"architectural risk, sequencing risk, missing rollback, hidden coupling, "
|
|
49
|
+
"AND whether v2's mitigations actually close the v1 critiques. Be hard "
|
|
50
|
+
"on residual gaps; do not rubber-stamp."
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def main() -> int:
|
|
55
|
+
anthropic = AnthropicClient(api_key=load_anthropic_key(), model="claude-sonnet-4-5")
|
|
56
|
+
openai = OpenAIClient(api_key=load_openai_key(), model="gpt-4o")
|
|
57
|
+
members = [anthropic, openai]
|
|
58
|
+
|
|
59
|
+
context = bundle_roadmap(ROADMAP_PATH)
|
|
60
|
+
project = detect_project_context(REPO_ROOT)
|
|
61
|
+
table = load_prices()
|
|
62
|
+
|
|
63
|
+
question = CouncilQuestion(
|
|
64
|
+
mode="roadmap",
|
|
65
|
+
user_prompt=context.text,
|
|
66
|
+
max_tokens=8192,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
estimates = estimate(
|
|
70
|
+
question, members, table, project=project, original_ask=ORIGINAL_ASK,
|
|
71
|
+
)
|
|
72
|
+
print("=== ESTIMATE (single round, max tokens) ===")
|
|
73
|
+
total_est = 0.0
|
|
74
|
+
for c, e in zip(members, estimates):
|
|
75
|
+
print(f" {c.name}/{c.model}: ~{e.input_tokens} in + {e.output_tokens} out = ${e.total_usd:.4f}")
|
|
76
|
+
total_est += e.total_usd
|
|
77
|
+
print(f" TOTAL per round (max): ${total_est:.4f}")
|
|
78
|
+
print(f" TOTAL 2 rounds (max, ignoring round-2 prompt growth): ${total_est * 2:.4f}")
|
|
79
|
+
print()
|
|
80
|
+
|
|
81
|
+
budget = CostBudget(
|
|
82
|
+
max_input_tokens=200_000,
|
|
83
|
+
max_output_tokens=80_000,
|
|
84
|
+
max_calls=20,
|
|
85
|
+
max_total_usd=2.50,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
rounds_collected: list[list] = []
|
|
89
|
+
|
|
90
|
+
def _on_round_complete(round_idx: int, round_responses) -> None:
|
|
91
|
+
rounds_collected.append(list(round_responses))
|
|
92
|
+
print(f"=== ROUND {round_idx + 1} COMPLETE ===")
|
|
93
|
+
for r in round_responses:
|
|
94
|
+
if r.error:
|
|
95
|
+
print(f" [error] {r.provider}/{r.model}: {r.error}")
|
|
96
|
+
continue
|
|
97
|
+
actual = estimate_cost(r.provider, r.model, r.input_tokens, r.output_tokens, table)
|
|
98
|
+
print(f" [done] {r.provider}/{r.model}: {r.input_tokens} in / "
|
|
99
|
+
f"{r.output_tokens} out · {r.latency_ms} ms · ${actual.total_usd:.4f}")
|
|
100
|
+
print()
|
|
101
|
+
|
|
102
|
+
print("=== CONSULT (2 rounds, debate mode) ===")
|
|
103
|
+
consult(
|
|
104
|
+
members, question, budget,
|
|
105
|
+
rounds=2,
|
|
106
|
+
on_round_complete=_on_round_complete,
|
|
107
|
+
table=table, project=project, original_ask=ORIGINAL_ASK,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
if not rounds_collected:
|
|
111
|
+
print("[error] no rounds completed", file=sys.stderr)
|
|
112
|
+
return 1
|
|
113
|
+
|
|
114
|
+
actual_total = 0.0
|
|
115
|
+
for round_idx, round_responses in enumerate(rounds_collected, start=1):
|
|
116
|
+
for r in round_responses:
|
|
117
|
+
if r.error:
|
|
118
|
+
continue
|
|
119
|
+
actual = estimate_cost(r.provider, r.model, r.input_tokens, r.output_tokens, table)
|
|
120
|
+
actual_total += actual.total_usd
|
|
121
|
+
print(f"=== TOTAL ACTUAL: ${actual_total:.4f} (across {len(rounds_collected)} rounds) ===")
|
|
122
|
+
|
|
123
|
+
final_round = rounds_collected[-1]
|
|
124
|
+
successes = [r for r in final_round if not r.error]
|
|
125
|
+
if not successes:
|
|
126
|
+
return 1
|
|
127
|
+
|
|
128
|
+
manifest = SessionManifest(
|
|
129
|
+
mode="roadmap",
|
|
130
|
+
artefact=str(ROADMAP_PATH.relative_to(REPO_ROOT)),
|
|
131
|
+
original_ask=ORIGINAL_ASK,
|
|
132
|
+
members=[f"{r.provider}/{r.model}" for r in final_round],
|
|
133
|
+
rounds=len(rounds_collected),
|
|
134
|
+
cost_usd_estimated=total_est * 2,
|
|
135
|
+
cost_usd_actual=actual_total,
|
|
136
|
+
extra={"purpose": "council-design 2-round debate on structural optimization roadmap v2"},
|
|
137
|
+
)
|
|
138
|
+
session_dir = save_session(manifest=manifest, responses=rounds_collected)
|
|
139
|
+
print(f"[saved] {session_dir.relative_to(REPO_ROOT)}/")
|
|
140
|
+
return 1 if any(r.error for round_r in rounds_collected for r in round_r) else 0
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
if __name__ == "__main__":
|
|
144
|
+
raise SystemExit(main())
|