agent-composer 0.3.0 → 0.4.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/README.md +495 -180
- package/composer.config.schema.json +206 -2
- package/dist/cli/cleanup.d.ts +24 -0
- package/dist/cli/cleanup.js +151 -0
- package/dist/cli/cleanup.js.map +1 -0
- package/dist/cli/doctor.d.ts +12 -0
- package/dist/cli/doctor.js +244 -4
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/goal.d.ts +28 -0
- package/dist/cli/goal.js +251 -0
- package/dist/cli/goal.js.map +1 -0
- package/dist/cli/help.d.ts +3 -0
- package/dist/cli/help.js +31 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/init.d.ts +5 -0
- package/dist/cli/init.js +116 -21
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/initArgs.d.ts +16 -0
- package/dist/cli/initArgs.js +19 -0
- package/dist/cli/initArgs.js.map +1 -0
- package/dist/cli/installGitHook.d.ts +7 -0
- package/dist/cli/installGitHook.js +61 -0
- package/dist/cli/installGitHook.js.map +1 -0
- package/dist/cli/mode.d.ts +6 -0
- package/dist/cli/mode.js +25 -0
- package/dist/cli/mode.js.map +1 -0
- package/dist/cli/status.d.ts +105 -0
- package/dist/cli/status.js +400 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/config/env.d.ts +1 -1
- package/dist/config/modes.d.ts +10 -0
- package/dist/config/modes.js +26 -0
- package/dist/config/modes.js.map +1 -0
- package/dist/config/oracleRole.d.ts +10 -0
- package/dist/config/oracleRole.js +11 -0
- package/dist/config/oracleRole.js.map +1 -0
- package/dist/config/schema.d.ts +246 -0
- package/dist/config/schema.js +127 -2
- package/dist/config/schema.js.map +1 -1
- package/dist/evolve/reflection.d.ts +9 -0
- package/dist/evolve/reflection.js +14 -0
- package/dist/evolve/reflection.js.map +1 -1
- package/dist/evolve/runner.d.ts +2 -1
- package/dist/evolve/runner.js +2 -1
- package/dist/evolve/runner.js.map +1 -1
- package/dist/index.js +115 -6
- package/dist/index.js.map +1 -1
- package/dist/providers/AnthropicCompatibleProvider.d.ts +13 -1
- package/dist/providers/AnthropicCompatibleProvider.js +115 -9
- package/dist/providers/AnthropicCompatibleProvider.js.map +1 -1
- package/dist/providers/CLIProvider.d.ts +23 -1
- package/dist/providers/CLIProvider.js +283 -65
- package/dist/providers/CLIProvider.js.map +1 -1
- package/dist/providers/IProvider.d.ts +13 -0
- package/dist/providers/SpendGuardProvider.d.ts +32 -0
- package/dist/providers/SpendGuardProvider.js +98 -0
- package/dist/providers/SpendGuardProvider.js.map +1 -0
- package/dist/registry.d.ts +5 -2
- package/dist/registry.js +17 -2
- package/dist/registry.js.map +1 -1
- package/dist/server/activeRuns.d.ts +17 -0
- package/dist/server/activeRuns.js +114 -0
- package/dist/server/activeRuns.js.map +1 -0
- package/dist/server/codexLifecycleRunner.d.ts +29 -0
- package/dist/server/codexLifecycleRunner.js +188 -0
- package/dist/server/codexLifecycleRunner.js.map +1 -0
- package/dist/server/configMutation.d.ts +22 -0
- package/dist/server/configMutation.js +121 -0
- package/dist/server/configMutation.js.map +1 -0
- package/dist/server/handoffContext.d.ts +1 -0
- package/dist/server/handoffContext.js +12 -0
- package/dist/server/handoffContext.js.map +1 -0
- package/dist/server/progress.d.ts +24 -0
- package/dist/server/progress.js +109 -0
- package/dist/server/progress.js.map +1 -0
- package/dist/server/toolDescriptions.d.ts +60 -0
- package/dist/server/toolDescriptions.js +134 -0
- package/dist/server/toolDescriptions.js.map +1 -0
- package/dist/server.d.ts +19 -21
- package/dist/server.js +90 -330
- package/dist/server.js.map +1 -1
- package/dist/tools/audit.d.ts +2 -0
- package/dist/tools/audit.js +66 -0
- package/dist/tools/audit.js.map +1 -0
- package/dist/tools/code.d.ts +2 -0
- package/dist/tools/code.js +160 -0
- package/dist/tools/code.js.map +1 -0
- package/dist/tools/codexLifecycle.d.ts +2 -0
- package/dist/tools/codexLifecycle.js +206 -0
- package/dist/tools/codexLifecycle.js.map +1 -0
- package/dist/tools/config.d.ts +2 -0
- package/dist/tools/config.js +183 -0
- package/dist/tools/config.js.map +1 -0
- package/dist/tools/context.d.ts +31 -0
- package/dist/tools/context.js +2 -0
- package/dist/tools/context.js.map +1 -0
- package/dist/tools/goal.d.ts +2 -0
- package/dist/tools/goal.js +159 -0
- package/dist/tools/goal.js.map +1 -0
- package/dist/tools/handoff.d.ts +2 -0
- package/dist/tools/handoff.js +57 -0
- package/dist/tools/handoff.js.map +1 -0
- package/dist/tools/oracle.d.ts +2 -0
- package/dist/tools/oracle.js +248 -0
- package/dist/tools/oracle.js.map +1 -0
- package/dist/tools/research.d.ts +2 -0
- package/dist/tools/research.js +51 -0
- package/dist/tools/research.js.map +1 -0
- package/dist/tools/review.d.ts +2 -0
- package/dist/tools/review.js +233 -0
- package/dist/tools/review.js.map +1 -0
- package/dist/tools/route.d.ts +2 -0
- package/dist/tools/route.js +69 -0
- package/dist/tools/route.js.map +1 -0
- package/dist/tools/session.d.ts +2 -0
- package/dist/tools/session.js +37 -0
- package/dist/tools/session.js.map +1 -0
- package/dist/tools/status.d.ts +2 -0
- package/dist/tools/status.js +34 -0
- package/dist/tools/status.js.map +1 -0
- package/dist/tools/workflow.d.ts +2 -0
- package/dist/tools/workflow.js +27 -0
- package/dist/tools/workflow.js.map +1 -0
- package/dist/util/applyFileBlocks.d.ts +18 -0
- package/dist/util/applyFileBlocks.js +163 -0
- package/dist/util/applyFileBlocks.js.map +1 -0
- package/dist/util/asyncControl.d.ts +14 -0
- package/dist/util/asyncControl.js +106 -0
- package/dist/util/asyncControl.js.map +1 -0
- package/dist/util/auditLog.d.ts +56 -0
- package/dist/util/auditLog.js +232 -0
- package/dist/util/auditLog.js.map +1 -0
- package/dist/util/codexLifecycle.d.ts +55 -0
- package/dist/util/codexLifecycle.js +102 -0
- package/dist/util/codexLifecycle.js.map +1 -0
- package/dist/util/codexLifecycleJob.d.ts +209 -0
- package/dist/util/codexLifecycleJob.js +360 -0
- package/dist/util/codexLifecycleJob.js.map +1 -0
- package/dist/util/composerDisabled.d.ts +6 -0
- package/dist/util/composerDisabled.js +27 -0
- package/dist/util/composerDisabled.js.map +1 -0
- package/dist/util/dispatchHint.d.ts +5 -3
- package/dist/util/dispatchHint.js +62 -2
- package/dist/util/dispatchHint.js.map +1 -1
- package/dist/util/goal.d.ts +132 -0
- package/dist/util/goal.js +616 -0
- package/dist/util/goal.js.map +1 -0
- package/dist/util/goalReport.d.ts +51 -0
- package/dist/util/goalReport.js +164 -0
- package/dist/util/goalReport.js.map +1 -0
- package/dist/util/jobPolling.d.ts +9 -0
- package/dist/util/jobPolling.js +17 -0
- package/dist/util/jobPolling.js.map +1 -0
- package/dist/util/oracleJob.d.ts +66 -0
- package/dist/util/oracleJob.js +295 -0
- package/dist/util/oracleJob.js.map +1 -0
- package/dist/util/oracleLock.d.ts +38 -0
- package/dist/util/oracleLock.js +182 -0
- package/dist/util/oracleLock.js.map +1 -0
- package/dist/util/reviewDiff.d.ts +8 -0
- package/dist/util/reviewDiff.js +29 -0
- package/dist/util/reviewDiff.js.map +1 -0
- package/dist/util/reviewJob.d.ts +57 -0
- package/dist/util/reviewJob.js +207 -0
- package/dist/util/reviewJob.js.map +1 -0
- package/dist/util/workflowPlan.d.ts +24 -0
- package/dist/util/workflowPlan.js +49 -0
- package/dist/util/workflowPlan.js.map +1 -0
- package/package.json +8 -1
- package/plugin/composer-mastermind/commands/evolve.md +4 -0
- package/plugin/composer-mastermind/hooks/boundary_guard.sh +43 -2
- package/plugin/composer-mastermind/hooks/codex_warm_review.sh +161 -9
- package/plugin/composer-mastermind/hooks/learn.sh +172 -32
- package/plugin/composer-mastermind/hooks/precommit_codex_review.sh +430 -62
- package/plugin/composer-mastermind/plugin.json +1 -1
- package/plugin/composer-mastermind/skills/composer-mastermind/SKILL.md +190 -4
- package/scripts/composer-oracle-router-safe.sh +47 -0
- package/scripts/composer-statusline-segment.mjs +40 -0
- package/scripts/oracle-codex-handoff-safe.sh +49 -0
- package/scripts/oracle-plan-mcp.sh +66 -0
- package/scripts/oracle-pro-safe.sh +471 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "composer-mastermind",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Multi-agent orchestrator: Claude as brain, GLM/Codex/agy as executors. Dispatches code/research/review work to subagents wired through the @composer-mcp/server MCP server.",
|
|
5
5
|
"claudeCodeVersion": ">=4.6",
|
|
6
6
|
"requires": [
|
|
@@ -60,8 +60,43 @@ system — spend it on planning, not on raw worker output.
|
|
|
60
60
|
| Generate a patch WITHOUT applying (rare) | `coder` subagent (`composer_code` → `coder` applies) |
|
|
61
61
|
| Reviewing a candidate patch / diff / implementation | `composer_review` directly; use `reviewer` only for high-volume isolation |
|
|
62
62
|
| Claude review explicitly requested, or high-risk/security-sensitive second opinion | `composer_review_claude` directly after the default review gate |
|
|
63
|
+
| Deep architecture / feature planning, migration design, hard root-cause debugging, or high-risk review where you want ChatGPT Pro's extended reasoning (opt-in) | `composer_oracle_plan` directly; advisory planning only — file edits still go through `composer_code_cli` |
|
|
63
64
|
| Anything that mutates state outside the conversation (push, deploy, install) | Escalate to the user. Do not act. |
|
|
64
65
|
|
|
66
|
+
When an edit targets a project other than the Composer MCP server cwd (for
|
|
67
|
+
example dotfiles or another repo), pass `projectDir: "<absolute path>"` to
|
|
68
|
+
`composer_code_cli` or `composer_code_chain`. Codex must trust that directory
|
|
69
|
+
(a git repo or a `config.toml` projects entry) or it will refuse; do not add
|
|
70
|
+
`--skip-git-repo-check`.
|
|
71
|
+
|
|
72
|
+
## Oracle planning lane (ChatGPT Pro — opt-in)
|
|
73
|
+
|
|
74
|
+
`composer_oracle_plan` consults ChatGPT Pro through the Oracle browser
|
|
75
|
+
(`scripts/oracle-pro-safe.sh`) for extended-reasoning planning, design,
|
|
76
|
+
migration, hard debugging, or high-risk review. It is OPT-IN and NOT the
|
|
77
|
+
default research lane — `composer_research` stays on Codex to keep routine
|
|
78
|
+
lookups fast and cheap.
|
|
79
|
+
|
|
80
|
+
- Use it deliberately: a `deep` / `review` / `debug` run drives a real browser
|
|
81
|
+
ChatGPT Pro session (slow, supervised). Do not route routine research here.
|
|
82
|
+
- `mode` selects thinking depth: `quick` / `standard` keep a fast model;
|
|
83
|
+
`deep` / `plan` / `review` / `debug` select ChatGPT Pro; `research` adds Deep
|
|
84
|
+
Research. Omit (`auto`) to let the script classify.
|
|
85
|
+
- It is ADVISORY: the tool never edits files. Hand its plan to
|
|
86
|
+
`composer_code_cli` for implementation, then `composer_review`.
|
|
87
|
+
- Requires a one-time Oracle browser login and the `oraclePlanner` role in the
|
|
88
|
+
active config. Full answers persist under `.composer/oracle/answers/`
|
|
89
|
+
(gitignored); the tool returns a bounded summary.
|
|
90
|
+
- For long deep-research, large architectural reviews, or when the user says not
|
|
91
|
+
to block, use the async pair instead: `composer_oracle_job_start` returns a
|
|
92
|
+
`jobId` immediately, then `composer_oracle_job_result` (optionally with
|
|
93
|
+
`waitMs`) pulls the answer when the job reaches `succeeded`. Both run off-CC and
|
|
94
|
+
return bounded summaries.
|
|
95
|
+
- Default to the synchronous `composer_oracle_plan` whenever the next step
|
|
96
|
+
depends on the answer (most planning/review). Reach for the async job pair only
|
|
97
|
+
when the answer is useful but not immediately blocking, or on an explicit
|
|
98
|
+
`[oracle:async]` request. Do not make every deep/review/debug call async.
|
|
99
|
+
|
|
65
100
|
## Codex rescue (second-opinion lane)
|
|
66
101
|
|
|
67
102
|
Use Codex rescue when the same bug has 2+ failed fix attempts, root-cause
|
|
@@ -81,6 +116,84 @@ or the user asks for a second opinion.
|
|
|
81
116
|
latest failing command, changed files, and smallest repro. Do not include the
|
|
82
117
|
whole transcript, secrets, or `.env.json`.
|
|
83
118
|
|
|
119
|
+
## Codex lifecycle participation
|
|
120
|
+
|
|
121
|
+
Use `codexLifecycle` for ambient Codex involvement across the development
|
|
122
|
+
loop. This is separate from `codexReview` (mechanical diff gate) and
|
|
123
|
+
`codexRescue` (stuck-debug escalation). It answers one question: should Codex
|
|
124
|
+
join this lifecycle step now?
|
|
125
|
+
|
|
126
|
+
- Read root `composer.config.json` `codexLifecycle`.
|
|
127
|
+
- If omitted or `enabled:false`, skip lifecycle participation. Existing
|
|
128
|
+
`composer_code_cli`, `codexReview`, and `codexRescue` rules still apply.
|
|
129
|
+
- For non-trivial feature/debug work, call `composer_handoff_create` first so
|
|
130
|
+
Codex and reviewers share the same objective, constraints, files, and
|
|
131
|
+
acceptance criteria.
|
|
132
|
+
- Call `composer_codex_lifecycle_decide` at eligible points with compact
|
|
133
|
+
signals: `event`, `expectedOutputTokens`, `changedFiles`, `diffLines`,
|
|
134
|
+
`failedAttempts`, `failingTests`, `touchesSecurity`, `touchesInfra`,
|
|
135
|
+
`userRequestedCodex`, `hasHandoff`, `isTrivial`, `isDestructive`, and `risk`.
|
|
136
|
+
- Treat the decision literally:
|
|
137
|
+
- `skip`: do not involve Codex for this lifecycle step.
|
|
138
|
+
- `ask`: ask the user before involving Codex, naming the event and reason.
|
|
139
|
+
- `run`: Codex may participate automatically within the configured mode,
|
|
140
|
+
model, execution, and spend/safety constraints.
|
|
141
|
+
- When the decision is `run`, call `composer_codex_lifecycle_run` with the
|
|
142
|
+
same event, handoff, prompt, and signals.
|
|
143
|
+
- When the decision is `ask` and the user confirms, call
|
|
144
|
+
`composer_codex_lifecycle_run` with `confirmed:true`; do not set
|
|
145
|
+
`confirmed:true` for policy `skip` outcomes.
|
|
146
|
+
- If lifecycle execution is `foreground`, use the returned result before
|
|
147
|
+
continuing.
|
|
148
|
+
- If lifecycle execution is `background`, keep the returned `jobId` and call
|
|
149
|
+
`composer_codex_lifecycle_result` before reporting the lifecycle step done.
|
|
150
|
+
Background Codex output is not complete until its durable result record is
|
|
151
|
+
`succeeded`, `failed`, `unavailable`, or deliberately `skipped`.
|
|
152
|
+
- Treat `skipped` as a policy decision and `unavailable` as a provider/session
|
|
153
|
+
failure (`auth`, `quota`, `rate_limit`, `timeout`, `cancelled`, `provider`,
|
|
154
|
+
or `unknown`). If `codexLifecycle.fallback.enabled`, Composer tries
|
|
155
|
+
`coderCli` first and then configured fallback roles such as `reviewerClaude`,
|
|
156
|
+
`reviewer`, or `coder`; always surface `providerRole`, `fallbackUsed`, and
|
|
157
|
+
the attempts list when a fallback handled the checkpoint. Optional lifecycle
|
|
158
|
+
jobs may continue after surfacing this; forced pre-commit review gates must
|
|
159
|
+
fail closed through `codexReview`.
|
|
160
|
+
- Lifecycle Codex runs are companion/advisory passes. Do not let background
|
|
161
|
+
lifecycle runs silently mutate files; integrate any suggestions deliberately
|
|
162
|
+
and gate code changes through review.
|
|
163
|
+
|
|
164
|
+
## Composer config tools
|
|
165
|
+
|
|
166
|
+
When the user asks to turn Composer/Codex lifecycle behavior on/off, set
|
|
167
|
+
fallback providers, or harden the pre-commit gate, prefer MCP config tools over
|
|
168
|
+
manual JSON editing:
|
|
169
|
+
|
|
170
|
+
- Call `composer_config_get` first with `scope:"active"` unless the user names
|
|
171
|
+
project or global config explicitly.
|
|
172
|
+
- Call `composer_config_set` with a narrow patch for `codexLifecycle` and/or
|
|
173
|
+
`codexReview`; the server validates before writing.
|
|
174
|
+
- Use `scope:"project"` for repo-local `composer.config.json` and
|
|
175
|
+
`scope:"global"` for `~/.config/composer/composer.config.json`.
|
|
176
|
+
- If `scope:"active"` resolves to the user-global fallback, call
|
|
177
|
+
`composer_config_set` again with `scope:"global"` explicitly; Composer
|
|
178
|
+
refuses implicit global writes.
|
|
179
|
+
- After config changes, run `agent-composer doctor` and report the effective
|
|
180
|
+
lifecycle mode, fallback order, and pre-commit gate state.
|
|
181
|
+
|
|
182
|
+
Default trigger intent:
|
|
183
|
+
|
|
184
|
+
| Event | Use when |
|
|
185
|
+
|---|---|
|
|
186
|
+
| `postPlan` | a plan is ready and design risk is non-trivial |
|
|
187
|
+
| `postCodeApply` | code was applied and the diff is broad or risky |
|
|
188
|
+
| `postTestFailure` | targeted checks fail after implementation |
|
|
189
|
+
| `afterFailedAttempts` | the same bug/fix has failed repeatedly |
|
|
190
|
+
| `postResearch` | research output needs a second synthesis pass |
|
|
191
|
+
| `preCommit` | optional policy layer before the mechanical gate |
|
|
192
|
+
| `stopWarm` | passive background/warm participation is configured |
|
|
193
|
+
|
|
194
|
+
Never use lifecycle participation to bypass user confirmation for destructive
|
|
195
|
+
actions, secret handling, deploys, pushes, or billing-affecting changes.
|
|
196
|
+
|
|
84
197
|
**Class-based route policy:** route by task class, not by a blanket
|
|
85
198
|
"always dispatch" rule.
|
|
86
199
|
|
|
@@ -121,6 +234,62 @@ expected-output estimate; if under 5 lines, just answer.
|
|
|
121
234
|
|
|
122
235
|
**Fan-out cap:** Max 3 parallel worker dispatches per turn for repos with >500 source files. Beyond 3, the prompt-cache misses compound faster than the parallelism saves wall time. If file slices overlap across workers, dispatch SEQUENTIALLY — parallel workers on the same files duplicate every Read.
|
|
123
236
|
|
|
237
|
+
# Control plane (status, route, workflow, session, audit)
|
|
238
|
+
|
|
239
|
+
These tools make routing explicit and cheap. Prefer them over re-deriving policy from this skill every turn.
|
|
240
|
+
|
|
241
|
+
- **`composer_status`** — read-only state snapshot: mode, integrations (review / lifecycle / oracle / git-hook / disabled), the active FOREGROUND worker, active/latest async jobs, latest audit facts, and a recommended next action. Inside Claude Code prefer this over the `agent-composer status` CLI — only the MCP tool sees live in-session `composer_session_*` overrides.
|
|
242
|
+
- **`composer_route_decide`** — preview the route for a prompt WITHOUT executing: returns `target`, `taskClass`, `contextBudget`, and `recommendedNextTools`. Output is `compact` by default; pass `format:"full"` only when debugging the classifier. Call it before a worker dispatch when the right lane is unclear; it spends no worker tokens.
|
|
243
|
+
- **`composer_workflow_plan`** — recommend (do NOT execute) the ordered tool sequence for a goal (`feature` / `debug` / `review` / `research`, tuned by mode + risk). It returns steps; you still call each tool yourself.
|
|
244
|
+
- **`composer_session_get` / `composer_session_set`** — EPHEMERAL per-session overrides (mode, oracle, code_cli `profile`) that do NOT write `composer.config.json`. Use for "this session only" toggles; `clear:true` resets. For durable changes use `composer_config_set`.
|
|
245
|
+
- **`composer_audit_record` / `composer_audit_read` / `composer_audit_summary`** — durable route/outcome trail. After a dispatch, record what happened (route, provider, `reviewVerdict`, `testsPassed`, `userCorrection`, `status`) so `/evolve` learns from real failures, not transcripts. Recording is EXPLICIT — these tools are never auto-called; keep `note`/`objective` short (capped on write). Read/summary to inspect route accuracy.
|
|
246
|
+
|
|
247
|
+
# Subagent speed contract
|
|
248
|
+
|
|
249
|
+
Fast path for quick inspection and minimal wait:
|
|
250
|
+
|
|
251
|
+
1. Call `composer_route_decide` with `format:"compact"` — local, no model.
|
|
252
|
+
Do NOT request `format:"full"` unless debugging the classifier.
|
|
253
|
+
2. Honor returned `contextBudget` (`inline` / `handoff` / `scoped-diff` /
|
|
254
|
+
`full-brief` / `oracle-brief`). Send only matching context, NEVER a raw
|
|
255
|
+
transcript.
|
|
256
|
+
3. Prefer `composer_code_cli` for implementation; the executor applies off-CC.
|
|
257
|
+
4. Use `reviewScope` (`staged` / `working-tree` / `branch`). NEVER paste broad
|
|
258
|
+
diffs.
|
|
259
|
+
5. Background, don't block: use `composer_review_job_start` +
|
|
260
|
+
`composer_review_job_result` for routine/advisory review while continuing
|
|
261
|
+
work. Reserve synchronous `composer_review` for the pre-commit / merge gate
|
|
262
|
+
or explicit "review now". Likewise prefer background lifecycle
|
|
263
|
+
(`execution:"background"`).
|
|
264
|
+
6. NEVER call Oracle unless explicitly tagged `[oracle:<mode>]` or the route
|
|
265
|
+
says premium escalation.
|
|
266
|
+
7. For quick state checks use `agent-composer status --fast` (skips audit /
|
|
267
|
+
job / goal scans). Do NOT pull full status/audit unless debugging
|
|
268
|
+
orchestration.
|
|
269
|
+
8. Reserve the synchronous fail-closed review gate for commits. If a greenfield
|
|
270
|
+
subsystem oscillates the gate, set
|
|
271
|
+
`codexReview.preCommitHook.maxConsecutiveBlocks` instead of grinding.
|
|
272
|
+
|
|
273
|
+
## contextBudget (how much context to send)
|
|
274
|
+
|
|
275
|
+
`composer_route_decide` returns a `contextBudget`. Honor it — send ONLY the matching context, NEVER a raw transcript:
|
|
276
|
+
|
|
277
|
+
| contextBudget | Send |
|
|
278
|
+
|---|---|
|
|
279
|
+
| `inline` | the prompt only (or answer inline; no worker) |
|
|
280
|
+
| `handoff` | a `composer_handoff_create` `handoffPath` |
|
|
281
|
+
| `scoped-diff` | a `reviewScope` (let the server compute the diff) |
|
|
282
|
+
| `full-brief` | handoff + the exact files / constraints |
|
|
283
|
+
| `oracle-brief` | a compact problem / architecture brief, never a repo dump |
|
|
284
|
+
|
|
285
|
+
## Scoped review (do not paste broad diffs)
|
|
286
|
+
|
|
287
|
+
`composer_review` / `composer_review_claude` accept `reviewScope` (`staged` | `unstaged` | `working-tree` | `branch`) plus optional `base` and `reviewFiles`. Pass a scope and let the server compute the diff off-CC — do NOT paste a broad diff into the prompt. Use `staged` for pre-commit review, `working-tree` for routine review, `branch` (+ `base`) for a PR-sized review. A pasted `diff` still works but costs main-session tokens.
|
|
288
|
+
|
|
289
|
+
## Codex profiles
|
|
290
|
+
|
|
291
|
+
`composer_code_cli` accepts `profile` to select a `codexProfiles` lane from config (model / reasoning effort / sandbox) — e.g. a cheap `fast` lane or a `deep` lane. A session `profile` set via `composer_session_set` applies when no explicit `profile` is passed.
|
|
292
|
+
|
|
124
293
|
# Explorer protocol (large-repo dispatches)
|
|
125
294
|
|
|
126
295
|
For repos with >500 source files (or any unfamiliar codebase), prefer an
|
|
@@ -195,10 +364,12 @@ global stop-gate; it fires on every stop.
|
|
|
195
364
|
A stronger, optional enforcement: `codexReview.preCommitHook.enabled` turns the
|
|
196
365
|
PreToolUse hook `precommit_codex_review.sh` into a hard gate — a `git commit`
|
|
197
366
|
is DENIED when Codex review returns `needs-attention` with a finding at or above
|
|
198
|
-
`preCommitHook.blockOnSeverity` (default `high`).
|
|
199
|
-
(`failClosed:false`)
|
|
200
|
-
`
|
|
201
|
-
|
|
367
|
+
`preCommitHook.blockOnSeverity` (default `high`). The default is fail-open
|
|
368
|
+
(`failClosed:false`), but strict local/project configs should set
|
|
369
|
+
`failClosed:true`; then Codex auth, quota, rate-limit, timeout, or parse
|
|
370
|
+
failures block the commit. Run `agent-composer doctor` to see the gate state.
|
|
371
|
+
This is mechanical (hook-enforced), unlike the orchestrator-driven triggers
|
|
372
|
+
above.
|
|
202
373
|
|
|
203
374
|
# Headless invocation
|
|
204
375
|
|
|
@@ -225,6 +396,21 @@ Rules:
|
|
|
225
396
|
- Override when the orchestration plan itself is non-trivial (>3
|
|
226
397
|
dispatches, cross-file integration). Then Opus 4.7 earns its keep.
|
|
227
398
|
|
|
399
|
+
## Authorizing file-writing workers
|
|
400
|
+
|
|
401
|
+
`boundary_guard.sh` enforces globally now: it denies main-thread
|
|
402
|
+
`Edit/Update/Write/NotebookEdit` in EVERY repo unless Composer is disabled.
|
|
403
|
+
A headless `claude -p` worker you spawn to AUTHOR files (multi-file
|
|
404
|
+
scaffolding, byte-exact reproduction) runs as its own main thread and will be
|
|
405
|
+
blocked. When you spawn such an authorized worker, set the
|
|
406
|
+
`COMPOSER_DANGEROUSLY_BYPASS_PERMISSIONS` env var to `1` in its environment
|
|
407
|
+
so its writes are allowed — prefix the variable on the worker's command line,
|
|
408
|
+
ahead of `claude -p ...` (the boundary_guard deny message prints the exact
|
|
409
|
+
form to use).
|
|
410
|
+
Do NOT export that variable in your own interactive shell — set it only on the
|
|
411
|
+
spawned worker, so the interactive Brain stays gated and routes through
|
|
412
|
+
`composer_code_cli`.
|
|
413
|
+
|
|
228
414
|
# Token discipline
|
|
229
415
|
|
|
230
416
|
- You hold context, plans, and integration. Workers hold execution.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Router intended for agent-composer's existing `researcher` cli provider.
|
|
5
|
+
# Composer appends the prompt as the final argv item; this wrapper joins args into one prompt.
|
|
6
|
+
|
|
7
|
+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
8
|
+
ORACLE_SCRIPT="${ORACLE_COMPOSER_ORACLE_SCRIPT:-$ROOT_DIR/scripts/oracle-pro-safe.sh}"
|
|
9
|
+
CODEX_BIN="${ORACLE_COMPOSER_CODEX_BIN:-codex}"
|
|
10
|
+
|
|
11
|
+
prompt="$*"
|
|
12
|
+
[[ -n "$prompt" ]] || { echo "composer-oracle-router-safe: prompt required" >&2; exit 1; }
|
|
13
|
+
|
|
14
|
+
lower="$(printf '%s' "$prompt" | tr '[:upper:]' '[:lower:]')"
|
|
15
|
+
|
|
16
|
+
route="codex"
|
|
17
|
+
mode="standard"
|
|
18
|
+
|
|
19
|
+
case "$lower" in
|
|
20
|
+
*'[codex]'*) route="codex" ;;
|
|
21
|
+
*'[oracle:quick]'*) route="oracle"; mode="quick" ;;
|
|
22
|
+
*'[oracle:standard]'*) route="oracle"; mode="standard" ;;
|
|
23
|
+
*'[oracle:deep]'*|*'[oracle:plan]'*) route="oracle"; mode="deep" ;;
|
|
24
|
+
*'[oracle:review]'*) route="oracle"; mode="review" ;;
|
|
25
|
+
*'[oracle:debug]'*) route="oracle"; mode="debug" ;;
|
|
26
|
+
*'[oracle:research]'*) route="oracle"; mode="research" ;;
|
|
27
|
+
esac
|
|
28
|
+
|
|
29
|
+
if [[ "$route" != "codex" ]]; then
|
|
30
|
+
if [[ ${#prompt} -gt 2500 ]] || [[ "$lower" =~ (architecture|architectural|design|plan|planning|proposal|migration|refactor|roadmap|tradeoff|trade-off|spec|handoff|implementation[[:space:]]+plan) ]]; then mode="deep"; fi
|
|
31
|
+
if [[ "$lower" =~ (review|audit|regression|security|compatibility|api[[:space:]]+break|edge[[:space:]]+case|risk) ]]; then mode="review"; fi
|
|
32
|
+
if [[ "$lower" =~ (debug|root[ -]?cause|failing|failure|flaky|bug|stack[[:space:]]+trace|exception|crash|deadlock|race) ]]; then mode="debug"; fi
|
|
33
|
+
if [[ "$lower" =~ (research|compare[[:space:]]+options|survey|citations|latest|web) ]]; then mode="research"; fi
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
if [[ "$route" == "codex" ]]; then
|
|
37
|
+
if ! command -v "$CODEX_BIN" >/dev/null 2>&1; then
|
|
38
|
+
echo "[router] Codex requested but '$CODEX_BIN' not found; falling back to Oracle quick." >&2
|
|
39
|
+
exec "$ORACLE_SCRIPT" --mode quick -- "$prompt"
|
|
40
|
+
fi
|
|
41
|
+
echo "[router] route=codex sandbox=read-only" >&2
|
|
42
|
+
printf "%s\n" "$prompt" | "$CODEX_BIN" exec --ephemeral --sandbox read-only --ask-for-approval never -
|
|
43
|
+
exit $?
|
|
44
|
+
else
|
|
45
|
+
echo "[router] route=oracle mode=$mode" >&2
|
|
46
|
+
exec "$ORACLE_SCRIPT" --mode "$mode" -- "$prompt"
|
|
47
|
+
fi
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
|
|
6
|
+
const stateDir = process.env.COMPOSER_STATE_DIR?.trim()
|
|
7
|
+
? path.resolve(process.env.COMPOSER_STATE_DIR)
|
|
8
|
+
: path.join(os.homedir(), ".composer", "state");
|
|
9
|
+
const filePath = path.join(stateDir, "active-runs.json");
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
if (!fs.existsSync(filePath)) process.exit(0);
|
|
13
|
+
const runs = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
14
|
+
if (!Array.isArray(runs) || runs.length === 0) process.exit(0);
|
|
15
|
+
|
|
16
|
+
const now = Date.now();
|
|
17
|
+
const active = runs
|
|
18
|
+
.map((run) => ({
|
|
19
|
+
tool: typeof run.tool === "string" ? run.tool : "",
|
|
20
|
+
providerLabel: typeof run.providerLabel === "string" ? run.providerLabel : undefined,
|
|
21
|
+
providerRole: typeof run.providerRole === "string" ? run.providerRole : undefined,
|
|
22
|
+
startedAtMs: Date.parse(run.startedAt),
|
|
23
|
+
}))
|
|
24
|
+
.filter((run) => run.tool && Number.isFinite(run.startedAtMs))
|
|
25
|
+
.sort((a, b) => a.startedAtMs - b.startedAtMs)[0];
|
|
26
|
+
|
|
27
|
+
if (!active) process.exit(0);
|
|
28
|
+
const tool = active.tool.replace(/^composer_/, "");
|
|
29
|
+
const provider = active.providerLabel ?? active.providerRole;
|
|
30
|
+
const elapsed = formatElapsed(now - active.startedAtMs);
|
|
31
|
+
process.stdout.write(`⚡composer: ${tool}${provider ? `(${provider})` : ""} ${elapsed}\n`);
|
|
32
|
+
} catch {
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function formatElapsed(elapsedMs) {
|
|
37
|
+
const seconds = Math.max(0, Math.floor(elapsedMs / 1000));
|
|
38
|
+
if (seconds < 60) return `${seconds}s`;
|
|
39
|
+
return `${Math.floor(seconds / 60)}m`;
|
|
40
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
usage() {
|
|
5
|
+
cat <<'USAGE'
|
|
6
|
+
Usage:
|
|
7
|
+
scripts/oracle-codex-handoff-safe.sh [--mode deep|review|debug|standard] [--exec] -- "feature/request"
|
|
8
|
+
|
|
9
|
+
Creates a ChatGPT Pro/Oracle plan under .composer/handoffs/ and optionally sends it to Codex.
|
|
10
|
+
USAGE
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
MODE="deep"
|
|
14
|
+
EXECUTE=0
|
|
15
|
+
PROMPT=""
|
|
16
|
+
while [[ $# -gt 0 ]]; do
|
|
17
|
+
case "$1" in
|
|
18
|
+
--mode) MODE="${2:-}"; shift 2 ;;
|
|
19
|
+
--mode=*) MODE="${1#*=}"; shift ;;
|
|
20
|
+
--exec) EXECUTE=1; shift ;;
|
|
21
|
+
-h|--help) usage; exit 0 ;;
|
|
22
|
+
--) shift; PROMPT="$*"; break ;;
|
|
23
|
+
*) if [[ -z "$PROMPT" ]]; then PROMPT="$1"; else PROMPT="$PROMPT $1"; fi; shift ;;
|
|
24
|
+
esac
|
|
25
|
+
done
|
|
26
|
+
[[ -n "$PROMPT" ]] || { usage >&2; exit 1; }
|
|
27
|
+
|
|
28
|
+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
29
|
+
ORACLE_SCRIPT="$ROOT_DIR/scripts/oracle-pro-safe.sh"
|
|
30
|
+
mkdir -p .composer/handoffs .composer/results
|
|
31
|
+
slug="$(date +%Y%m%d-%H%M%S)-oracle-handoff"
|
|
32
|
+
plan_path=".composer/handoffs/$slug.md"
|
|
33
|
+
|
|
34
|
+
handoff_prompt="Create a compact Codex-ready implementation handoff for the following request. Include objective, constraints, likely files, implementation steps, tests, risks, and acceptance criteria. Do not include long code blocks unless essential. Request: $PROMPT"
|
|
35
|
+
|
|
36
|
+
answer_path="$($ORACLE_SCRIPT --mode "$MODE" --slug "$slug" -- "$handoff_prompt" | tail -1)"
|
|
37
|
+
[[ -f "$answer_path" ]] || { echo "Oracle did not produce an answer path" >&2; exit 1; }
|
|
38
|
+
cp "$answer_path" "$plan_path"
|
|
39
|
+
echo "$plan_path"
|
|
40
|
+
|
|
41
|
+
if [[ "$EXECUTE" -eq 1 ]]; then
|
|
42
|
+
result_path=".composer/results/$slug.codex-result.md"
|
|
43
|
+
{
|
|
44
|
+
echo "Implement the following plan in the current repository. Keep the diff focused. Run relevant tests. Return summary, changed files, tests run, and unresolved risks."
|
|
45
|
+
echo
|
|
46
|
+
cat "$plan_path"
|
|
47
|
+
} | codex exec --sandbox workspace-write --ask-for-approval on-request --output-last-message "$result_path" -
|
|
48
|
+
echo "$result_path"
|
|
49
|
+
fi
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# oracle-plan-mcp.sh — thin MCP-facing wrapper around oracle-pro-safe.sh.
|
|
3
|
+
#
|
|
4
|
+
# Why: CLIProvider returns a role's STDOUT to the orchestrator. oracle-pro-safe.sh
|
|
5
|
+
# prints the answer FILE PATH on its last stdout line (a contract relied on by
|
|
6
|
+
# oracle-codex-handoff-safe.sh), and oracle's own render/progress is noisy. This
|
|
7
|
+
# wrapper runs oracle-pro-safe.sh, recovers that path, and emits ONLY the final
|
|
8
|
+
# answer file CONTENT on stdout, so composer_oracle_plan returns clean answer text.
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
MODE="auto"
|
|
12
|
+
ARGS=()
|
|
13
|
+
while [[ $# -gt 0 ]]; do
|
|
14
|
+
case "$1" in
|
|
15
|
+
--mode) MODE="${2:?missing --mode value}"; shift 2 ;;
|
|
16
|
+
--mode=*) MODE="${1#*=}"; shift ;;
|
|
17
|
+
--) shift; ARGS+=("$@"); break ;;
|
|
18
|
+
*) ARGS+=("$1"); shift ;;
|
|
19
|
+
esac
|
|
20
|
+
done
|
|
21
|
+
|
|
22
|
+
PROMPT="${ARGS[*]:-}"
|
|
23
|
+
if [[ -z "$PROMPT" && ! -t 0 ]]; then
|
|
24
|
+
PROMPT="$(cat)"
|
|
25
|
+
fi
|
|
26
|
+
if [[ -z "$PROMPT" ]]; then
|
|
27
|
+
echo "oracle-plan-mcp: prompt required" >&2
|
|
28
|
+
exit 2
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
32
|
+
ORACLE_SCRIPT="$ROOT_DIR/scripts/oracle-pro-safe.sh"
|
|
33
|
+
|
|
34
|
+
tmp="$(mktemp)"
|
|
35
|
+
trap 'rm -f "$tmp"' EXIT
|
|
36
|
+
|
|
37
|
+
# Capture oracle-pro-safe stdout (answer render + final path line) into tmp.
|
|
38
|
+
# Its stderr (logs/progress) is inherited -> our stderr -> not returned to MCP.
|
|
39
|
+
set +e
|
|
40
|
+
bash "$ORACLE_SCRIPT" --mode "$MODE" -- "$PROMPT" > "$tmp"
|
|
41
|
+
status=$?
|
|
42
|
+
set -e
|
|
43
|
+
|
|
44
|
+
if (( status != 0 )); then
|
|
45
|
+
echo "oracle-plan-mcp: oracle-pro-safe.sh failed (exit $status); captured output:" >&2
|
|
46
|
+
cat "$tmp" >&2 || true
|
|
47
|
+
exit "$status"
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
answer_path="$(tail -n 1 "$tmp" | tr -d '\r')"
|
|
51
|
+
if [[ -z "$answer_path" || ! -s "$answer_path" ]]; then
|
|
52
|
+
echo "oracle-plan-mcp: oracle finished but no answer file at '$answer_path'; captured output:" >&2
|
|
53
|
+
cat "$tmp" >&2 || true
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# Write a stable sidecar so async callers (composer_oracle_job_start) can
|
|
58
|
+
# recover the full-answer path even though only bounded text is returned.
|
|
59
|
+
meta_dir="$(dirname "$answer_path")"
|
|
60
|
+
slug="$(basename "$answer_path" .md)"
|
|
61
|
+
if [[ -d "$meta_dir" ]] && command -v node >/dev/null 2>&1; then
|
|
62
|
+
node -e 'const fs=require("fs");fs.writeFileSync(process.argv[1],JSON.stringify({answerPath:process.argv[2],oracleSlug:process.argv[3],mode:process.argv[4]})+"\n")' \
|
|
63
|
+
"$meta_dir/.last-plan-meta.json" "$answer_path" "$slug" "$MODE" 2>/dev/null || true
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
cat "$answer_path"
|