greprag 5.74.8 → 5.74.10
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/dist/codex-checkpoint-hook.js +184 -0
- package/dist/codex-chip-hooks.js +1 -1
- package/dist/codex-fast-hook.js +14 -1
- package/dist/commands/codex-chip/help.js +3 -2
- package/dist/commands/codex-chip/prompt.js +2 -1
- package/dist/commands/codex-generated-cleanup.js +170 -0
- package/dist/commands/codex-model-policy.js +0 -16
- package/dist/commands/codex.js +6 -0
- package/dist/commands/coordinate-gate.js +25 -0
- package/dist/commands/init.js +15 -2
- package/dist/commands/load-primer-reminder.js +1 -1
- package/dist/commands/load.js +2 -5
- package/dist/commands/mechanic-spawn.js +3 -2
- package/dist/commands/os-primer-reminder.js +1 -1
- package/dist/opencode-plugin.bundle.js +2 -2
- package/package.json +1 -1
- package/skill/greprag/SKILL.md +3 -1
- package/skill/greprag/docs/codex-chip.md +10 -2
- package/skill/mechanic/SKILL.md +3 -4
- package/skill/templates/codex-chip-spawn.md +166 -121
- package/skill/templates/codex-subagent-spawn.md +0 -34
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** Codex checkpoint coordination — detect a successful Git commit transition
|
|
3
|
+
* and inject the delivery handoff at that exact lifecycle boundary.
|
|
4
|
+
*
|
|
5
|
+
* PreToolUse records the prior HEAD around shell-capable tools. PostToolUse
|
|
6
|
+
* proves HEAD changed via a commit reflog action and emits immediately; the
|
|
7
|
+
* next PreToolUse is a fallback if that lifecycle event was unavailable.
|
|
8
|
+
* User prompt and executor-wrapper wording are irrelevant.
|
|
9
|
+
* adr: adr/codex-checkpoint-coordination.md */
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.checkpointCoordinationText = checkpointCoordinationText;
|
|
45
|
+
exports.recordCodexGitBoundary = recordCodexGitBoundary;
|
|
46
|
+
exports.evaluateCodexCommitResult = evaluateCodexCommitResult;
|
|
47
|
+
exports.evaluatePendingCodexCheckpoint = evaluatePendingCodexCheckpoint;
|
|
48
|
+
const crypto = __importStar(require("crypto"));
|
|
49
|
+
const fs = __importStar(require("fs"));
|
|
50
|
+
const path = __importStar(require("path"));
|
|
51
|
+
const child_process_1 = require("child_process");
|
|
52
|
+
function homeDir() {
|
|
53
|
+
return process.env.USERPROFILE || process.env.HOME || '';
|
|
54
|
+
}
|
|
55
|
+
function normalizedCwd(input) {
|
|
56
|
+
return path.resolve(input.cwd || process.cwd()).replace(/\\/g, '/').toLowerCase();
|
|
57
|
+
}
|
|
58
|
+
function statePath(input) {
|
|
59
|
+
const home = homeDir();
|
|
60
|
+
const session = (input.session_id || '').trim();
|
|
61
|
+
if (!home || !session)
|
|
62
|
+
return null;
|
|
63
|
+
const key = crypto.createHash('sha256')
|
|
64
|
+
.update(`${session}\0${normalizedCwd(input)}`)
|
|
65
|
+
.digest('hex')
|
|
66
|
+
.slice(0, 24);
|
|
67
|
+
return path.join(home, '.greprag', 'state', `codex-checkpoint-${key}.json`);
|
|
68
|
+
}
|
|
69
|
+
function git(cwd, args) {
|
|
70
|
+
try {
|
|
71
|
+
return (0, child_process_1.execFileSync)('git', args, {
|
|
72
|
+
cwd,
|
|
73
|
+
encoding: 'utf8',
|
|
74
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
75
|
+
windowsHide: true,
|
|
76
|
+
}).trim() || null;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function currentHead(cwd) {
|
|
83
|
+
return git(cwd, ['rev-parse', 'HEAD']);
|
|
84
|
+
}
|
|
85
|
+
function currentBranch(cwd) {
|
|
86
|
+
return git(cwd, ['branch', '--show-current']) || '(detached HEAD)';
|
|
87
|
+
}
|
|
88
|
+
function latestHeadAction(cwd) {
|
|
89
|
+
return git(cwd, ['reflog', '-1', '--format=%gs', 'HEAD']) || '';
|
|
90
|
+
}
|
|
91
|
+
function isCommitHeadAction(cwd) {
|
|
92
|
+
return /^commit(?: \([^)]+\))?:/i.test(latestHeadAction(cwd));
|
|
93
|
+
}
|
|
94
|
+
function isShellCapableTool(input) {
|
|
95
|
+
const name = (input.tool_name || '').toLowerCase();
|
|
96
|
+
return /(?:^|[.:/_-])(bash|shell|exec|exec_command|write_stdin)$/.test(name);
|
|
97
|
+
}
|
|
98
|
+
function writePending(file, pending) {
|
|
99
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
100
|
+
fs.writeFileSync(file, JSON.stringify(pending, null, 2) + '\n');
|
|
101
|
+
}
|
|
102
|
+
function readPending(file) {
|
|
103
|
+
try {
|
|
104
|
+
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function clearPending(file) {
|
|
111
|
+
try {
|
|
112
|
+
fs.unlinkSync(file);
|
|
113
|
+
}
|
|
114
|
+
catch { /* already absent */ }
|
|
115
|
+
}
|
|
116
|
+
function consumePending(input, hookEventName) {
|
|
117
|
+
const file = statePath(input);
|
|
118
|
+
if (!file)
|
|
119
|
+
return null;
|
|
120
|
+
const pending = readPending(file);
|
|
121
|
+
if (!pending || pending.cwd !== normalizedCwd(input))
|
|
122
|
+
return null;
|
|
123
|
+
clearPending(file);
|
|
124
|
+
const cwd = input.cwd || process.cwd();
|
|
125
|
+
const afterHead = currentHead(cwd);
|
|
126
|
+
if (!afterHead || afterHead === pending.beforeHead || !isCommitHeadAction(cwd))
|
|
127
|
+
return null;
|
|
128
|
+
return {
|
|
129
|
+
hookSpecificOutput: {
|
|
130
|
+
hookEventName,
|
|
131
|
+
additionalContext: checkpointCoordinationText(currentBranch(cwd), afterHead.slice(0, 12)),
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function checkpointCoordinationText(branch, sha) {
|
|
136
|
+
return `[DELIVERY COORDINATION — CHECKPOINT CREATED]
|
|
137
|
+
|
|
138
|
+
Checkpoint: ${branch} @ ${sha}
|
|
139
|
+
|
|
140
|
+
Coordinate now, before merge, push, deploy, publish, or release.
|
|
141
|
+
|
|
142
|
+
- Child task: send the LEAD your branch, SHA, checks, status, owned dirt, and blockers. The LEAD owns integration.
|
|
143
|
+
- LEAD/standalone task: call codex_app.list_threads unfiltered, scope to this repo/worktree, exclude yourself, and ask every live peer for its latest checkpoint, owned dirt, blockers, and sequencing needs.
|
|
144
|
+
- Elect exactly one delivery owner. If no peers exist, you are the owner.
|
|
145
|
+
- Use greprag send for cross-harness peers.
|
|
146
|
+
|
|
147
|
+
Do not begin a delivery action until coordination is settled.`;
|
|
148
|
+
}
|
|
149
|
+
/** PreToolUse leg: remember HEAD around any shell-capable action. The result
|
|
150
|
+
* leg classifies the actual Git transition, so nested executor syntax and
|
|
151
|
+
* dynamically composed commands do not matter. */
|
|
152
|
+
function recordCodexGitBoundary(input) {
|
|
153
|
+
if (input.hook_event_name !== 'PreToolUse')
|
|
154
|
+
return;
|
|
155
|
+
if (!isShellCapableTool(input))
|
|
156
|
+
return;
|
|
157
|
+
const file = statePath(input);
|
|
158
|
+
if (!file)
|
|
159
|
+
return;
|
|
160
|
+
const cwd = input.cwd || process.cwd();
|
|
161
|
+
writePending(file, {
|
|
162
|
+
sessionId: input.session_id || '',
|
|
163
|
+
cwd: normalizedCwd(input),
|
|
164
|
+
toolName: input.tool_name || '',
|
|
165
|
+
beforeHead: currentHead(cwd),
|
|
166
|
+
recordedAt: new Date().toISOString(),
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
/** Preferred result leg: emit on the successful commit's own PostToolUse. */
|
|
170
|
+
function evaluateCodexCommitResult(input) {
|
|
171
|
+
if (input.hook_event_name !== 'PostToolUse')
|
|
172
|
+
return null;
|
|
173
|
+
if (!isShellCapableTool(input))
|
|
174
|
+
return null;
|
|
175
|
+
return consumePending(input, 'PostToolUse');
|
|
176
|
+
}
|
|
177
|
+
/** Fallback result leg: if PostToolUse was unavailable, emit before the first
|
|
178
|
+
* later tool call. Failed/empty commits leave HEAD unchanged and clear
|
|
179
|
+
* silently. */
|
|
180
|
+
function evaluatePendingCodexCheckpoint(input) {
|
|
181
|
+
if (input.hook_event_name !== 'PreToolUse')
|
|
182
|
+
return null;
|
|
183
|
+
return consumePending(input, 'PreToolUse');
|
|
184
|
+
}
|
package/dist/codex-chip-hooks.js
CHANGED
|
@@ -69,7 +69,7 @@ function context(input) {
|
|
|
69
69
|
'Landing: the parent is the delivery owner for merge, post-merge branch/manifest bookkeeping, and any profile-declared push/deploy/release; the child owns routine archival of its own task after the terminal message is delivered. Do not edit the parent checkout or independently cross delivery boundaries. A mission whose first line begins `FIX:` (emitted by `greprag fix spawn`) is writable in its isolated checkout/worktree and hands its verified checkpoint to that owner without a human approval gate. If no live parent exists and the chip carries the full-goal mission, it becomes delivery owner. `greprag fix spawn` only prints the mission; visible Codex task dispatch creates the isolated checkout/worktree.',
|
|
70
70
|
];
|
|
71
71
|
if ((0, model_1.chipMissionKind)(chip) === 'fix') {
|
|
72
|
-
lines.push('Harness: Codex. Mission: visible native FIX chip with ordinary writable authority, not
|
|
72
|
+
lines.push('Harness: Codex. Mission: visible native FIX chip with ordinary writable authority, not a same-session helper.', 'Scope: repair GrepRAG-owned harness surfaces in this checkout: load entries, skill templates, docs, hook context, CLI messages, and tests. Codex owns native task creation, worktrees, permissions, Git, and task lifecycle.', 'Own diagnosis, implementation, tests, commit, and parent report. Inspect Codex behavior only far enough to correct GrepRAG guidance or report a precise external blocker.', 'FIX peer handoff: if a peer offers to coordinate, integrate, rework, or take over a harness repair, hand off branch/commit, dirty files, checks, blockers, and caveats. Do not defend patch ownership; peers may take ownership within their assigned GrepRAG harness scope.', 'Visible delegation route: load `codex-chip-spawn` and create the child with `codex_app__create_thread` using the current project worktree target; load `chip-leader` for multi-chip seams. Same-session helper tools never satisfy a visible-chip requirement.');
|
|
73
73
|
}
|
|
74
74
|
return output(input.hook_event_name || 'SessionStart', lines.join('\n'));
|
|
75
75
|
}
|
package/dist/codex-fast-hook.js
CHANGED
|
@@ -65,9 +65,10 @@ async function main() {
|
|
|
65
65
|
const subcommand = process.argv[2];
|
|
66
66
|
if (subcommand !== 'codex-chip-hook'
|
|
67
67
|
&& subcommand !== 'codex-pretooluse'
|
|
68
|
+
&& subcommand !== 'codex-posttooluse'
|
|
68
69
|
&& subcommand !== 'codex-notify'
|
|
69
70
|
&& subcommand !== 'codex-store') {
|
|
70
|
-
process.stderr.write('Usage: greprag-codex-hook <codex-chip-hook|codex-pretooluse|codex-notify|codex-store>\n');
|
|
71
|
+
process.stderr.write('Usage: greprag-codex-hook <codex-chip-hook|codex-pretooluse|codex-posttooluse|codex-notify|codex-store>\n');
|
|
71
72
|
process.exit(1);
|
|
72
73
|
}
|
|
73
74
|
const input = await readInput();
|
|
@@ -81,6 +82,13 @@ async function main() {
|
|
|
81
82
|
await runCodexNotify(input);
|
|
82
83
|
return;
|
|
83
84
|
}
|
|
85
|
+
if (subcommand === 'codex-posttooluse') {
|
|
86
|
+
const { evaluateCodexCommitResult } = await Promise.resolve().then(() => __importStar(require('./codex-checkpoint-hook')));
|
|
87
|
+
const result = evaluateCodexCommitResult(input);
|
|
88
|
+
if (result)
|
|
89
|
+
process.stdout.write(JSON.stringify(result) + '\n');
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
84
92
|
const { evaluateCodexChipHook } = await Promise.resolve().then(() => __importStar(require('./codex-chip-hooks')));
|
|
85
93
|
const chipResult = evaluateCodexChipHook(input);
|
|
86
94
|
if (subcommand === 'codex-chip-hook') {
|
|
@@ -89,6 +97,11 @@ async function main() {
|
|
|
89
97
|
return;
|
|
90
98
|
}
|
|
91
99
|
let result = chipResult;
|
|
100
|
+
if (subcommand === 'codex-pretooluse') {
|
|
101
|
+
const { evaluatePendingCodexCheckpoint, recordCodexGitBoundary, } = await Promise.resolve().then(() => __importStar(require('./codex-checkpoint-hook')));
|
|
102
|
+
result = mergeOutputs(result, evaluatePendingCodexCheckpoint(input));
|
|
103
|
+
recordCodexGitBoundary(input);
|
|
104
|
+
}
|
|
92
105
|
if (!result?.hookSpecificOutput.permissionDecision && input.tool_name === 'Bash') {
|
|
93
106
|
const { runSearchGuard } = await Promise.resolve().then(() => __importStar(require('./commands/search-guard')));
|
|
94
107
|
result = mergeOutputs(result, runSearchGuard(input));
|
|
@@ -15,8 +15,9 @@ exports.CODEX_CHIP_HELP = `greprag codex chip — Codex task orchestration
|
|
|
15
15
|
|
|
16
16
|
Native Codex Desktop is the default: omit --runtime. Use --runtime cli only for
|
|
17
17
|
the explicit headless fallback. Spawn prepares the Desktop create request and
|
|
18
|
-
handoff with
|
|
19
|
-
|
|
18
|
+
handoff with a Codex worktree environment plus
|
|
19
|
+
\`startingState.branchName\`. The standalone CLI does not create the Desktop
|
|
20
|
+
task itself. The active topology is an implicit LEAD for
|
|
20
21
|
quick chips, an explicit LEAD for multi-chip orchestration, and Chip A/B/C with
|
|
21
22
|
optional ADVISOR orientation. FIX missions are visible one-friction tasks from
|
|
22
23
|
\`greprag fix spawn\`: they select \`chip.fix\` and load mechanic doctrine.
|
|
@@ -26,7 +26,8 @@ function chipPrompt(manifest, _cliCommand = 'greprag') {
|
|
|
26
26
|
|
|
27
27
|
Setup — do this FIRST:
|
|
28
28
|
${mechanicSetup}${leaderSetup}- Stay in ${executionPath}. Applicable AGENTS instructions and the session-start recap are already in context; inspect the current repository state.
|
|
29
|
-
- Bootstrap this checkout before build/test: if \`scripts/
|
|
29
|
+
- Bootstrap this checkout before build/test: if \`scripts/worktree-bootstrap.cjs\` exists, run \`node scripts/worktree-bootstrap.cjs\`; if only \`scripts/ensure-npm-deps.cjs\` exists, run \`node scripts/ensure-npm-deps.cjs\`. Never link or junction \`node_modules\` to another checkout.
|
|
30
|
+
- When running build/test or other env-driven commands, use \`node scripts/codex-run.cjs -- <command ...>\` if that wrapper exists. It loads ignored env files from the main checkout; never copy or print secrets.
|
|
30
31
|
- Do not create a second worktree. The selected workspace is fully writable; there are no leases, read-only mode, or GrepRAG goal gates.
|
|
31
32
|
- The durable manifest is ${manifest.id}; it is task bookkeeping, not a scope or permission gate.
|
|
32
33
|
${startupInstruction}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.cleanupCodexGeneratedDist = cleanupCodexGeneratedDist;
|
|
37
|
+
exports.runCodexCleanGenerated = runCodexCleanGenerated;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const proc_1 = require("../proc");
|
|
41
|
+
function samePath(left, right) {
|
|
42
|
+
const l = path.resolve(left);
|
|
43
|
+
const r = path.resolve(right);
|
|
44
|
+
return process.platform === 'win32' ? l.toLowerCase() === r.toLowerCase() : l === r;
|
|
45
|
+
}
|
|
46
|
+
function isInside(parent, child) {
|
|
47
|
+
const relative = path.relative(path.resolve(parent), path.resolve(child));
|
|
48
|
+
return !!relative && !relative.startsWith('..') && !path.isAbsolute(relative);
|
|
49
|
+
}
|
|
50
|
+
function gitRootFor(start) {
|
|
51
|
+
try {
|
|
52
|
+
return path.resolve(String((0, proc_1.safeExecFileSync)('git', ['-C', start, 'rev-parse', '--show-toplevel'], {
|
|
53
|
+
encoding: 'utf8',
|
|
54
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
55
|
+
})).trim());
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function assertDistLeaf(target) {
|
|
62
|
+
if (path.basename(target).toLowerCase() !== 'dist') {
|
|
63
|
+
throw new Error(`Refusing generated cleanup for non-dist path: ${target}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function assertNoRepoMetadata(target) {
|
|
67
|
+
if (fs.existsSync(path.join(target, '.git'))) {
|
|
68
|
+
throw new Error(`Refusing to remove a directory containing .git metadata: ${target}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function cleanupBound(target, opts) {
|
|
72
|
+
const cwd = path.resolve(opts.cwd || process.cwd());
|
|
73
|
+
if (opts.under) {
|
|
74
|
+
const bound = path.resolve(cwd, opts.under);
|
|
75
|
+
if (samePath(bound, target) || !isInside(bound, target)) {
|
|
76
|
+
throw new Error(`Refusing cleanup outside explicit --under bound: ${target}`);
|
|
77
|
+
}
|
|
78
|
+
return { bound, boundKind: 'explicit-under' };
|
|
79
|
+
}
|
|
80
|
+
const parent = path.dirname(target);
|
|
81
|
+
if (!fs.existsSync(parent)) {
|
|
82
|
+
throw new Error(`Refusing cleanup because parent directory does not exist: ${parent}`);
|
|
83
|
+
}
|
|
84
|
+
const gitStart = fs.existsSync(target) && fs.lstatSync(target).isDirectory() ? target : parent;
|
|
85
|
+
const gitRoot = gitRootFor(gitStart);
|
|
86
|
+
if (!gitRoot) {
|
|
87
|
+
throw new Error(`Refusing cleanup outside a Git worktree; pass --under <dir> for an explicit bound: ${target}`);
|
|
88
|
+
}
|
|
89
|
+
if (samePath(gitRoot, target) || !isInside(gitRoot, target)) {
|
|
90
|
+
throw new Error(`Refusing cleanup outside Git root ${gitRoot}: ${target}`);
|
|
91
|
+
}
|
|
92
|
+
return { bound: gitRoot, boundKind: 'git-root' };
|
|
93
|
+
}
|
|
94
|
+
function cleanupCodexGeneratedDist(targetArg, opts = {}) {
|
|
95
|
+
if (!targetArg || !targetArg.trim())
|
|
96
|
+
throw new Error('Missing generated directory path.');
|
|
97
|
+
const cwd = path.resolve(opts.cwd || process.cwd());
|
|
98
|
+
const target = path.resolve(cwd, targetArg);
|
|
99
|
+
assertDistLeaf(target);
|
|
100
|
+
const bound = cleanupBound(target, opts);
|
|
101
|
+
const dryRun = !!opts.dryRun;
|
|
102
|
+
if (!fs.existsSync(target)) {
|
|
103
|
+
return { target, ...bound, removed: false, dryRun, reason: 'missing' };
|
|
104
|
+
}
|
|
105
|
+
const stat = fs.lstatSync(target);
|
|
106
|
+
if (stat.isSymbolicLink()) {
|
|
107
|
+
throw new Error(`Refusing to remove symlink/reparse target: ${target}`);
|
|
108
|
+
}
|
|
109
|
+
if (!stat.isDirectory()) {
|
|
110
|
+
throw new Error(`Refusing to remove non-directory generated path: ${target}`);
|
|
111
|
+
}
|
|
112
|
+
assertNoRepoMetadata(target);
|
|
113
|
+
if (dryRun) {
|
|
114
|
+
return { target, ...bound, removed: false, dryRun, reason: 'dry-run' };
|
|
115
|
+
}
|
|
116
|
+
fs.rmSync(target, { recursive: true, force: false });
|
|
117
|
+
if (fs.existsSync(target))
|
|
118
|
+
throw new Error(`Cleanup did not remove target: ${target}`);
|
|
119
|
+
return { target, ...bound, removed: true, dryRun };
|
|
120
|
+
}
|
|
121
|
+
function parseArgs(args) {
|
|
122
|
+
let under;
|
|
123
|
+
let dryRun = false;
|
|
124
|
+
let json = false;
|
|
125
|
+
const positional = [];
|
|
126
|
+
for (let i = 0; i < args.length; i++) {
|
|
127
|
+
const arg = args[i];
|
|
128
|
+
if (arg === '--dry-run') {
|
|
129
|
+
dryRun = true;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
if (arg === '--json') {
|
|
133
|
+
json = true;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (arg === '--under') {
|
|
137
|
+
under = args[++i];
|
|
138
|
+
if (!under)
|
|
139
|
+
throw new Error('Missing value for --under.');
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (arg.startsWith('--'))
|
|
143
|
+
throw new Error(`Unknown clean-generated flag: ${arg}`);
|
|
144
|
+
positional.push(arg);
|
|
145
|
+
}
|
|
146
|
+
if (positional.length !== 1) {
|
|
147
|
+
throw new Error('Usage: greprag codex clean-generated <path-to-dist> [--under <dir>] [--dry-run] [--json]');
|
|
148
|
+
}
|
|
149
|
+
return { target: positional[0], under, dryRun, json };
|
|
150
|
+
}
|
|
151
|
+
function runCodexCleanGenerated(args) {
|
|
152
|
+
const parsed = parseArgs(args);
|
|
153
|
+
const result = cleanupCodexGeneratedDist(parsed.target, {
|
|
154
|
+
under: parsed.under,
|
|
155
|
+
dryRun: parsed.dryRun,
|
|
156
|
+
});
|
|
157
|
+
if (parsed.json) {
|
|
158
|
+
console.log(JSON.stringify(result));
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const action = result.reason === 'missing'
|
|
162
|
+
? 'already absent'
|
|
163
|
+
: result.reason === 'dry-run'
|
|
164
|
+
? 'would remove'
|
|
165
|
+
: result.removed
|
|
166
|
+
? 'removed'
|
|
167
|
+
: 'unchanged';
|
|
168
|
+
console.log(`Codex generated cleanup ${action}: ${result.target}`);
|
|
169
|
+
console.log(`Bound: ${result.boundKind} ${result.bound}`);
|
|
170
|
+
}
|
|
@@ -36,7 +36,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.KNOWN_CODEX_MODEL_EFFORTS = exports.DEFAULT_CODEX_MODEL_POLICY = exports.CODEX_MODEL_EFFORTS = void 0;
|
|
37
37
|
exports.loadCodexModelPolicy = loadCodexModelPolicy;
|
|
38
38
|
exports.resolveChipModelSlot = resolveChipModelSlot;
|
|
39
|
-
exports.resolveSubagentModelSlot = resolveSubagentModelSlot;
|
|
40
39
|
exports.printCodexModelPolicy = printCodexModelPolicy;
|
|
41
40
|
const fs = __importStar(require("fs"));
|
|
42
41
|
const os = __importStar(require("os"));
|
|
@@ -51,11 +50,6 @@ exports.DEFAULT_CODEX_MODEL_POLICY = {
|
|
|
51
50
|
advisor: { model: 'gpt-5.6-sol', effort: 'high' },
|
|
52
51
|
fix: { model: 'gpt-5.5', effort: 'high' },
|
|
53
52
|
},
|
|
54
|
-
subagent: {
|
|
55
|
-
fast_scan: { model: 'gpt-5.5', effort: 'medium' },
|
|
56
|
-
routine_worker: { model: 'gpt-5.5', effort: 'high' },
|
|
57
|
-
deep_worker: { model: 'gpt-5.6-luna', effort: 'xhigh' },
|
|
58
|
-
},
|
|
59
53
|
};
|
|
60
54
|
exports.KNOWN_CODEX_MODEL_EFFORTS = {
|
|
61
55
|
'gpt-5.6-sol': ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'],
|
|
@@ -90,11 +84,6 @@ function applyPolicy(base, patch, source) {
|
|
|
90
84
|
throw new Error(`${source} has unknown chip model slot ${key}.`);
|
|
91
85
|
base.chip[key] = applySlot(base.chip[key], chipPatch[key] || {}, `${source} chip.${key}`);
|
|
92
86
|
}
|
|
93
|
-
for (const key of Object.keys(patch.subagent || {})) {
|
|
94
|
-
if (!(key in base.subagent))
|
|
95
|
-
throw new Error(`${source} has unknown subagent model slot ${key}.`);
|
|
96
|
-
base.subagent[key] = applySlot(base.subagent[key], patch.subagent[key] || {}, `${source} subagent.${key}`);
|
|
97
|
-
}
|
|
98
87
|
return base;
|
|
99
88
|
}
|
|
100
89
|
function readPolicyFile(filePath) {
|
|
@@ -148,9 +137,6 @@ function loadCodexModelPolicy(cwd = process.cwd(), homeDir = process.env.HOME ||
|
|
|
148
137
|
function resolveChipModelSlot(role, policy = loadCodexModelPolicy()) {
|
|
149
138
|
return policy.chip[role];
|
|
150
139
|
}
|
|
151
|
-
function resolveSubagentModelSlot(role, policy = loadCodexModelPolicy()) {
|
|
152
|
-
return policy.subagent[role];
|
|
153
|
-
}
|
|
154
140
|
function printCodexModelPolicy(args = []) {
|
|
155
141
|
const json = args.includes('--json');
|
|
156
142
|
const policy = loadCodexModelPolicy();
|
|
@@ -160,6 +146,4 @@ function printCodexModelPolicy(args = []) {
|
|
|
160
146
|
console.log('Config files: ~/.greprag/codex-models.json, then .greprag/codex-models.json');
|
|
161
147
|
for (const [role, slot] of Object.entries(policy.chip))
|
|
162
148
|
console.log(` chip.${role}: ${slot.model} / ${slot.effort}`);
|
|
163
|
-
for (const [role, slot] of Object.entries(policy.subagent))
|
|
164
|
-
console.log(` subagent.${role}: ${slot.model} / ${slot.effort}`);
|
|
165
149
|
}
|
package/dist/commands/codex.js
CHANGED
|
@@ -53,6 +53,7 @@ const codex_app_server_1 = require("./codex-app-server");
|
|
|
53
53
|
const codex_delivery_1 = require("./codex-delivery");
|
|
54
54
|
const codex_model_policy_1 = require("./codex-model-policy");
|
|
55
55
|
const codex_startup_1 = require("./codex-startup");
|
|
56
|
+
const codex_generated_cleanup_1 = require("./codex-generated-cleanup");
|
|
56
57
|
const codex_watch_health_1 = require("./codex-watch-health");
|
|
57
58
|
var codex_startup_2 = require("./codex-startup");
|
|
58
59
|
Object.defineProperty(exports, "codexStartupInfo", { enumerable: true, get: function () { return codex_startup_2.codexStartupInfo; } });
|
|
@@ -458,6 +459,7 @@ const HELP = `greprag codex — Codex-specific helpers.
|
|
|
458
459
|
greprag codex models show [--json]
|
|
459
460
|
greprag codex chip spawn "<task>" --name <name> [--role worker|leader|planner|advisor] [--runtime cli]
|
|
460
461
|
greprag codex chip list|status|steer|stop|report|block|cleanup|reconcile
|
|
462
|
+
greprag codex clean-generated <path-to-dist> [--under <dir>] [--dry-run] [--json]
|
|
461
463
|
greprag codex doctor
|
|
462
464
|
greprag codex startup remove
|
|
463
465
|
|
|
@@ -518,6 +520,10 @@ async function runCodex(args) {
|
|
|
518
520
|
await (0, command_1.runCodexChip)(args.slice(1));
|
|
519
521
|
return;
|
|
520
522
|
}
|
|
523
|
+
if (sub === 'clean-generated') {
|
|
524
|
+
(0, codex_generated_cleanup_1.runCodexCleanGenerated)(args.slice(1));
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
521
527
|
if (sub !== 'watch' && sub !== 'arm') {
|
|
522
528
|
console.error(`Unknown codex command: ${sub}\n`);
|
|
523
529
|
console.log(HELP);
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
* shared-state mutation actually happens. The eval is ready for a future Write
|
|
39
39
|
* adapter; only a new triggerFrom* + a `Write|Edit` matcher would be needed. */
|
|
40
40
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.hasGitSubcommand = hasGitSubcommand;
|
|
41
42
|
exports.classifyRiskyCommand = classifyRiskyCommand;
|
|
42
43
|
exports.triggerFromPreToolUse = triggerFromPreToolUse;
|
|
43
44
|
exports.buildCoordinateDirective = buildCoordinateDirective;
|
|
@@ -141,6 +142,30 @@ function classifyGit(tokens) {
|
|
|
141
142
|
return { kind: 'push', label: 'git push' };
|
|
142
143
|
return null;
|
|
143
144
|
}
|
|
145
|
+
/** True when any executable command segment invokes the requested Git
|
|
146
|
+
* subcommand, including `git -C <worktree> <subcommand>`. Exported so lifecycle
|
|
147
|
+
* hooks can key off agent-generated Git actions instead of user prompt words. */
|
|
148
|
+
function hasGitSubcommand(command, expected) {
|
|
149
|
+
if (!command || !expected)
|
|
150
|
+
return false;
|
|
151
|
+
for (const seg of commandSegments(command)) {
|
|
152
|
+
const tokens = shellWords(seg);
|
|
153
|
+
if (tokens[0] !== 'git')
|
|
154
|
+
continue;
|
|
155
|
+
let i = 1;
|
|
156
|
+
const optionsWithValue = new Set([
|
|
157
|
+
'-C', '-c', '--exec-path', '--git-dir', '--work-tree', '--namespace', '--super-prefix', '--config-env',
|
|
158
|
+
]);
|
|
159
|
+
while (i < tokens.length && tokens[i].startsWith('-')) {
|
|
160
|
+
const option = tokens[i++];
|
|
161
|
+
if (optionsWithValue.has(option) && i < tokens.length)
|
|
162
|
+
i++;
|
|
163
|
+
}
|
|
164
|
+
if (tokens[i] === expected)
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
144
169
|
/** Classify a Bash command into a risky-action trigger, or null. PURE. Matches
|
|
145
170
|
* the FIRST risky segment (a chained command fires on whichever risky verb
|
|
146
171
|
* appears first). */
|
package/dist/commands/init.js
CHANGED
|
@@ -636,9 +636,9 @@ async function runCodexInit(opts) {
|
|
|
636
636
|
}
|
|
637
637
|
console.log(`\n Codex hooks file: ${hooksPath}`);
|
|
638
638
|
console.log(` Project anchor: ${anchor.anchorPath}`);
|
|
639
|
-
console.log('
|
|
639
|
+
console.log(' Open Settings -> Settings -> Hooks and trust the GrepRAG hook definitions, then fully restart Codex Desktop.');
|
|
640
640
|
console.log(' Inbox messages for Codex surface on SessionStart and UserPromptSubmit hook boundaries.');
|
|
641
|
-
console.log('
|
|
641
|
+
console.log(' Hooks will activate after the Codex host restart; starting only a new task is not sufficient after hook changes.\n');
|
|
642
642
|
}
|
|
643
643
|
/** greprag init --global
|
|
644
644
|
* Creates ~/.greprag/project.json with a stable UUID.
|
|
@@ -1130,6 +1130,19 @@ function applyCodexHooks(config) {
|
|
|
1130
1130
|
if (removedPostToolInbox) {
|
|
1131
1131
|
changes.push(`Removed ${removedPostToolInbox} Codex PostToolUse inbox hook(s); UserPromptSubmit now owns inbox steering`);
|
|
1132
1132
|
}
|
|
1133
|
+
const checkpointHook = {
|
|
1134
|
+
matcher: '',
|
|
1135
|
+
hooks: [commandHook('codex-posttooluse', 5, 'Coordinating Codex checkpoint', 'greprag-codex-hook')],
|
|
1136
|
+
};
|
|
1137
|
+
if (!hasGrepragHook(config.hooks.PostToolUse, 'codex-posttooluse')) {
|
|
1138
|
+
if (!config.hooks.PostToolUse)
|
|
1139
|
+
config.hooks.PostToolUse = [];
|
|
1140
|
+
config.hooks.PostToolUse.push(checkpointHook);
|
|
1141
|
+
changes.push('Added Codex PostToolUse hook (successful checkpoint coordination)');
|
|
1142
|
+
}
|
|
1143
|
+
else {
|
|
1144
|
+
changes.push('Codex PostToolUse checkpoint hook already configured (skipped)');
|
|
1145
|
+
}
|
|
1133
1146
|
const permissionHook = {
|
|
1134
1147
|
matcher: '',
|
|
1135
1148
|
hooks: [commandHook('codex-permission-context', 3, 'Loading GrepRAG approval context')],
|
|
@@ -46,7 +46,7 @@ exports.OPENCODE_CHIP_SPAWN_POINTER = [
|
|
|
46
46
|
/** POINTER — Codex Desktop's native chip path. This is intentionally distinct
|
|
47
47
|
* from Claude Code spawn_task: different lifecycle, runtime, and handoff. */
|
|
48
48
|
exports.CODEX_CHIP_SPAWN_POINTER = [
|
|
49
|
-
'[greprag Codex delegation —
|
|
49
|
+
'[greprag Codex delegation — 1–2-chip quick path with the initiator as LEAD, or a separate LEAD for larger/seamed missions.]',
|
|
50
50
|
'• About to delegate a Codex task? → run `greprag load codex-chip-spawn` FIRST. Use exact first-line titles `LEAD: <Mission>`, `Chip A/B/C: <Specific Purview>`, and `FIX: [type] <one friction unit>`. Chips are ordinary writable native tasks; completion is a native Codex task reply to the LEAD after committing. A `FIX:` task loads `greprag load mechanic` first.',
|
|
51
51
|
].join('\n');
|
|
52
52
|
exports.loadPrimerModule = {
|
package/dist/commands/load.js
CHANGED
|
@@ -73,10 +73,6 @@ const LIBRARY = {
|
|
|
73
73
|
files: ['skill/templates/codex-chip-spawn.md'],
|
|
74
74
|
purpose: 'Spawn an independent writable native Codex Desktop task with an isolated worktree and native completion/cleanup.',
|
|
75
75
|
},
|
|
76
|
-
'codex-subagent-spawn': {
|
|
77
|
-
files: ['skill/templates/codex-subagent-spawn.md'],
|
|
78
|
-
purpose: 'Use bounded ephemeral Codex subagents inside the current session without a visible task, worktree, manifest, inbox identity, or goal.',
|
|
79
|
-
},
|
|
80
76
|
'skill-change': {
|
|
81
77
|
files: ['skill/templates/skill-change.md'],
|
|
82
78
|
purpose: 'Internal bundled schema for safely updating a skill after a run: when to edit, Convention A/B shapes, and when to propose instead.',
|
|
@@ -432,7 +428,8 @@ async function runLoad(args) {
|
|
|
432
428
|
return;
|
|
433
429
|
console.error(`Unknown load entry: ${name}\n`);
|
|
434
430
|
await printCatalog();
|
|
435
|
-
process.
|
|
431
|
+
process.exitCode = 1;
|
|
432
|
+
return;
|
|
436
433
|
}
|
|
437
434
|
const bodies = [];
|
|
438
435
|
for (const file of entry.files) {
|
|
@@ -148,8 +148,9 @@ function buildFixMission(friction, scope, parentSession, type = inferFixType(fri
|
|
|
148
148
|
'1. `greprag load mechanic`',
|
|
149
149
|
...workspace.setup,
|
|
150
150
|
'4. Read AGENTS.md and the session-start recap, then inspect the current repository state.',
|
|
151
|
-
'5. Bootstrap this checkout before build/test: if `scripts/
|
|
152
|
-
'6.
|
|
151
|
+
'5. Bootstrap this checkout before build/test: if `scripts/worktree-bootstrap.cjs` exists, run `node scripts/worktree-bootstrap.cjs`; if only `scripts/ensure-npm-deps.cjs` exists, run `node scripts/ensure-npm-deps.cjs`. Never link or junction `node_modules` to another checkout.',
|
|
152
|
+
'6. When running build/test or other env-driven commands, use `node scripts/codex-run.cjs -- <command ...>` if that wrapper exists. It loads ignored env files from the main checkout; never copy or print secrets.',
|
|
153
|
+
'7. Reproduce the friction before changing anything.',
|
|
153
154
|
'',
|
|
154
155
|
'**Repair contract**',
|
|
155
156
|
`- ${workspace.work}`,
|
|
@@ -24,7 +24,7 @@ function buildOsPrimer(env) {
|
|
|
24
24
|
'[grepragOS — the operating laws. Full doctrine: `greprag load os`.]',
|
|
25
25
|
'• Doctrine vs state: methods ship in the CLI (`greprag load`); live state lives in the repo. A skill that depends on repo state carries a "STATE — read these first" block naming exact paths.',
|
|
26
26
|
'• Discoverability: every durable artifact must be findable next session — docs auto-register, skills auto-mirror, decisions get a dated ADR/decision-log entry, everything else gets its path named in the owning skill/doc. If nothing points at it, you didn\'t finish.',
|
|
27
|
-
'• Pull before derive: `greprag memory search` / `corpus search` / `load` BEFORE asking the operator or re-deriving what the project already knows. Named person/org/project/repo/customer/handle or unexplained proper noun → search Memory before guessing, unless fully defined in-turn.',
|
|
27
|
+
'• Pull before derive: `greprag memory search` / `corpus search` / `load` BEFORE asking the operator or re-deriving what the project already knows. Env/toolchain/worktree/secret bootstrap roadblock → search Memory for the exact error and repo/tool before inventing a workaround. Named person/org/project/repo/customer/handle or unexplained proper noun → search Memory before guessing, unless fully defined in-turn.',
|
|
28
28
|
`• Friction ⇒ fix NOW: type by durable repair surface (\`harness|doctrine|injection|env|code\`) ⇒ \`greprag fix spawn --type <type> "<unit>"\`. It PRINTS a fix-chip mission — YOU then create the visible child task with that mission as its first message (how: \`greprag load ${spawnEntry}\`, or your harness's native task tool). Repo write = isolated worktree; data-only row/diagnosis = no repo write. One unit per chip; the chip fixes, verifies, checkpoints, and hands it to the mission delivery owner. Never queue friction.`,
|
|
29
29
|
'• Teach the system, not the chat: explained twice by the operator ⇒ it belongs in a skill / load entry / STATE block / ADR, not the conversation.',
|
|
30
30
|
].join('\n');
|
|
@@ -1752,7 +1752,7 @@ function buildOsPrimer(env) {
|
|
|
1752
1752
|
"[grepragOS \u2014 the operating laws. Full doctrine: `greprag load os`.]",
|
|
1753
1753
|
'\u2022 Doctrine vs state: methods ship in the CLI (`greprag load`); live state lives in the repo. A skill that depends on repo state carries a "STATE \u2014 read these first" block naming exact paths.',
|
|
1754
1754
|
"\u2022 Discoverability: every durable artifact must be findable next session \u2014 docs auto-register, skills auto-mirror, decisions get a dated ADR/decision-log entry, everything else gets its path named in the owning skill/doc. If nothing points at it, you didn't finish.",
|
|
1755
|
-
"\u2022 Pull before derive: `greprag memory search` / `corpus search` / `load` BEFORE asking the operator or re-deriving what the project already knows. Named person/org/project/repo/customer/handle or unexplained proper noun \u2192 search Memory before guessing, unless fully defined in-turn.",
|
|
1755
|
+
"\u2022 Pull before derive: `greprag memory search` / `corpus search` / `load` BEFORE asking the operator or re-deriving what the project already knows. Env/toolchain/worktree/secret bootstrap roadblock \u2192 search Memory for the exact error and repo/tool before inventing a workaround. Named person/org/project/repo/customer/handle or unexplained proper noun \u2192 search Memory before guessing, unless fully defined in-turn.",
|
|
1756
1756
|
`\u2022 Friction \u21D2 fix NOW: type by durable repair surface (\`harness|doctrine|injection|env|code\`) \u21D2 \`greprag fix spawn --type <type> "<unit>"\`. It PRINTS a fix-chip mission \u2014 YOU then create the visible child task with that mission as its first message (how: \`greprag load ${spawnEntry}\`, or your harness's native task tool). Repo write = isolated worktree; data-only row/diagnosis = no repo write. One unit per chip; the chip fixes, verifies, checkpoints, and hands it to the mission delivery owner. Never queue friction.`,
|
|
1757
1757
|
"\u2022 Teach the system, not the chat: explained twice by the operator \u21D2 it belongs in a skill / load entry / STATE block / ADR, not the conversation."
|
|
1758
1758
|
].join("\n");
|
|
@@ -1827,7 +1827,7 @@ var OPENCODE_CHIP_SPAWN_POINTER = [
|
|
|
1827
1827
|
"\u2022 Delegating a component of a plan to an isolated chip session, or `greprag fix spawn` just printed a FIX-chip mission? \u2192 run `greprag load chip-bootloader` FIRST for the method: OpenCode chips spawn natively via `greprag opencode chip goal create` + `greprag opencode chip spawn` (HTTP child session; manual paste only when the API is down). \u22652 chips at one objective \u2192 `greprag load chip-leader-opencode` BEFORE the first spawn."
|
|
1828
1828
|
].join("\n");
|
|
1829
1829
|
var CODEX_CHIP_SPAWN_POINTER = [
|
|
1830
|
-
"[greprag Codex delegation \u2014
|
|
1830
|
+
"[greprag Codex delegation \u2014 1\u20132-chip quick path with the initiator as LEAD, or a separate LEAD for larger/seamed missions.]",
|
|
1831
1831
|
"\u2022 About to delegate a Codex task? \u2192 run `greprag load codex-chip-spawn` FIRST. Use exact first-line titles `LEAD: <Mission>`, `Chip A/B/C: <Specific Purview>`, and `FIX: [type] <one friction unit>`. Chips are ordinary writable native tasks; completion is a native Codex task reply to the LEAD after committing. A `FIX:` task loads `greprag load mechanic` first."
|
|
1832
1832
|
].join("\n");
|
|
1833
1833
|
var loadPrimerModule = {
|
package/package.json
CHANGED
package/skill/greprag/SKILL.md
CHANGED
|
@@ -148,6 +148,8 @@ Aliases (silent back-compat): `greprag memory briefing` → `recap` (renamed v5.
|
|
|
148
148
|
|
|
149
149
|
**Codex/Windows: ABOUT TO VALIDATE WITH NONTRIVIAL `node -e` JAVASCRIPT? STOP — write the code to a temporary `.cjs` file and run `node <file>`.** PowerShell parses the command before Node sees it; regex lookarounds, `$1`, pipes, nested quotes, and semicolons can be split or expanded before Node runs. Keep `node -e` only for tiny quote-free probes.
|
|
150
150
|
|
|
151
|
+
**Codex/Windows: ABOUT TO CLEAN A GENERATED `dist` DIRECTORY? STOP — run `greprag codex clean-generated <path-to-dist>` instead of inline `Remove-Item -Recurse`.** Codex's native command launcher can reject free-form recursive delete text before PowerShell executes your path checks; the GrepRAG command resolves the `dist` path, requires a Git-root or explicit `--under` bound, rejects symlink/repo-metadata targets, and removes only that checked generated directory.
|
|
152
|
+
|
|
151
153
|
**Codex messaging has one simple contract.** Discover Codex tasks with `codex_app.list_threads` unfiltered first, scope by cwd, then coordinate Codex-to-Codex with `codex_app.send_message_to_thread`; `query` may narrow only after cwd scoping. `greprag send` is the durable cross-harness inbox rail and fallback queue; it does not by itself prove that an idle Codex task woke or acted. Public installs use `greprag init --codex --tenant-id <handle>` and Codex hooks surface queued inbox rows at SessionStart/UserPromptSubmit boundaries. There is no Codex startup watcher to install. A stored row, completed user-only turn, app-server `turn/start` / `turn/steer`, or `codex exec resume` is not proof of agent action. Only the recipient's actual peer response proves delivery.
|
|
152
154
|
|
|
153
155
|
**ABOUT TO `greprag send` TO A `@gmail.com` / `@anthropic.com` / REAL EMAIL ADDRESS? STOP — for `inbox`/`send` (internal cross-session messaging), `users.email` IS NEVER A ROUTING ADDRESS.** Use the numeric handle (`1834729@greprag.com`) or claimed vanity alias (`travis@greprag.com`). If you don't know the recipient's handle, ASK — don't guess from their email. adr: adr/numeric-handles.md. Full grammar: `docs/inbox.md § address`.
|
|
@@ -158,7 +160,7 @@ Aliases (silent back-compat): `greprag memory briefing` → `recap` (renamed v5.
|
|
|
158
160
|
|
|
159
161
|
- `docs/setup.md` — codex · claude-code · opencode · auth · hooks · conventions · permissions · channels · anchor · bulk-register
|
|
160
162
|
- `docs/platforms.md` — exact platform paths for Claude Code · Codex · OpenCode
|
|
161
|
-
- `docs/codex-chip.md` — Codex
|
|
163
|
+
- `docs/codex-chip.md` — Codex quick-chip, Leader, reporting, and cleanup shape
|
|
162
164
|
- `docs/per-project-flags.md` — flip `memory_capture` / `session_start_recap` / `inbox_notify`
|
|
163
165
|
- `docs/inbox.md` — `greprag send`, `greprag inbox`, address grammar, retract (internal messaging)
|
|
164
166
|
- `docs/email.md` — `greprag email send`/`pending`/`pull`/`boxes`/`domain` — REAL SMTP: send-as custom domains, segregated mailboxes (distinct from `send`)
|
|
@@ -2,14 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
Use `greprag load codex-chip-spawn` for the Codex block recipe:
|
|
4
4
|
|
|
5
|
-
- internal same-session subagent (`max_threads=6`, `max_depth=1`; no separate
|
|
6
|
-
worktree, manifest, inbox, or goal) uses `greprag load codex-subagent-spawn`;
|
|
7
5
|
- quick mode: rename the current task `LEAD: <Mission>` and directly spawn
|
|
8
6
|
1–2 visible `Chip A/B: <Specific Purview>` worktree tasks;
|
|
9
7
|
- Leader mode: rename the current task `PLANNER: <Mission>`, then create a
|
|
10
8
|
separate `LEAD: <Mission>` task before that LEAD spawns
|
|
11
9
|
`Chip A/B/C: <Specific Purview>` children for seams or larger orchestration.
|
|
12
10
|
|
|
11
|
+
Same-session subagents are native Codex behavior, not GrepRAG chip doctrine.
|
|
12
|
+
Create visible chips with native `codex_app__create_thread`: `target.type =
|
|
13
|
+
project`, the current `projectId`, a Codex `worktree` environment with
|
|
14
|
+
`startingState: { type: "branch", branchName: "<prepared chip branch>" }`,
|
|
15
|
+
plus top-level `model` and `thinking` from `greprag codex models show`.
|
|
16
|
+
|
|
13
17
|
Normal chips are writable and own discovery, design, implementation, tests, and
|
|
14
18
|
commit. Preserve the Codex-provided worktree, committed result artifact, and
|
|
15
19
|
parent cleanup. The child opening prompt starts with the exact visible title
|
|
@@ -28,6 +32,10 @@ means the child archives its own Codex task; `Archive: no` leaves it open. The
|
|
|
28
32
|
lead remains responsible for integration and post-merge branch bookkeeping,
|
|
29
33
|
not routine child-task archival.
|
|
30
34
|
Review is a separate explicit review chip/session when the lead asks for it.
|
|
35
|
+
If the repo ships `scripts/codex-run.cjs`, children use
|
|
36
|
+
`node scripts/codex-run.cjs -- <command ...>` for build/test/env-driven
|
|
37
|
+
commands so ignored `.env`, `.env.local`, `.dev.vars`, and package-level env
|
|
38
|
+
files are read from the main checkout without copying or printing secrets.
|
|
31
39
|
FIX landing (adr/codex-landing-doctrine.md): a mission whose first line
|
|
32
40
|
begins `FIX:` (from `greprag fix spawn`) uses the handoff's detected
|
|
33
41
|
`workspaceMode`. Usable Git history selects an isolated worktree; non-Git,
|
package/skill/mechanic/SKILL.md
CHANGED
|
@@ -97,8 +97,8 @@ the Codex-provided checkout: bundled load entries, skill templates, docs, hook
|
|
|
97
97
|
context, CLI messages, and tests that teach agents how to use the harness.
|
|
98
98
|
Inspect Codex behavior only far enough to correct those GrepRAG surfaces or to
|
|
99
99
|
report a precise external blocker. Codex owns native task creation, worktrees,
|
|
100
|
-
permissions, Git, and task lifecycle. Do not create another child
|
|
101
|
-
|
|
100
|
+
permissions, Git, and task lifecycle. Do not create another child unless the
|
|
101
|
+
parent explicitly changes that assignment.
|
|
102
102
|
Landing (adr/codex-landing-doctrine.md): a `MECHANIC: <Mission>` or
|
|
103
103
|
`FIX: <friction>` chip replies to its LEAD with the commit, exact friction,
|
|
104
104
|
change, reason, checks, and cleanup parameters. The LEAD is the delivery owner
|
|
@@ -113,8 +113,7 @@ project worktree or local target. For 1–2 children the current
|
|
|
113
113
|
task is the implicit LEAD; for more than two children or shared seams, load
|
|
114
114
|
`chip-leader` and create a separate `LEAD: <Mission>` that dispatches exact
|
|
115
115
|
`Chip A/B/C: <Specific Purview>` tasks.
|
|
116
|
-
|
|
117
|
-
never satisfies a visible-chip requirement.
|
|
116
|
+
Native same-session helpers never satisfy a visible-chip requirement.
|
|
118
117
|
|
|
119
118
|
ABOUT TO answer a Mechanic peer who offers to coordinate, integrate, rework, or
|
|
120
119
|
take over a harness repair? STOP — hand off the repair state: commit/branch,
|
|
@@ -1,95 +1,102 @@
|
|
|
1
1
|
# Codex Chip Spawn Method
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
`create_goal`, verifies it with `get_goal`, then fans out children. PLANNER is
|
|
33
|
-
a handoff role: after briefing the LEAD it goes quiet until completion,
|
|
34
|
-
blocker, explicit decision request, or operator intervention.
|
|
35
|
-
|
|
36
|
-
## Workspace selection and project preflight
|
|
37
|
-
|
|
38
|
-
Standard writable chips use the current project with
|
|
39
|
-
`environment: { "type": "worktree" }`. For a FIX chip, run
|
|
40
|
-
`greprag fix spawn` in the source project and honor its top-level
|
|
41
|
-
`workspaceMode` without a fail-then-fallback attempt:
|
|
42
|
-
|
|
43
|
-
- `workspaceMode=worktree`: use the project worktree target. Before the call,
|
|
44
|
-
check the saved project/main repo for `.codex/environments/environment.toml`.
|
|
45
|
-
If missing, stop and set up the repo first with the `codex-environments`
|
|
46
|
-
skill.
|
|
47
|
-
- `workspaceMode=local`: use the project local target. The source has no usable
|
|
48
|
-
Git HEAD, so do not initialize Git, invoke `codex-environments`, or request a
|
|
49
|
-
worktree. This is the project-local task path with serialized writes: the
|
|
50
|
-
caller yields file writes until the FIX chip reports back.
|
|
51
|
-
- Non-FIX writable chips remain worktree-only.
|
|
52
|
-
- Missing for `PLANNER` or `ADVISOR` consultation: local/projectless fallback
|
|
53
|
-
is allowed only when the prompt explicitly forbids writes and no child
|
|
54
|
-
worktree dispatch happens until the repo environment exists.
|
|
55
|
-
|
|
56
|
-
## Dispatch
|
|
57
|
-
|
|
58
|
-
Call `codex_app__create_thread` once as a standalone tool call:
|
|
3
|
+
Codex has no Claude Code `pre-spawn-check` validator over `spawn_task`. The
|
|
4
|
+
agent writes the exact first-line title + Block 1 + task body + Block 2 into
|
|
5
|
+
the prompt itself, then dispatches exactly once with
|
|
6
|
+
`codex_app__create_thread`. Codex task creation proves dispatch only; the
|
|
7
|
+
child's native `IN-FLIGHT` reply proves launch/setup.
|
|
8
|
+
|
|
9
|
+
> **Part of a multi-chip mission?** If this chip is one of ≥2 aimed at a
|
|
10
|
+
> single objective, you should already be inside a chip-leader plan — your
|
|
11
|
+
> **base branch** and **merge target** (the integration branch, *never* master)
|
|
12
|
+
> come from it. If you're not, stop and run `greprag load chip-leader` first.
|
|
13
|
+
> A lone chip targeting its own objective proceeds here directly.
|
|
14
|
+
|
|
15
|
+
## What the agent provides
|
|
16
|
+
|
|
17
|
+
- `title: "Chip A: <verb-phrase>"` — exact first prompt line. Use the
|
|
18
|
+
leader-assigned label (`A`/`B`/`C`...) per workstream, for example
|
|
19
|
+
`"Chip B: Build freshness engine"`. The label is the shared handle the
|
|
20
|
+
leader and chip both use end-to-end (title -> report-back self-ID -> merge
|
|
21
|
+
references). Dedicated orchestration titles are exact too: `PLANNER:
|
|
22
|
+
<Mission>`, `LEAD: <Mission>`, `ADVISOR: <Purview>`, and `FIX:
|
|
23
|
+
[type] <one friction unit>`.
|
|
24
|
+
- `prompt:` — exact title line + Block 1 + task body + Block 2 (templates
|
|
25
|
+
below).
|
|
26
|
+
- The first-line title also selects the model slot:
|
|
27
|
+
`Chip A/B/C` -> `chip.worker`, `LEAD` -> `chip.leader`, `PLANNER` ->
|
|
28
|
+
`chip.planner`, `ADVISOR` -> `chip.advisor`, `FIX` -> `chip.fix`.
|
|
29
|
+
- `target:` — Codex project target. Writable worktree chips must include the
|
|
30
|
+
prepared branch as `startingState`; this is the required Codex parameter
|
|
31
|
+
Claude does not have:
|
|
59
32
|
|
|
60
33
|
```json
|
|
61
34
|
{
|
|
62
35
|
"target": {
|
|
63
36
|
"type": "project",
|
|
64
37
|
"projectId": "<current-project-id>",
|
|
65
|
-
"environment": {
|
|
38
|
+
"environment": {
|
|
39
|
+
"type": "worktree",
|
|
40
|
+
"startingState": { "type": "branch", "branchName": "<prepared chip branch>" }
|
|
41
|
+
}
|
|
66
42
|
},
|
|
67
|
-
"prompt": "<Block 1 + Task + Block 2>",
|
|
43
|
+
"prompt": "<exact title + Block 1 + Task + Block 2>",
|
|
68
44
|
"model": "<selected role model>",
|
|
69
45
|
"thinking": "<selected role effort>"
|
|
70
46
|
}
|
|
71
47
|
```
|
|
72
48
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
inspect candidates with `read_thread`, and retry only after proving no matching
|
|
76
|
-
task exists.
|
|
49
|
+
- `model:` / `thinking:` — select with `greprag codex models show`; pass them
|
|
50
|
+
top-level in `codex_app__create_thread`, not by relying on Desktop defaults.
|
|
77
51
|
|
|
78
|
-
|
|
52
|
+
`workspaceMode=local` FIX tasks keep the same required Codex shape but use the
|
|
53
|
+
project-local environment and omit `startingState`:
|
|
79
54
|
|
|
80
|
-
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"target": {
|
|
58
|
+
"type": "project",
|
|
59
|
+
"projectId": "<current-project-id>",
|
|
60
|
+
"environment": { "type": "local" }
|
|
61
|
+
},
|
|
62
|
+
"prompt": "<exact title + Block 1 + Task + Block 2>",
|
|
63
|
+
"model": "<selected role model>",
|
|
64
|
+
"thinking": "<selected role effort>"
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Codex has no `mode: interactive` create-thread field. If the chip must pause
|
|
69
|
+
for human input, put that requirement in the task body and make the child
|
|
70
|
+
report `BLOCKED` with the decision needed.
|
|
71
|
+
|
|
72
|
+
## Block 1 — Setup (verbatim, substitute `<exact-title>`, `<branch>` + mode)
|
|
73
|
+
|
|
74
|
+
`<exact-title>` = the first prompt line. `<branch>` = the prepared chip branch
|
|
75
|
+
used in `startingState.branchName`. `workspaceMode` comes from the dispatch
|
|
76
|
+
path; standard chips and `workspaceMode=worktree` FIX chips are already in a
|
|
77
|
+
Codex worktree environment.
|
|
78
|
+
|
|
79
|
+
````
|
|
80
|
+
**Setup — do this FIRST:**
|
|
81
81
|
|
|
82
82
|
```text
|
|
83
83
|
## Setup - do this FIRST
|
|
84
|
-
Stay in the selected workspace and inspect the current
|
|
84
|
+
Stay in the Codex-provided selected workspace and inspect the current
|
|
85
|
+
repository state.
|
|
85
86
|
Applicable AGENTS.md instructions and the session-start recap are already in
|
|
86
|
-
context.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
87
|
+
context.
|
|
88
|
+
Do not create another worktree. Standard chips and `workspaceMode=worktree`
|
|
89
|
+
FIX chips are already in the Codex worktree environment created from
|
|
90
|
+
`startingState.branchName`. A `workspaceMode=local` FIX stays in the project
|
|
91
|
+
directory, never initializes Git, never requests a worktree, and requires the
|
|
92
|
+
caller to yield file writes until the FIX chip reports back.
|
|
93
|
+
Bootstrap this checkout before build/test: if `scripts/worktree-bootstrap.cjs`
|
|
94
|
+
exists, run `node scripts/worktree-bootstrap.cjs`; if only
|
|
95
|
+
`scripts/ensure-npm-deps.cjs` exists, run `node scripts/ensure-npm-deps.cjs`.
|
|
96
|
+
Never link or junction `node_modules` to another checkout.
|
|
97
|
+
When running build/test or other env-driven commands, use
|
|
98
|
+
`node scripts/codex-run.cjs -- <command ...>` if that wrapper exists. It loads
|
|
99
|
+
ignored env files from the main checkout; never copy or print secrets.
|
|
93
100
|
After setup and bootstrap succeed, reply to the LEAD in the native Codex task
|
|
94
101
|
thread:
|
|
95
102
|
`IN-FLIGHT: <exact title> — setup complete; work started`
|
|
@@ -111,25 +118,36 @@ the LEAD only: findings, questions, tradeoffs, and recommendations. Do not
|
|
|
111
118
|
write operator-facing completion language or decide/spawn worker chips.
|
|
112
119
|
```
|
|
113
120
|
|
|
114
|
-
|
|
121
|
+
The `IN-FLIGHT` reply is non-negotiable — without it the parent assumes the
|
|
122
|
+
Codex task exists but was not successfully launched.
|
|
115
123
|
|
|
116
|
-
|
|
124
|
+
---
|
|
125
|
+
````
|
|
126
|
+
|
|
127
|
+
**Multi-chip mission (`greprag load chip-leader`)?** The first-line title alone
|
|
128
|
+
is not enough because Codex can auto-title before the child is renamed. The
|
|
129
|
+
parent or LEAD must set the exact registry/task title immediately after the
|
|
130
|
+
task appears, then read it back twice before treating the title as durable:
|
|
117
131
|
|
|
118
132
|
```text
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
Relevant files/contracts: <starting points; child still owns discovery>
|
|
123
|
-
Constraints and prior decisions: <invariants that must survive>
|
|
124
|
-
Seams and integration order: <shared contracts/order, or none>
|
|
125
|
-
Acceptance: <checks/evidence that mean done>
|
|
126
|
-
Own repository discovery, design, implementation, tests, and commit; do not
|
|
127
|
-
wait for a parent-authored implementation plan.
|
|
133
|
+
set_thread_title "<exact-title>"
|
|
134
|
+
read_thread -> exact title
|
|
135
|
+
read_thread -> exact title again after the retry delay
|
|
128
136
|
```
|
|
129
137
|
|
|
130
|
-
|
|
138
|
+
The leader dictates the exact string (for example `Chip A: Converter format
|
|
139
|
+
coverage`). Single chips still use the exact title, but skip leader-assigned
|
|
140
|
+
registry retitle planning.
|
|
141
|
+
|
|
142
|
+
## Block 2 — Report back (verbatim, substitute `<branch>` + LEAD task)
|
|
131
143
|
|
|
132
|
-
|
|
144
|
+
Use the native Codex parent-child task-message channel for Codex-to-Codex
|
|
145
|
+
completion. Do not substitute `greprag send` for normal Codex child reports.
|
|
146
|
+
|
|
147
|
+
````
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
**Block 2 — Report back via native Codex task reply:**
|
|
133
151
|
|
|
134
152
|
```text
|
|
135
153
|
## Report when done
|
|
@@ -161,45 +179,72 @@ worktree pruning. If review is needed, the parent creates a fresh review
|
|
|
161
179
|
chip/session.
|
|
162
180
|
```
|
|
163
181
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
182
|
+
**Cleanup discipline (HARD RULE):** chip prompts forbid `git clean`,
|
|
183
|
+
`git reset --hard`, `git checkout <other>`, raw recursive delete outside the
|
|
184
|
+
selected workspace, manual worktree deletion, or manual Codex managed-checkout
|
|
185
|
+
pruning.
|
|
186
|
+
````
|
|
187
|
+
|
|
188
|
+
## After spawning — wait for native IN-FLIGHT (HARD RULE)
|
|
189
|
+
|
|
190
|
+
The chip reports back to the LEAD through native Codex task replies. Nothing
|
|
191
|
+
else proves it launched correctly: `create_thread` success proves only that
|
|
192
|
+
Codex accepted the dispatch. So immediately after `codex_app__create_thread`
|
|
193
|
+
returns, resolve the visible task, set the exact title, read it back twice, and
|
|
194
|
+
wait for:
|
|
195
|
+
|
|
196
|
+
```text
|
|
197
|
+
IN-FLIGHT: <exact-title> — setup complete; work started
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
If `create_thread` returns a generic/transport failure, treat it as ambiguous
|
|
201
|
+
success. Do not call `create_thread` again until recovery checks prove no
|
|
202
|
+
existing task exists: use `list_threads` for the expected title or manifest id,
|
|
203
|
+
inspect candidates with `read_thread`, and recover a matching visible task
|
|
204
|
+
before retrying.
|
|
205
|
+
|
|
206
|
+
Use native Codex task replies for Codex-to-Codex reporting. Use `greprag send`
|
|
207
|
+
only for explicit cross-harness or fallback coordination; a stored GrepRAG row
|
|
208
|
+
is not proof that an idle Codex task woke or acted.
|
|
209
|
+
|
|
210
|
+
**Launch state:** the Block 1 `IN-FLIGHT` reply is your only signal the child
|
|
211
|
+
actually entered its selected workspace and completed setup. No `IN-FLIGHT` =
|
|
212
|
+
assume the task is not launched, blocked, or not yet set up — don't wait on
|
|
213
|
+
results from a chip that never started.
|
|
214
|
+
|
|
215
|
+
## Before composing
|
|
216
|
+
|
|
217
|
+
`greprag fix list --repaired --scope chip-startup --limit 20 --project <chip-project> --format markdown` — already scoped, no slicing. If non-empty, paste at top of body as `**Project Fixes (do not re-discover):**`. Do not use `fix search` for this pull.
|
|
218
|
+
|
|
219
|
+
## Merge before testing globally (HARD RULE)
|
|
220
|
+
|
|
221
|
+
Chips never `npm link` from the worktree — dangling symlinks silently break the
|
|
222
|
+
CLI everywhere. To test a built CLI globally: merge through the repo delivery
|
|
223
|
+
path first, then install from the main checkout.
|
|
224
|
+
|
|
225
|
+
## Parent merge discipline — cleanup after integration (HARD RULE)
|
|
226
|
+
|
|
227
|
+
When you (the parent) integrate a Codex chip branch — through the canonical
|
|
228
|
+
commit path or a profile-declared merge — clear the Codex chip bookkeeping in
|
|
229
|
+
the same breath after the child's `Archive: yes` report and merge:
|
|
198
230
|
|
|
199
231
|
```bash
|
|
200
232
|
greprag codex chip cleanup <id> --native-archived
|
|
201
233
|
```
|
|
202
234
|
|
|
203
235
|
The child archives its own task after sending `Archive: yes`; the parent does
|
|
204
|
-
not perform routine child-task archival.
|
|
205
|
-
|
|
236
|
+
not perform routine child-task archival. The parent may delete the branch after
|
|
237
|
+
merge. Codex owns managed-worktree pruning, and the cleanup command records the
|
|
238
|
+
archive-safe attestation before removing managed checkout state. Local-mode FIX
|
|
239
|
+
tasks have no worktree or branch to prune.
|
|
240
|
+
|
|
241
|
+
**FIX chips use the same delivery owner.** A `greprag fix spawn` mission is the
|
|
242
|
+
source of truth for FIX behavior. `fix spawn` detects usable Git history and
|
|
243
|
+
emits `workspaceMode`: Git uses an isolated worktree; non-Git, unavailable
|
|
244
|
+
Git, or no commit uses the project-local task with serialized writes. Dispatch
|
|
245
|
+
honors that mode without trying a worktree first. The FIX chip identifies the
|
|
246
|
+
exact friction, makes the smallest durable root-cause fix, verifies and
|
|
247
|
+
checkpoints it, then reports the commit/result and cleanup parameters to the
|
|
248
|
+
parent delivery owner. It creates no human landing gate. If no live parent
|
|
249
|
+
exists and the chip carries the full-goal mission, it becomes delivery owner
|
|
250
|
+
and follows the repo profile.
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# Codex Internal Subagent
|
|
2
|
-
|
|
3
|
-
Use an internal subagent for ephemeral, same-session work: a bounded research
|
|
4
|
-
pass, comparison, review, edit, or test whose result can return directly to the
|
|
5
|
-
current task.
|
|
6
|
-
|
|
7
|
-
## Contract
|
|
8
|
-
|
|
9
|
-
- Load this method with `greprag load codex-subagent-spawn` when the shape is
|
|
10
|
-
not already in context.
|
|
11
|
-
- The subagent is ephemeral and same-session. It has no visible worktree task,
|
|
12
|
-
durable manifest, inbox identity, or goal.
|
|
13
|
-
- Keep concurrency at `max_threads=6` and recursion at `max_depth=1`.
|
|
14
|
-
- Give it one specific question or purview and ask for a compact result with
|
|
15
|
-
evidence. `fast_scan` is read-only; `routine_worker` and `deep_worker` may
|
|
16
|
-
perform bounded edits/tests in the parent workspace.
|
|
17
|
-
- Use the configured model slots: `subagent.fast_scan`, `subagent.routine_worker`,
|
|
18
|
-
and `subagent.deep_worker`. Inspect them with `greprag codex models show`.
|
|
19
|
-
- The parent prevents overlapping concurrent edits and owns the final judgment,
|
|
20
|
-
integration, and any commit that should outlive the session.
|
|
21
|
-
- Do not use it for independent worktree isolation, parent-visible lifecycle
|
|
22
|
-
reporting, or work that must outlive the session; choose a quick chip instead.
|
|
23
|
-
|
|
24
|
-
## Compact brief
|
|
25
|
-
|
|
26
|
-
```text
|
|
27
|
-
Subagent purview: <one bounded question>
|
|
28
|
-
Context: <the files or facts it may inspect>
|
|
29
|
-
Return: <decision / findings / recommended next step>
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
Internal subagents do not need `greprag send`; their result is returned to the
|
|
33
|
-
initiating task. If you need a visible child identity, report, or cleanup
|
|
34
|
-
boundary, stop using this primitive and load `codex-chip-spawn`.
|