claude-dev-env 2.35.0 → 4.0.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/.agents/skills/_shared/advisor/scripts/README.md +1 -1
- package/.agents/skills/autoconverge/SKILL.md +19 -15
- package/.agents/skills/autoconverge/reference/gotchas.md +3 -3
- package/.agents/skills/autoconverge/reference/multi-pr.md +6 -2
- package/.agents/skills/autoconverge/workflow/converge.contract.test.mjs +11 -0
- package/.agents/skills/autoconverge/workflow/converge.mjs +26 -33
- package/.agents/skills/autoconverge/workflow/converge.run-input.test.mjs +26 -2
- package/.agents/skills/autoconverge/workflow/converge_multi.mjs +12 -28
- package/.agents/skills/autoconverge/workflow/converge_multi.run-input.test.mjs +16 -0
- package/.agents/skills/team-advisor/SKILL.md +11 -11
- package/_shared/advisor/advisor-protocol.md +51 -51
- package/_shared/advisor/reference/advisor-block.md +9 -9
- package/_shared/advisor/reference/astra-rung.md +39 -0
- package/_shared/advisor/reference/identity.md +4 -4
- package/_shared/advisor/reference/lifecycle.md +6 -6
- package/_shared/advisor/reference/spawn-walk-log.md +9 -9
- package/_shared/advisor/reference/third-party-bind.md +11 -11
- package/_shared/advisor/reference/warm-up.md +13 -13
- package/_shared/advisor/scripts/codex_astra_advisor.py +308 -0
- package/_shared/advisor/scripts/codex_astra_preflight.py +115 -0
- package/_shared/advisor/scripts/codex_astra_reply.py +159 -0
- package/_shared/advisor/scripts/config/advisor_scripts_constants/advisor_route_constants.py +3 -3
- package/_shared/advisor/scripts/config/advisor_scripts_constants/astra_advisor_constants.py +38 -0
- package/_shared/advisor/scripts/model_tier_run_validator.py +17 -18
- package/_shared/advisor/scripts/tests/test_codex_astra_advisor.py +271 -0
- package/_shared/advisor/scripts/tests/test_codex_astra_preflight.py +24 -0
- package/_shared/advisor/scripts/tests/test_codex_astra_reply.py +42 -0
- package/_shared/advisor/scripts/tests/test_model_tier_run_validator.py +55 -30
- package/_shared/advisor/scripts/tests/test_tier_model_ids.py +14 -4
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +14 -0
- package/_shared/pr-loop/scripts/terminology_sweep.py +138 -50
- package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +13 -1
- package/bin/cde.mjs +175 -0
- package/bin/cde.test.mjs +222 -0
- package/bin/install-constants.mjs +4 -0
- package/bin/install.cursor-rules.test.mjs +233 -2
- package/bin/install.mjs +49 -3
- package/bin/pstack-model-preferences.codex.json +23 -0
- package/bin/select-pstack-models.test.mjs +378 -0
- package/docs/references/team-advisor-skill.md +3 -3
- package/hooks/hooks_constants/tool_names.py +20 -0
- package/hooks/validators/README.md +35 -1
- package/hooks/validators/fast_save_validators.py +63 -89
- package/hooks/validators/run_all_validators.py +16 -8
- package/hooks/validators/test_fast_save_validators_policy_lint.py +25 -0
- package/hooks/validators/test_run_all_validators_policy_lint.py +52 -0
- package/package.json +3 -2
- package/rules/pstack-models.md +119 -0
- package/scripts/cde_lint.py +258 -0
- package/scripts/check.ps1 +18 -6
- package/scripts/policy_lint/__init__.py +41 -0
- package/scripts/policy_lint/adapter_configuration.py +91 -0
- package/scripts/policy_lint/adapter_detectors.py +368 -0
- package/scripts/policy_lint/adapter_pairing.py +145 -0
- package/scripts/policy_lint/adapter_support.py +97 -0
- package/scripts/policy_lint/adapters.py +376 -0
- package/scripts/policy_lint/config/__init__.py +1 -0
- package/scripts/policy_lint/config/constants.py +77 -0
- package/scripts/policy_lint/engine.py +224 -0
- package/scripts/policy_lint/model.py +388 -0
- package/scripts/policy_lint/registry.py +171 -0
- package/scripts/policy_lint/render.py +91 -0
- package/scripts/policy_lint/selection.py +372 -0
- package/scripts/policy_lint/selection_git.py +147 -0
- package/scripts/repository_checks/__init__.py +1 -0
- package/scripts/repository_checks/claude_md.py +108 -0
- package/scripts/repository_checks/config/__init__.py +1 -0
- package/scripts/repository_checks/config/constants.py +150 -0
- package/scripts/repository_checks/env_var_documentation.py +243 -0
- package/scripts/repository_checks/hook_modules.py +34 -0
- package/scripts/repository_checks/models.py +37 -0
- package/scripts/repository_checks/package_inventory.py +118 -0
- package/scripts/repository_checks/pytest_testpaths.py +84 -0
- package/scripts/repository_checks/reporting.py +39 -0
- package/scripts/repository_checks/runner.py +93 -0
- package/scripts/repository_checks/tracked_secrets.py +147 -0
- package/scripts/repository_checks/tracked_tree.py +28 -0
- package/scripts/repository_policy.py +120 -0
- package/scripts/select_pstack_models.mjs +304 -0
- package/scripts/tests/repository_policy_test_support.py +89 -0
- package/scripts/tests/test_cde_lint.py +398 -0
- package/scripts/tests/test_claude_md.py +68 -0
- package/scripts/tests/test_env_var_documentation.py +133 -0
- package/scripts/tests/test_hook_modules.py +17 -0
- package/scripts/tests/test_models.py +26 -0
- package/scripts/tests/test_package_inventory.py +96 -0
- package/scripts/tests/test_policy_lint_rules_engine.py +381 -0
- package/scripts/tests/test_policy_lint_rules_registry.py +369 -0
- package/scripts/tests/test_policy_lint_selection.py +373 -0
- package/scripts/tests/test_pytest_testpaths.py +66 -0
- package/scripts/tests/test_reporting.py +54 -0
- package/scripts/tests/test_repository_policy.py +71 -0
- package/scripts/tests/test_runner.py +59 -0
- package/scripts/tests/test_tracked_secrets.py +175 -0
- package/scripts/tests/test_tracked_tree.py +28 -0
- package/_shared/advisor/reference/sol-rung.md +0 -39
- package/_shared/advisor/scripts/codex_sol_advisor.py +0 -581
- package/_shared/advisor/scripts/config/advisor_scripts_constants/sol_advisor_constants.py +0 -38
- package/_shared/advisor/scripts/tests/test_codex_sol_advisor.py +0 -740
|
@@ -59,8 +59,10 @@ python "$HOME/.claude/skills/_shared/pr-loop/scripts/select_converge_pacer.py" \
|
|
|
59
59
|
[`../_shared/pr-loop/portable-driver.md`](../_shared/pr-loop/portable-driver.md).
|
|
60
60
|
**Do not abort** because the Workflow tool is missing.
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
`
|
|
62
|
+
Set the GitHub transport directive before any GitHub step. Use `transport: "cloud"` in a
|
|
63
|
+
Cloud session. Use `transport: "local"` in a local session. Cloud uses the
|
|
64
|
+
connected GitHub MCP tools and never starts a local GitHub CLI authentication
|
|
65
|
+
flow.
|
|
64
66
|
|
|
65
67
|
## Review-lens boundary
|
|
66
68
|
|
|
@@ -68,18 +70,19 @@ The code-review lens boundary (workflow agent versus the built-in `/code-review`
|
|
|
68
70
|
command) is defined on the **Code-review lens** bullet in
|
|
69
71
|
[`reference/convergence.md`](reference/convergence.md).
|
|
70
72
|
|
|
71
|
-
##
|
|
73
|
+
## Select the GitHub transport directive before any GitHub step
|
|
72
74
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
`pr-loop-cloud-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
In a Cloud session, set `transport: "cloud"` and load the GitHub MCP schemas
|
|
76
|
+
before the first GitHub tool call. Do not run any local GitHub CLI
|
|
77
|
+
authentication, account-switch, or token command. Use the operation in
|
|
78
|
+
[`cloud-pr-loop-compatibility.md`](../../../docs/references/cloud-pr-loop-compatibility.md)
|
|
79
|
+
for each GitHub read or write. Use the Cloud session's credentialed push path
|
|
80
|
+
for local commits. If that path rejects a push, report the exact error instead
|
|
81
|
+
of trying to log in through the local CLI.
|
|
82
|
+
|
|
83
|
+
In a local session, set `transport: "local"` and use the authenticated local
|
|
84
|
+
GitHub CLI. The workflow defaults to this value when older callers omit the
|
|
85
|
+
field.
|
|
83
86
|
|
|
84
87
|
## Pre-flight (main session)
|
|
85
88
|
|
|
@@ -161,7 +164,7 @@ orchestrating session's own steps, and the script's agent-prompt text carries
|
|
|
161
164
|
```
|
|
162
165
|
Workflow({
|
|
163
166
|
scriptPath: "<this skill dir>/workflow/converge.mjs",
|
|
164
|
-
args: { owner: "<O>", repo: "<R>", prNumber: <N>, bugbotDisabled: false, copilotDisabled: false, homeDirectory: "<HOME>" }
|
|
167
|
+
args: { owner: "<O>", repo: "<R>", prNumber: <N>, bugbotDisabled: false, copilotDisabled: false, homeDirectory: "<HOME>", transport: "<cloud|local>" }
|
|
165
168
|
})
|
|
166
169
|
```
|
|
167
170
|
|
|
@@ -173,7 +176,8 @@ the absolute path to the directory that holds `.claude` (resolve it once from
|
|
|
173
176
|
runs in a sandbox with no access to environment variables, so the run reads the
|
|
174
177
|
home directory from this arg to build the path to the codex-review scripts the
|
|
175
178
|
Codex gate calls; leave it out and the Codex gate cannot find those scripts. Set
|
|
176
|
-
`
|
|
179
|
+
`transport: "cloud"` for Cloud and `transport: "local"` for local execution.
|
|
180
|
+
Set `bugbotDisabled: true` only when the user has opted Cursor Bugbot out for the
|
|
177
181
|
run; otherwise the workflow detects an opt-out or an unreachable Bugbot on its
|
|
178
182
|
own. Set `copilotDisabled: true` when the step 5 quota pre-check exits non-zero,
|
|
179
183
|
and `false` when it exits 0; on `true` the workflow skips the Copilot gate with
|
|
@@ -46,9 +46,9 @@ fails in a new way.
|
|
|
46
46
|
not `~/.claude/...`; a tilde resolves to the wrong home and gives a
|
|
47
47
|
file-not-found error that looks like a script failure.
|
|
48
48
|
|
|
49
|
-
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
- **Local identity drift across accounts.** A local run that touches more than
|
|
50
|
+
one GitHub account must use the selected local account. Cloud runs use the
|
|
51
|
+
connected GitHub MCP identity and never use local CLI identity commands.
|
|
52
52
|
|
|
53
53
|
- **Commit or push fails after a repair.** Read the hook or command output,
|
|
54
54
|
repair the named issue, and record the rerun. Apply the
|
|
@@ -73,6 +73,7 @@ Workflow({
|
|
|
73
73
|
args: {
|
|
74
74
|
convergeScriptPath: "<this skill dir>/workflow/converge.mjs",
|
|
75
75
|
homeDirectory: "<HOME>",
|
|
76
|
+
transport: "<cloud|local>",
|
|
76
77
|
prs: [
|
|
77
78
|
{ owner: "<O>", repo: "<R>", prNumber: <N1>, repoPath: "<abs worktree 1>", bugbotDisabled: false, copilotDisabled: false },
|
|
78
79
|
{ owner: "<O>", repo: "<R>", prNumber: <N2>, repoPath: "<abs worktree 2>", bugbotDisabled: false, copilotDisabled: false }
|
|
@@ -87,8 +88,11 @@ checked out in. `homeDirectory` is the absolute path to the directory that holds
|
|
|
87
88
|
`.claude` (resolve it once from `$HOME`, or `$env:USERPROFILE` on Windows, with
|
|
88
89
|
forward slashes); the fan-out forwards it to every child run, which needs it to
|
|
89
90
|
build the codex-review scripts path because the workflow sandbox has no access to
|
|
90
|
-
environment variables.
|
|
91
|
-
|
|
91
|
+
environment variables. Set `transport: "cloud"` in a Cloud session and
|
|
92
|
+
`transport: "local"` in a local session. Cloud uses the connected GitHub MCP
|
|
93
|
+
tools and skips local CLI authentication. The workflow runs in the background
|
|
94
|
+
and notifies the session on completion; watch live progress with `/workflows`,
|
|
95
|
+
where each PR's child run
|
|
92
96
|
appears under its own group.
|
|
93
97
|
|
|
94
98
|
The workflow returns
|
|
@@ -32,6 +32,17 @@ test('review tasks use code-quality-agent and keep the working tree read-only',
|
|
|
32
32
|
assert.match(reviewTaskSource, /Make no edit to the tree under verification/)
|
|
33
33
|
})
|
|
34
34
|
|
|
35
|
+
test('workflow agents receive the selected GitHub transport before role instructions', () => {
|
|
36
|
+
assert.match(
|
|
37
|
+
workflowSource,
|
|
38
|
+
/HEADLESS_EDIT_PREAMBLE\}\$\{githubTransportDirective\(activeGithubTransport\)\}\$\{worktreeDirective/,
|
|
39
|
+
)
|
|
40
|
+
assert.match(
|
|
41
|
+
workflowSource,
|
|
42
|
+
/HEADLESS_READONLY_PREAMBLE\}\$\{githubTransportDirective\(activeGithubTransport\)\}\$\{worktreeDirective/,
|
|
43
|
+
)
|
|
44
|
+
})
|
|
45
|
+
|
|
35
46
|
test('review result parser accepts one standalone terminal disposition only', () => {
|
|
36
47
|
const parseReviewResult = loadReviewResultParser()
|
|
37
48
|
|
|
@@ -91,6 +91,7 @@ const HEADLESS_READONLY_PREAMBLE = HEADLESS_EDIT_PREAMBLE.replace(
|
|
|
91
91
|
)
|
|
92
92
|
|
|
93
93
|
let activeRepoPath = null
|
|
94
|
+
let activeGithubTransport = 'local'
|
|
94
95
|
|
|
95
96
|
/**
|
|
96
97
|
* Build the per-agent worktree directive for a path-scoped run.
|
|
@@ -111,33 +112,11 @@ const worktreeDirective = (repoPath) =>
|
|
|
111
112
|
? `WORKTREE — this PR is checked out at ${repoPath}. Unless a step explicitly names a different repository directory (for example an environment-hardening repo checkout, which you cd into exactly as that step directs), run every git, gh, diff, edit, commit, push, and test command for this PR in that worktree: cd "${repoPath}" before any such command, and resolve repository roots from there.\n\n`
|
|
112
113
|
: ''
|
|
113
114
|
|
|
114
|
-
/**
|
|
115
|
-
* Spawn a workflow agent that edits code, with the full edit preamble prepended
|
|
116
|
-
* to its prompt. An edit agent may run rm during cleanup, so it inherits the
|
|
117
|
-
* rm-shape rules alongside the no-confirmation-prompt guidance. On a path-scoped
|
|
118
|
-
* run the worktree directive is prepended too, so the agent runs in the PR's own
|
|
119
|
-
* worktree (activeRepoPath); on a single-PR run that directive is empty and the
|
|
120
|
-
* agent keeps its own working directory. A read-only agent (a review, verify, or
|
|
121
|
-
* utility spawn) routes through convergeReadOnlyAgent for the trimmed preamble.
|
|
122
|
-
* @param {string} prompt the agent's role-specific instruction body
|
|
123
|
-
* @param {object} options the agent() options (label, phase, schema, agentType, model)
|
|
124
|
-
* @returns {Promise<*>} the agent() result
|
|
125
|
-
*/
|
|
126
115
|
const convergeAgent = (prompt, options) =>
|
|
127
|
-
agent(`${HEADLESS_EDIT_PREAMBLE}${worktreeDirective(activeRepoPath)}${prompt}`, options)
|
|
116
|
+
agent(`${HEADLESS_EDIT_PREAMBLE}${githubTransportDirective(activeGithubTransport)}${worktreeDirective(activeRepoPath)}${prompt}`, options)
|
|
128
117
|
|
|
129
|
-
/**
|
|
130
|
-
* Spawn a read-only workflow agent with the trimmed read-only preamble prepended
|
|
131
|
-
* to its prompt. A review, verify, or utility agent edits nothing and never runs
|
|
132
|
-
* rm, so it receives the read-only preamble that drops the rm-shape-rules bullet.
|
|
133
|
-
* The worktree directive is prepended on a path-scoped run exactly as for
|
|
134
|
-
* convergeAgent, so a read-only agent still runs in the PR's own worktree.
|
|
135
|
-
* @param {string} prompt the agent's role-specific instruction body
|
|
136
|
-
* @param {object} options the agent() options (label, phase, schema, agentType, model)
|
|
137
|
-
* @returns {Promise<*>} the agent() result
|
|
138
|
-
*/
|
|
139
118
|
const convergeReadOnlyAgent = (prompt, options) =>
|
|
140
|
-
agent(`${HEADLESS_READONLY_PREAMBLE}${worktreeDirective(activeRepoPath)}${prompt}`, options)
|
|
119
|
+
agent(`${HEADLESS_READONLY_PREAMBLE}${githubTransportDirective(activeGithubTransport)}${worktreeDirective(activeRepoPath)}${prompt}`, options)
|
|
141
120
|
|
|
142
121
|
/**
|
|
143
122
|
* Spawn a fresh git-utility Explore agent for a specific task. The one task,
|
|
@@ -1627,19 +1606,32 @@ function normalizeRunInput(rawArgs) {
|
|
|
1627
1606
|
}
|
|
1628
1607
|
}
|
|
1629
1608
|
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1609
|
+
const DEFAULT_GITHUB_TRANSPORT = 'local'
|
|
1610
|
+
const GITHUB_TRANSPORT_DIRECTIVES = {
|
|
1611
|
+
local:
|
|
1612
|
+
'LOCAL GITHUB TRANSPORT DIRECTIVE. Use the authenticated local GitHub CLI for GitHub operations. Report local authentication or permission failures directly.\n\n',
|
|
1613
|
+
cloud:
|
|
1614
|
+
'CLOUD GITHUB TRANSPORT DIRECTIVE. Use the connected GitHub MCP tools for every GitHub API read and write. Load the GitHub MCP schemas before the first MCP call and resolve the connected identity with mcp__github__get_me. Do not invoke a local GitHub CLI for authentication, account switching, token lookup, pull-request operations, review operations, or push setup. Replace local CLI steps in this prompt with the matching operation in docs/references/cloud-pr-loop-compatibility.md. For a local commit push, use only the credentialed push path supplied by the Cloud session. If no credentialed path is available, return a named blocker instead of attempting a login.\n\n',
|
|
1615
|
+
}
|
|
1616
|
+
const VALID_GITHUB_TRANSPORTS = new Set(Object.keys(GITHUB_TRANSPORT_DIRECTIVES))
|
|
1617
|
+
|
|
1618
|
+
function githubTransportDirective(transport) {
|
|
1619
|
+
return GITHUB_TRANSPORT_DIRECTIVES[transport] || GITHUB_TRANSPORT_DIRECTIVES[DEFAULT_GITHUB_TRANSPORT]
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1639
1622
|
function classifyRunInput(rawArgs) {
|
|
1640
1623
|
const candidate = normalizeRunInput(rawArgs)
|
|
1641
1624
|
const hasUsableCoordinates =
|
|
1642
1625
|
candidate != null && candidate.owner && candidate.repo && candidate.prNumber
|
|
1626
|
+
const hasValidTransport =
|
|
1627
|
+
candidate != null &&
|
|
1628
|
+
(candidate.transport === undefined || VALID_GITHUB_TRANSPORTS.has(candidate.transport))
|
|
1629
|
+
if (hasUsableCoordinates && !hasValidTransport) {
|
|
1630
|
+
return {
|
|
1631
|
+
input: null,
|
|
1632
|
+
blocker: 'invalid run transport: expected "local" or "cloud"',
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1643
1635
|
if (hasUsableCoordinates) return { input: candidate, blocker: null }
|
|
1644
1636
|
return {
|
|
1645
1637
|
input: null,
|
|
@@ -1654,6 +1646,7 @@ if (runInput.blocker) {
|
|
|
1654
1646
|
}
|
|
1655
1647
|
const input = runInput.input
|
|
1656
1648
|
activeRepoPath = typeof input.repoPath === 'string' && input.repoPath ? input.repoPath : null
|
|
1649
|
+
activeGithubTransport = input.transport === undefined ? DEFAULT_GITHUB_TRANSPORT : input.transport
|
|
1657
1650
|
const prCoordinates = `owner=${input.owner} repo=${input.repo} PR #${input.prNumber} (https://github.com/${input.owner}/${input.repo}/pull/${input.prNumber})`
|
|
1658
1651
|
|
|
1659
1652
|
/**
|
|
@@ -17,10 +17,10 @@ function sourceSliceBetween(startNeedle, endNeedle) {
|
|
|
17
17
|
|
|
18
18
|
const productionModule = new Function(
|
|
19
19
|
`${sourceSliceBetween('function normalizeRunInput(', '\nconst runInput =')}\n` +
|
|
20
|
-
'return { normalizeRunInput, classifyRunInput };',
|
|
20
|
+
'return { normalizeRunInput, classifyRunInput, githubTransportDirective };',
|
|
21
21
|
)();
|
|
22
22
|
|
|
23
|
-
const { normalizeRunInput, classifyRunInput } = productionModule;
|
|
23
|
+
const { normalizeRunInput, classifyRunInput, githubTransportDirective } = productionModule;
|
|
24
24
|
|
|
25
25
|
const VALID_COORDINATES = { owner: 'jl-cmd', repo: 'claude-dev-env', prNumber: 543 };
|
|
26
26
|
|
|
@@ -46,6 +46,19 @@ test('classifyRunInput accepts coordinates carrying owner, repo, and prNumber',
|
|
|
46
46
|
assert.equal(classified.blocker, null);
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
+
test('classifyRunInput accepts the cloud transport without changing the input shape', () => {
|
|
50
|
+
const cloudInput = { ...VALID_COORDINATES, transport: 'cloud' };
|
|
51
|
+
const classified = classifyRunInput(cloudInput);
|
|
52
|
+
assert.deepEqual(classified.input, cloudInput);
|
|
53
|
+
assert.equal(classified.blocker, null);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('classifyRunInput blocks an unknown transport before any GitHub work starts', () => {
|
|
57
|
+
const classified = classifyRunInput({ ...VALID_COORDINATES, transport: 'proxy' });
|
|
58
|
+
assert.equal(classified.input, null);
|
|
59
|
+
assert.match(classified.blocker, /transport/i);
|
|
60
|
+
});
|
|
61
|
+
|
|
49
62
|
test('classifyRunInput blocks a failed parse with a structured blocker and no input', () => {
|
|
50
63
|
const classified = classifyRunInput('not json at all');
|
|
51
64
|
assert.equal(classified.input, null);
|
|
@@ -90,3 +103,14 @@ test('classifyRunInput leaves copilotDisabled undefined when the input omits it'
|
|
|
90
103
|
const classified = classifyRunInput(VALID_COORDINATES);
|
|
91
104
|
assert.equal(classified.input.copilotDisabled, undefined);
|
|
92
105
|
});
|
|
106
|
+
|
|
107
|
+
test('the cloud transport directive selects MCP and contains no local CLI auth command', () => {
|
|
108
|
+
const cloudDirective = githubTransportDirective('cloud');
|
|
109
|
+
assert.match(cloudDirective, /mcp__github__/);
|
|
110
|
+
assert.match(cloudDirective, /credentialed push path/);
|
|
111
|
+
assert.doesNotMatch(cloudDirective, /gh auth/);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test('the local transport directive keeps the local CLI path', () => {
|
|
115
|
+
assert.match(githubTransportDirective('local'), /authenticated local GitHub CLI/);
|
|
116
|
+
});
|
|
@@ -57,18 +57,9 @@ function isUsablePrEntry(prEntry) {
|
|
|
57
57
|
)
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
* A fan-out run needs the absolute converge.mjs script path and a non-empty list
|
|
64
|
-
* of PR entries that each carry owner, repo, prNumber, and the absolute worktree
|
|
65
|
-
* path the PR is checked out in. A payload that fails to parse, a non-string
|
|
66
|
-
* convergeScriptPath, a missing or empty prs list, or any entry missing a
|
|
67
|
-
* coordinate yields a blocker the top-level run reports as
|
|
68
|
-
* {converged:false, blocker} rather than throwing on a missing field.
|
|
69
|
-
* @param {string|object} rawArgs the workflow args global (JSON string or object)
|
|
70
|
-
* @returns {{input: object|null, blocker: string|null}} usable coordinates or a blocker
|
|
71
|
-
*/
|
|
60
|
+
const DEFAULT_GITHUB_TRANSPORT = 'local'
|
|
61
|
+
const VALID_GITHUB_TRANSPORTS = new Set(['local', 'cloud'])
|
|
62
|
+
|
|
72
63
|
function classifyMultiInput(rawArgs) {
|
|
73
64
|
const candidate = normalizeMultiInput(rawArgs)
|
|
74
65
|
if (candidate == null) {
|
|
@@ -84,6 +75,12 @@ function classifyMultiInput(rawArgs) {
|
|
|
84
75
|
'invalid run coordinates: convergeScriptPath (absolute path to converge.mjs) is required',
|
|
85
76
|
}
|
|
86
77
|
}
|
|
78
|
+
if (candidate.transport !== undefined && !VALID_GITHUB_TRANSPORTS.has(candidate.transport)) {
|
|
79
|
+
return {
|
|
80
|
+
input: null,
|
|
81
|
+
blocker: 'invalid run transport: expected "local" or "cloud"',
|
|
82
|
+
}
|
|
83
|
+
}
|
|
87
84
|
if (!Array.isArray(candidate.prs) || candidate.prs.length === 0) {
|
|
88
85
|
return {
|
|
89
86
|
input: null,
|
|
@@ -102,21 +99,7 @@ function classifyMultiInput(rawArgs) {
|
|
|
102
99
|
return { input: candidate, blocker: null }
|
|
103
100
|
}
|
|
104
101
|
|
|
105
|
-
|
|
106
|
-
* Build the converge.mjs child-run args for one validated PR entry.
|
|
107
|
-
*
|
|
108
|
-
* Every per-run opt-out the child converge.mjs reads is forwarded here so the
|
|
109
|
-
* fan-out honors it: bugbotDisabled skips the Bugbot phase, and copilotDisabled
|
|
110
|
-
* short-circuits the Copilot quota gate when the account is out of premium
|
|
111
|
-
* requests. An entry that omits an opt-out defaults it to false so the child
|
|
112
|
-
* runs that phase. homeDirectory is a run-level value forwarded to every child
|
|
113
|
-
* so the child can build its codex-review scripts path: the workflow sandbox
|
|
114
|
-
* exposes no process global, so the child reads home from its args, not env.
|
|
115
|
-
* @param {object} prEntry one validated element of the args.prs array
|
|
116
|
-
* @param {string} homeDirectory the run-level home directory for every child
|
|
117
|
-
* @returns {object} the args object passed to the converge.mjs child run
|
|
118
|
-
*/
|
|
119
|
-
function childRunInput(prEntry, homeDirectory) {
|
|
102
|
+
function childRunInput(prEntry, homeDirectory, transport = DEFAULT_GITHUB_TRANSPORT) {
|
|
120
103
|
return {
|
|
121
104
|
owner: prEntry.owner,
|
|
122
105
|
repo: prEntry.repo,
|
|
@@ -125,6 +108,7 @@ function childRunInput(prEntry, homeDirectory) {
|
|
|
125
108
|
bugbotDisabled: Boolean(prEntry.bugbotDisabled),
|
|
126
109
|
copilotDisabled: Boolean(prEntry.copilotDisabled),
|
|
127
110
|
homeDirectory,
|
|
111
|
+
transport,
|
|
128
112
|
}
|
|
129
113
|
}
|
|
130
114
|
|
|
@@ -141,7 +125,7 @@ const childResults = await parallel(
|
|
|
141
125
|
input.prs.map((eachPr) => async () => {
|
|
142
126
|
const childOutcome = await workflow(
|
|
143
127
|
{ scriptPath: input.convergeScriptPath },
|
|
144
|
-
childRunInput(eachPr, input.homeDirectory),
|
|
128
|
+
childRunInput(eachPr, input.homeDirectory, input.transport),
|
|
145
129
|
)
|
|
146
130
|
return {
|
|
147
131
|
owner: eachPr.owner,
|
|
@@ -68,6 +68,18 @@ test('valid coordinates classify with no blocker and keep every PR entry', () =>
|
|
|
68
68
|
assert.equal(classified.input.prs.length, 2);
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
+
test('a cloud transport classifies with no blocker', () => {
|
|
72
|
+
const classified = classifyMultiInput({ ...validArgs(), transport: 'cloud' });
|
|
73
|
+
assert.equal(classified.blocker, null);
|
|
74
|
+
assert.equal(classified.input.transport, 'cloud');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('an unknown transport is blocked before child workflows start', () => {
|
|
78
|
+
const classified = classifyMultiInput({ ...validArgs(), transport: 'proxy' });
|
|
79
|
+
assert.equal(classified.input, null);
|
|
80
|
+
assert.match(classified.blocker, /transport/i);
|
|
81
|
+
});
|
|
82
|
+
|
|
71
83
|
test('a missing convergeScriptPath is blocked', () => {
|
|
72
84
|
const classified = classifyMultiInput({ prs: [validEntry(101)] });
|
|
73
85
|
assert.equal(classified.input, null);
|
|
@@ -138,6 +150,10 @@ test('childRunInput defaults bugbotDisabled to false when the entry omits it', (
|
|
|
138
150
|
assert.equal(childRunInput(validEntry(101)).bugbotDisabled, false);
|
|
139
151
|
});
|
|
140
152
|
|
|
153
|
+
test('childRunInput forwards the selected cloud transport', () => {
|
|
154
|
+
assert.equal(childRunInput(validEntry(101), '/home/dev', 'cloud').transport, 'cloud');
|
|
155
|
+
});
|
|
156
|
+
|
|
141
157
|
test('childRunInput forwards the run-level home directory to the child run', () => {
|
|
142
158
|
const childArgs = childRunInput(validEntry(101), '/home/dev');
|
|
143
159
|
assert.equal(childArgs.homeDirectory, '/home/dev');
|
|
@@ -16,23 +16,23 @@ One warm advisor at the strongest tier this session can reach. This session is t
|
|
|
16
16
|
|
|
17
17
|
| Doc | Holds |
|
|
18
18
|
|---|---|
|
|
19
|
-
| [`docs/references/advisor-tool.md`](../../docs/references/advisor-tool.md) | **Consult cadence and weight
|
|
20
|
-
| [`~/.claude/_shared/advisor/advisor-protocol.md`](../../_shared/advisor/advisor-protocol.md) | **Bind and lifecycle
|
|
21
|
-
| [`agents/session-advisor.md`](../../agents/session-advisor.md) | **Reply contract
|
|
22
|
-
| [`reference/advisor-docs-review.md`](reference/advisor-docs-review.md) | Anthropic advisor-tool source facts: measured effects, Sonnet steering, cost levers, failure modes. Background
|
|
19
|
+
| [`docs/references/advisor-tool.md`](../../docs/references/advisor-tool.md) | **Consult cadence and weight.** When to call, the hard rule before first write, and how to treat advice. Read this for every consult. |
|
|
20
|
+
| [`~/.claude/_shared/advisor/advisor-protocol.md`](../../_shared/advisor/advisor-protocol.md) | **Bind and lifecycle.** Session identity, host detect, model floor, warm-up, CLI fallback. Its read map routes each moment to a `reference/` detail file. |
|
|
21
|
+
| [`agents/session-advisor.md`](../../agents/session-advisor.md) | **Reply contract.** ENDORSE / CORRECTION / PLAN / STOP. SendMessage only. |
|
|
22
|
+
| [`reference/advisor-docs-review.md`](reference/advisor-docs-review.md) | Anthropic advisor-tool source facts: measured effects, Sonnet steering, cost levers, failure modes. Background. Read it when tuning the bind, not on every consult. |
|
|
23
23
|
|
|
24
24
|
## Bind
|
|
25
25
|
|
|
26
26
|
1. Name the session identity first (protocol **Host profiles**), then walk the model floor.
|
|
27
|
-
2. Claude: Fable first in-session at `ADVISOR_EFFORT` (default low). When Fable is out of usage, bind
|
|
28
|
-
3. Name: `team-advisor-agent` on Claude (Agent spawn of `session-advisor`); a native
|
|
27
|
+
2. Claude: Fable first in-session at `ADVISOR_EFFORT` (default low). When Fable is out of usage, bind Astra at the same effort. Codex: Astra in-session. Third-party: headless Fable then Astra. When the host's walk fails, fail closed.
|
|
28
|
+
3. Name: `team-advisor-agent` on Claude (Agent spawn of `session-advisor`); a native Astra subagent on Codex; one CLI `session_id` on a third-party host via the protocol Claude-chain or Astra helper.
|
|
29
29
|
4. A Fable-tier spawn or re-spawn carries the exact token `FABLE-SPAWN-AUTHORIZED` in its prompt (protocol warm-up; `fable_spawn_gate` requires it).
|
|
30
|
-
5. Skip the multi-consumer "who you are" opener
|
|
31
|
-
6. When the bind or reply path fails, fail closed and report to the user. On a third-party host, only the bound
|
|
30
|
+
5. Skip the multi-consumer "who you are" opener. This session is the sole consumer.
|
|
31
|
+
6. When the bind or reply path fails, fail closed and report to the user. On a third-party host, only the bound advisor issues ENDORSE / CORRECTION / PLAN / STOP.
|
|
32
32
|
|
|
33
|
-
**GOTCHA (Cursor / ThirdParty +
|
|
33
|
+
**GOTCHA (Cursor / ThirdParty + Astra):** when the walk reaches Astra or the user asks for Astra, first tool call is `python ~/.claude/_shared/advisor/scripts/codex_astra_advisor.py --bind --enable-astra --cwd <repo-root>` with the charter on stdin. Do not use Agent or Task. Do not search for a probe path. Details: [`third-party-bind.md`](../../_shared/advisor/reference/third-party-bind.md) GOTCHA and [`astra-rung.md`](../../_shared/advisor/reference/astra-rung.md).
|
|
34
34
|
|
|
35
|
-
Full walk, charter, consult packet,
|
|
35
|
+
Full walk, charter, consult packet, Astra routing, and drift re-bind live in the protocol read map and its `reference/` files.
|
|
36
36
|
|
|
37
37
|
## Consult
|
|
38
38
|
|
|
@@ -44,6 +44,6 @@ Aim for two consults on a normal task: one after orientation and one after write
|
|
|
44
44
|
|
|
45
45
|
## Constraints
|
|
46
46
|
|
|
47
|
-
- One bind per session; this session owns spawn, in-session
|
|
47
|
+
- One bind per session; this session owns spawn, in-session Astra spawn, or CLI bind, drift re-bind, and shutdown.
|
|
48
48
|
- Bind at or above the protocol floor for this host.
|
|
49
49
|
- The advisor only answers (messaging); the session runs tools and posts.
|
|
@@ -13,20 +13,20 @@ On Claude, continue with **Model floor** and the rest of this document.
|
|
|
13
13
|
|
|
14
14
|
## Read map
|
|
15
15
|
|
|
16
|
-
The sections below hold the standing rules
|
|
16
|
+
The sections below hold the standing rules. Open a reference file at the moment its row names.
|
|
17
17
|
|
|
18
18
|
| Moment | Open |
|
|
19
19
|
|---|---|
|
|
20
|
-
| Naming the session identity | [`reference/identity.md`](reference/identity.md)
|
|
21
|
-
| Binding on a Claude host | [`reference/warm-up.md`](reference/warm-up.md)
|
|
22
|
-
| Binding on a Codex host | [`reference/identity.md`](reference/identity.md)
|
|
23
|
-
| Binding from a third-party host | [`reference/third-party-bind.md`](reference/third-party-bind.md)
|
|
24
|
-
| Fable is out of usage | [`reference/
|
|
25
|
-
| Composing a consult | [`reference/consult-format.md`](reference/consult-format.md)
|
|
26
|
-
| Assembling an executor spawn prompt | [`reference/advisor-block.md`](reference/advisor-block.md)
|
|
27
|
-
| Advisor drifts, dies, or the task pivots | [`reference/lifecycle.md`](reference/lifecycle.md)
|
|
28
|
-
| Logging or checking a bind walk | [`reference/spawn-walk-log.md`](reference/spawn-walk-log.md)
|
|
29
|
-
| Any CLI call to a Claude advisor | [`reference/cli-chain.md`](reference/cli-chain.md)
|
|
20
|
+
| Naming the session identity | [`reference/identity.md`](reference/identity.md): Claude, Codex, or neither |
|
|
21
|
+
| Binding on a Claude host | [`reference/warm-up.md`](reference/warm-up.md): spawn fields, Fable token, charter |
|
|
22
|
+
| Binding on a Codex host | [`reference/identity.md`](reference/identity.md): in-session Astra spawn |
|
|
23
|
+
| Binding from a third-party host | [`reference/third-party-bind.md`](reference/third-party-bind.md): CLI bind steps, fail-closed rule |
|
|
24
|
+
| Fable is out of usage | [`reference/astra-rung.md`](reference/astra-rung.md): Astra fallback at shared effort |
|
|
25
|
+
| Composing a consult | [`reference/consult-format.md`](reference/consult-format.md): packet, new-evidence and report-back rules |
|
|
26
|
+
| Assembling an executor spawn prompt | [`reference/advisor-block.md`](reference/advisor-block.md): the paste parts |
|
|
27
|
+
| Advisor drifts, dies, or the task pivots | [`reference/lifecycle.md`](reference/lifecycle.md): re-spawn and re-bind steps |
|
|
28
|
+
| Logging or checking a bind walk | [`reference/spawn-walk-log.md`](reference/spawn-walk-log.md): record shape, validator |
|
|
29
|
+
| Any CLI call to a Claude advisor | [`reference/cli-chain.md`](reference/cli-chain.md): runner modes, alias table, resume |
|
|
30
30
|
|
|
31
31
|
## Host profiles
|
|
32
32
|
|
|
@@ -42,95 +42,95 @@ Session identity:
|
|
|
42
42
|
Mechanical override for scripts:
|
|
43
43
|
|
|
44
44
|
1. `ADVISOR_HOST_PROFILE=ThirdParty` or `=Claude` or `=Codex` (explicit override; any letter case).
|
|
45
|
-
2. `THIRD_PARTY=1` (or `true` / `yes` / `on`)
|
|
45
|
+
2. `THIRD_PARTY=1` (or `true` / `yes` / `on`) selects a third-party (non-Claude) harness.
|
|
46
46
|
3. Default: Claude.
|
|
47
47
|
|
|
48
|
-
### Shared effort
|
|
48
|
+
### Shared effort, any host
|
|
49
49
|
|
|
50
|
-
Fable and
|
|
51
|
-
Pass `--effort <level>` on the
|
|
50
|
+
Fable and Astra both read `ADVISOR_EFFORT` (`low`, `medium`, `high`, `xhigh`, `max`). The default is `low`.
|
|
51
|
+
Pass `--effort <level>` on the Astra helper to set effort for that Astra run.
|
|
52
52
|
Pass `--effort <level>` on the Claude CLI bind for Fable. An unset or unrecognized value uses `low`.
|
|
53
53
|
|
|
54
|
-
###
|
|
54
|
+
### Astra rung
|
|
55
55
|
|
|
56
|
-
On Claude and ThirdParty: when Fable is out of usage, bind
|
|
57
|
-
Open that attempt with `
|
|
56
|
+
On Claude and ThirdParty: when Fable is out of usage, bind Astra through the Codex helper.
|
|
57
|
+
Open that attempt with `ADVISOR_ASTRA=1` (or `true` / `yes` / `on`) in the environment, or pass `--enable-astra` on the helper invocation.
|
|
58
58
|
Flag off both ways: fail closed when Fable did not bind.
|
|
59
|
-
Flag on: run the Codex preflight and bind per [`reference/
|
|
59
|
+
Flag on: run the Codex preflight and bind per [`reference/astra-rung.md`](reference/astra-rung.md); a failed preflight fails closed when Fable did not bind.
|
|
60
60
|
|
|
61
|
-
On Codex:
|
|
61
|
+
On Codex: Astra is the in-session default. The `ADVISOR_ASTRA` flag is not required. Fail closed when that spawn does not bind.
|
|
62
62
|
|
|
63
63
|
### Claude host
|
|
64
64
|
|
|
65
|
-
Use the **Model floor** ladder below (Fable first, then
|
|
66
|
-
Warm-up spawns `subagent_type: session-advisor` via the Agent tool; consults go through `SendMessage` to that warm agent.
|
|
65
|
+
Use the **Model floor** ladder below (Fable first, then Astra when Fable is out of usage).
|
|
66
|
+
Warm-up spawns `subagent_type: session-advisor` via the Agent tool for Fable; consults go through `SendMessage` to that warm agent. Astra uses the Codex helper.
|
|
67
67
|
Assemble and paste each executor's Advisor block per the **Advisor block** section.
|
|
68
68
|
|
|
69
69
|
### Codex host
|
|
70
70
|
|
|
71
|
-
Spawn a native in-session
|
|
72
|
-
Walk `candidate_tiers = ["
|
|
73
|
-
**Fail closed:** when
|
|
74
|
-
Do not walk Fable on a Codex host. Consults stay in-session with that
|
|
71
|
+
Spawn a native in-session Astra subagent at `resolve_codex_model_id("Astra")`.
|
|
72
|
+
Walk `candidate_tiers = ["Astra"]`. Record `{tier: "Astra", result: "spawned"}` on success.
|
|
73
|
+
**Fail closed:** when Astra does not bind, set `selected_tier = null` and a `fallback_reason`, report that the advisor is unreachable, and **stop**.
|
|
74
|
+
Do not walk Fable on a Codex host. Consults stay in-session with that Astra subagent.
|
|
75
75
|
Assemble and paste each executor's Advisor block per the **Advisor block** section.
|
|
76
76
|
|
|
77
77
|
### Third-party host
|
|
78
78
|
|
|
79
79
|
On a third-party (non-Claude, non-Codex) harness, the shared CLI Claude-chain is the one path to a Claude advisor: bind Fable through it, per [`reference/third-party-bind.md`](reference/third-party-bind.md).
|
|
80
80
|
The bound Claude session is the advisor; this third-party session stays the executor.
|
|
81
|
-
Walk `candidate_tiers = ["Fable"]`. When Fable is out of usage, the
|
|
82
|
-
**Cursor
|
|
83
|
-
**Fail closed:** when every candidate fails, set `selected_tier = null` and a `fallback_reason`, report that the advisor is unreachable, and **stop
|
|
81
|
+
Walk `candidate_tiers = ["Fable"]`. When Fable is out of usage, the Astra rung binds after Fable (`candidate_tiers = ["Fable", "Astra"]`).
|
|
82
|
+
**Cursor Astra first shot:** when the walk reaches Astra (or the user asks for Astra), bind through `codex_astra_advisor.py --bind --enable-astra` on the first tool call (see the GOTCHA in [`reference/third-party-bind.md`](reference/third-party-bind.md)). Do not use the Agent tool, and do not hunt a probe path.
|
|
83
|
+
**Fail closed:** when every candidate fails, set `selected_tier = null` and a `fallback_reason`, report that the advisor is unreachable, and **stop**. ENDORSE / CORRECTION / PLAN / STOP come only from a bound advisor.
|
|
84
84
|
Executors report to the orchestrating session; that session consults the bound advisor and relays the four-signal reply.
|
|
85
85
|
|
|
86
86
|
## Model floor
|
|
87
87
|
|
|
88
|
-
On Claude and ThirdParty the advisor ladder is `Fable` first, then
|
|
89
|
-
On Codex the walk is
|
|
88
|
+
On Claude and ThirdParty the advisor ladder is `Fable` first, then Astra (flag-gated, Codex CLI) when Fable is out of usage.
|
|
89
|
+
On Codex the walk is Astra only, in-session.
|
|
90
90
|
Opus is not an advisor candidate. `Sonnet` and `Haiku` are executor tiers only.
|
|
91
91
|
Consumer `own_tier` is recorded on the spawn-walk log; it does not add Opus to the advisor walk.
|
|
92
92
|
Tier names are canonical Title Case; the validator accepts any letter case and normalizes to Title Case.
|
|
93
|
-
Try binds top-down.
|
|
94
|
-
The advisor is created at `selected_tier
|
|
95
|
-
When Fable fails on a Claude host, try
|
|
96
|
-
On a Codex host a failed
|
|
97
|
-
On a third-party host the CLI chain is already the primary path, so a failed Fable (and
|
|
93
|
+
Try binds top-down. Fable resolves to the short model alias in [`reference/cli-chain.md`](reference/cli-chain.md); Astra resolves through `resolve_codex_model_id("Astra")` to `gpt-6-astra`.
|
|
94
|
+
The advisor is created at `selected_tier`, the first ladder tier that binds.
|
|
95
|
+
When Fable fails on a Claude host, try Astra if the flag is on, else fail closed. The CLI chain is the Fable bind path on a third-party host and the Claude-host fallback for Fable; it does not bind Opus as advisor.
|
|
96
|
+
On a Codex host a failed Astra spawn fails closed per **Host profiles → Codex host**.
|
|
97
|
+
On a third-party host the CLI chain is already the primary path, so a failed Fable (and Astra, when enabled) walk fails closed per **Host profiles → Third-party host**.
|
|
98
98
|
|
|
99
99
|
Emit a structured spawn-walk log so the walk can be checked mechanically: [`reference/spawn-walk-log.md`](reference/spawn-walk-log.md).
|
|
100
100
|
The validator checks ladder shape only; host policy sits on top.
|
|
101
101
|
|
|
102
|
-
**Equal-tier pairings.** Bind Fable for an independent second pass on irreversible or security-sensitive work. The advisor is Fable or
|
|
102
|
+
**Equal-tier pairings.** Bind Fable for an independent second pass on irreversible or security-sensitive work. The advisor is Fable or Astra.
|
|
103
103
|
|
|
104
104
|
## Warm-up (once per session)
|
|
105
105
|
|
|
106
|
-
On a **Claude host**,
|
|
107
|
-
A **Fable**-tier try carries the exact token `FABLE-SPAWN-AUTHORIZED` in its prompt
|
|
106
|
+
On a **Claude host**, spawn `session-advisor` at the Fable alias with the charter as its prompt. When Fable is out of usage and the Astra rung is open, bind Astra through the Codex helper instead.
|
|
107
|
+
A **Fable**-tier try carries the exact token `FABLE-SPAWN-AUTHORIZED` in its prompt. `hooks/blocking/fable_spawn_gate.py` denies a Fable-tier spawn without it.
|
|
108
108
|
Full spawn fields and the charter template: [`reference/warm-up.md`](reference/warm-up.md).
|
|
109
109
|
|
|
110
|
-
On a **Codex host**, spawn a native in-session
|
|
110
|
+
On a **Codex host**, spawn a native in-session Astra subagent with the same charter. Bind fields: [`reference/identity.md`](reference/identity.md) and [`reference/warm-up.md`](reference/warm-up.md).
|
|
111
111
|
|
|
112
|
-
On a **third-party host**, bind per [`reference/third-party-bind.md`](reference/third-party-bind.md) and charter the CLI session with the same charter
|
|
112
|
+
On a **third-party host**, bind per [`reference/third-party-bind.md`](reference/third-party-bind.md) and charter the CLI session with the same charter. The reply contract is the same, and consults travel through the CLI runner.
|
|
113
113
|
|
|
114
114
|
## Consulting the warm agent
|
|
115
115
|
|
|
116
|
-
Send a consult at the trigger points `docs/references/advisor-tool.md` **When to call** defines
|
|
116
|
+
Send a consult at the trigger points `docs/references/advisor-tool.md` **When to call** defines: plan lock-in, believed completion, hard-to-reverse actions, repeated failure or stalled progress, and reconsidered approach.
|
|
117
117
|
The paste parts in [`reference/advisor-block.md`](reference/advisor-block.md) restate them for executors.
|
|
118
118
|
|
|
119
|
-
Each consult carries the sender's identity and assignment, the delta since the last consult, the live decision or blocker, and the paths or excerpts needed to answer well
|
|
119
|
+
Each consult carries the sender's identity and assignment, the delta since the last consult, the live decision or blocker, and the paths or excerpts needed to answer well. Full packet shape plus the new-evidence and report-back rules: [`reference/consult-format.md`](reference/consult-format.md).
|
|
120
120
|
Consult briefs embed the `docs/references/advisor-tool.md` **Brevity cue** line, sized per that section.
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
A CORRECTION names a wrong step or a risk worth closing. Address it before treating the plan or the work as done.
|
|
123
123
|
Route a STOP, or an unreachable advisor, upward per [`reference/consult-format.md`](reference/consult-format.md).
|
|
124
124
|
|
|
125
|
-
## Advisor block
|
|
125
|
+
## Advisor block
|
|
126
126
|
|
|
127
|
-
Assemble each executor's block from the parts in [`reference/advisor-block.md`](reference/advisor-block.md), in order: one transport preamble picked by host profile, then the shared core, then
|
|
127
|
+
Assemble each executor's block from the parts in [`reference/advisor-block.md`](reference/advisor-block.md), in order: one transport preamble picked by host profile, then the shared core, then the weak-executor add-on for an executor at Sonnet or below.
|
|
128
128
|
Paste the assembled block at the **top** of the spawn prompt, ahead of any other sentence that mentions the advisor.
|
|
129
|
-
The assembled block is self-contained
|
|
129
|
+
The assembled block is self-contained. The executor receives this text alone.
|
|
130
130
|
|
|
131
131
|
## Lifecycle ownership
|
|
132
132
|
|
|
133
|
-
The session that binds the advisor owns its whole lifecycle
|
|
133
|
+
The session that binds the advisor owns its whole lifecycle: first bind, drift re-spawn or re-bind, and shutdown. Every other consumer reaches the advisor by message alone.
|
|
134
134
|
Drift signals and the per-host re-spawn / re-bind steps: [`reference/lifecycle.md`](reference/lifecycle.md).
|
|
135
135
|
|
|
136
136
|
## CLI chain
|
|
@@ -140,14 +140,14 @@ Modes and failover, the tier-to-alias table, brief piping, and `--resume` sessio
|
|
|
140
140
|
|
|
141
141
|
**Third-party host:** the primary bind and consult path; the walk order and fail-closed rule live in [`reference/third-party-bind.md`](reference/third-party-bind.md).
|
|
142
142
|
|
|
143
|
-
**Codex host:** do not use this runner as the primary path.
|
|
143
|
+
**Codex host:** do not use this runner as the primary path. Astra binds in-session.
|
|
144
144
|
|
|
145
145
|
**Claude host:** fall back to this runner exactly when one of these holds:
|
|
146
|
-
- The Agent-tool spawn errors at every candidate tier down to the floor
|
|
146
|
+
- The Agent-tool spawn errors at every candidate tier down to the floor. The tool itself is unavailable.
|
|
147
147
|
- `SendMessage` to the shared advisor errors, or draws no reply within the bound in `ADVISOR_SENDMESSAGE_REPLY_WAIT_SECONDS` (120) in `$HOME/.claude/_shared/advisor/scripts/config/advisor_scripts_constants/model_tier_run_validator_constants.py`, and a re-spawn also fails.
|
|
148
148
|
- The running session is itself a subagent barred from spawning further agents.
|
|
149
149
|
|
|
150
150
|
## State the mechanism
|
|
151
151
|
|
|
152
|
-
One warm agent, addressed by name, whose transcript accumulates across consults
|
|
152
|
+
One warm agent, addressed by name, whose transcript accumulates across consults. Each consult sends only the delta since the last one.
|
|
153
153
|
A consuming skill's own text states this mechanism; a token or cost saving becomes a claim only after a measured comparison against cold spawns.
|