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.
@@ -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
+ }
@@ -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 an internal subagent.', '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. Never use `multi_agent_v1__spawn_agent` for a visible chip.');
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
  }
@@ -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 an isolated worktree and starting branch. The standalone CLI does
19
- not create the Desktop task itself. The active topology is an implicit LEAD for
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/ensure-npm-deps.cjs\` exists, run \`node scripts/ensure-npm-deps.cjs\`; if \`scripts/worktree-bootstrap.cjs\` exists, run \`node scripts/worktree-bootstrap.cjs\`. Never link or junction \`node_modules\` to another checkout.
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
  }
@@ -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). */
@@ -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(' Start a fresh Codex session, then open Settings -> Settings -> Hooks and trust the GrepRAG hook definitions.');
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(' Memory hooks will activate on your next Codex session.\n');
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 — internal subagent, 1–2-chip quick path with the initiator as LEAD, or a separate LEAD for larger/seamed missions.]',
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 = {
@@ -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.exit(1);
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/ensure-npm-deps.cjs` exists, run `node scripts/ensure-npm-deps.cjs`; if `scripts/worktree-bootstrap.cjs` exists, run `node scripts/worktree-bootstrap.cjs`. Never link or junction `node_modules` to another checkout.',
152
- '6. Reproduce the friction before changing anything.',
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 internal subagent, 1\u20132-chip quick path with the initiator as LEAD, or a separate LEAD for larger/seamed missions.]",
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "greprag",
3
- "version": "5.74.8",
3
+ "version": "5.74.10",
4
4
  "description": "GrepRAG — agent memory for Claude Code, Codex, and OpenCode.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -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 subagent, quick-chip, Leader, reporting, and cleanup shape
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,
@@ -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 or use an
101
- internal subagent unless the parent explicitly changes that assignment.
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
- `multi_agent_v1__spawn_agent` is only an ephemeral same-session subagent and
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
- Use this for Codex visible child tasks. Claude-side `spawn_task` rules do not
4
- apply to Codex: Codex creates the task, selects its workspace, and provides the
5
- native parent-child reply channel.
6
-
7
- ## Roles and models
8
-
9
- The exact first-line title selects the governance and model slot:
10
-
11
- | Title | Purpose | Model slot |
12
- | --- | --- | --- |
13
- | `Chip A/B/C: <Specific Purview>` | Independent implementation worker | `chip.worker` |
14
- | `LEAD: <Mission>` | Own and integrate a multi-chip mission | `chip.leader` |
15
- | `PLANNER: <Mission>` | Create and brief a separate LEAD | `chip.planner` |
16
- | `ADVISOR: <Purview>` | Read-only consultation to the LEAD | `chip.advisor` |
17
- | `FIX: [harness\|doctrine\|injection\|env\|code] <one friction unit>` | Root-cause repair | `chip.fix` |
18
-
19
- Check active slots with `greprag codex models show`. Pass the selected slot as
20
- top-level `model` and `thinking` in `codex_app__create_thread`; do not rely on
21
- Codex Desktop defaults for a visible chip.
22
-
23
- ## Mode selection
24
-
25
- - 1-2 visible tasks: rename the current task `LEAD: <Mission>` and
26
- spawn `Chip A` / `Chip B` directly.
27
- - More chips or shared seams: rename the current task `PLANNER: <Mission>`,
28
- create a separate `LEAD: <Mission>` first, then that LEAD spawns children.
29
- - Bounded same-session work: use `greprag load codex-subagent-spawn` instead.
30
-
31
- A dedicated `LEAD: <Mission>` creates a native top-level goal with
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": { "type": "<worktree|local>" }
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
- Creation success proves dispatch, not successful startup. If the result is
74
- ambiguous, do not retry blindly: use `list_threads` for the expected title,
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
- ## Block 1 - Setup and startup acknowledgement
52
+ `workspaceMode=local` FIX tasks keep the same required Codex shape but use the
53
+ project-local environment and omit `startingState`:
79
54
 
80
- Paste this at the top of the child prompt after the title.
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 repository state.
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. Do not create another worktree; a `workspaceMode=local` FIX stays in
87
- the project directory and never initializes Git.
88
- Bootstrap this checkout before build/test: if `scripts/ensure-npm-deps.cjs`
89
- exists, run `node scripts/ensure-npm-deps.cjs`; if
90
- `scripts/worktree-bootstrap.cjs` exists, run
91
- `node scripts/worktree-bootstrap.cjs`. Never link or junction `node_modules` to
92
- another checkout.
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
- ## Task body
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
- Keep the actual work dominant:
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
- ## Task
120
- Outcome: <observable result>
121
- Problem and evidence: <failure, request, or proof motivating the work>
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
- ## Block 2 - Report back
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
- Paste this at the end of the child prompt.
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
- ## FIX contract
165
-
166
- For `FIX:` tasks, the mission printed by `greprag fix spawn` is the source of
167
- truth. The FIX chip keeps the existing route and carries its type in the title,
168
- for example `FIX: [doctrine] stale skill text sent Codex to Claude rules`.
169
- Type means durable repair surface: `harness` hooks/watchers/task dispatch,
170
- `doctrine` load entries/skills/rendered instructions, `injection`
171
- recap/Capture/doc-pointer/stateful injection, `env` bootstrap/deps/scripts, and
172
- `code` product/source behavior. It identifies the exact friction, makes the
173
- smallest durable root-cause fix, explains why it works, verifies and commits
174
- it, then hands it to the parent delivery owner.
175
-
176
- Removal comes first: remove offending doctrine, gates, controls, duplication,
177
- or wrong boundaries before adding guidance. Add prose or controls only when
178
- removal cannot solve the friction. Data-only repair rows and diagnosis do not
179
- require a writable task.
180
-
181
- ## After spawning
182
-
183
- - Wait for the child-confirmed native `IN-FLIGHT` reply; task creation alone
184
- does not prove setup/bootstrap succeeded.
185
- - In `workspaceMode=local`, yield parent file writes until the FIX chip reports
186
- back; both tasks share the same project directory.
187
- - Use native Codex parent-child task replies for Codex-to-Codex reporting.
188
- - Use `greprag send` only for explicit cross-harness or fallback coordination.
189
- - Contact same-project Codex peers through `codex_app.list_threads` scoped by
190
- `cwd`, then `codex_app.send_message_to_thread`. Coordination asks only about
191
- blockers, owned dirt, or sequencing constraints; peer review is a separate
192
- child task.
193
-
194
- ## Parent cleanup
195
-
196
- After integration, the parent may clear remaining GrepRAG manifest/branch
197
- bookkeeping with:
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. Codex owns managed-worktree pruning.
205
- Local-mode FIX tasks have no worktree or branch to prune.
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`.