greprag 5.74.7 → 5.74.9
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 +2 -2
- package/dist/codex-fast-hook.js +14 -1
- package/dist/commands/codex-chip/help.js +7 -6
- package/dist/commands/codex-chip/prompt.js +4 -4
- package/dist/commands/coordinate-gate.js +25 -0
- package/dist/commands/init.js +15 -2
- package/package.json +1 -1
- package/skill/greprag/docs/codex-chip.md +7 -7
- package/skill/templates/codex-chip-spawn.md +23 -17
|
@@ -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
|
@@ -64,9 +64,9 @@ function context(input) {
|
|
|
64
64
|
`Worktree: ${(0, model_1.chipExecutionPath)(chip)}`,
|
|
65
65
|
`Branch: ${chip.worktree.branch}`,
|
|
66
66
|
`Parent session: ${chip.parent.sessionId || 'not recorded'}`,
|
|
67
|
-
`Finish by committing the durable result
|
|
67
|
+
`Finish by committing the durable result, then send the parent the commit artifact, checks, caveats, Cleanup line, and Archive: yes|no in the actual native task message. After delivery, Archive: yes means archive this child task yourself. The optional host command is ${cli} codex chip report ${chip.id}.`,
|
|
68
68
|
// adr: adr/codex-landing-doctrine.md — one delivery owner, including FIX missions.
|
|
69
|
-
'Landing: the parent is the delivery owner for merge,
|
|
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
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.');
|
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));
|
|
@@ -21,11 +21,12 @@ quick chips, an explicit LEAD for multi-chip orchestration, and Chip A/B/C with
|
|
|
21
21
|
optional ADVISOR orientation. FIX missions are visible one-friction tasks from
|
|
22
22
|
\`greprag fix spawn\`: they select \`chip.fix\` and load mechanic doctrine.
|
|
23
23
|
Every role is an ordinary writable session; roles only orient the work. Native Codex chips commit their durable
|
|
24
|
-
result, then
|
|
25
|
-
hash, checks, caveats, cleanup parameters, and
|
|
26
|
-
\`
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
result, then use the native task-message channel to send the LEAD status,
|
|
25
|
+
commit hash, checks, caveats, cleanup parameters, and
|
|
26
|
+
\`Archive: yes\` or \`Archive: no — <reason>\`. The archive decision must be in
|
|
27
|
+
that sent message, not only the child's final response. After delivery,
|
|
28
|
+
\`Archive: yes\` means the child archives its own task; the parent integrates
|
|
29
|
+
the commit and handles post-merge branch bookkeeping. Peer review is a separate
|
|
30
|
+
explicit review chip/session when needed. The
|
|
30
31
|
\`greprag codex chip report\` command remains host bookkeeping for explicit
|
|
31
32
|
CLI-managed chips, not mandatory native Codex completion ceremony.`;
|
|
@@ -20,7 +20,7 @@ function chipPrompt(manifest, _cliCommand = 'greprag') {
|
|
|
20
20
|
? `- After setup and bootstrap succeed, reply to the LEAD in the native Codex task thread: \`IN-FLIGHT: ${(0, model_1.chipTitle)(manifest)} — setup complete; work started\`. If setup fails, reply \`BLOCKED\` with the exact failure instead.\n`
|
|
21
21
|
: '';
|
|
22
22
|
const reportInstruction = native
|
|
23
|
-
? '- Commit the durable result, then
|
|
23
|
+
? '- Commit the durable result, then use the native Codex task-message tool to send the LEAD `DONE` or `BLOCKED`, commit hash if any, checks, material caveats, cleanup parameters, and `Archive: yes` or `Archive: no — <reason>`. Do not substitute a final response in your own task.'
|
|
24
24
|
: '- Commit the completed durable result, including report-only artifacts, then run `greprag codex chip report <id> --summary "<result>" --check "<check>"`. The report must carry the commit artifact back to the parent.';
|
|
25
25
|
return `${(0, model_1.chipTitle)(manifest)}
|
|
26
26
|
|
|
@@ -37,7 +37,7 @@ ${manifest.task}
|
|
|
37
37
|
|
|
38
38
|
Report when done:
|
|
39
39
|
${reportInstruction}
|
|
40
|
-
- Include a \`Cleanup:\` line naming the
|
|
41
|
-
-
|
|
42
|
-
- Landing: do not independently merge, push, deploy, or delete the worktree — the parent is the delivery owner and integrates the result, follows the repo profile, and
|
|
40
|
+
- Include a \`Cleanup:\` line naming the task, worktree, and branch actions. When done use \`Cleanup: child archives own task; Codex may prune managed worktree; parent may delete branch after merge\`; when anything must remain open use \`Cleanup: keep task/worktree/branch because ...\`.
|
|
41
|
+
- Put the archive decision in the actual message sent to the LEAD: \`Archive: yes\` or \`Archive: no — <reason>\`. After that message is delivered, \`Archive: yes\` means call \`set_thread_archived\` for your own task; \`Archive: no\` means leave it open. Never make the parent perform routine child-task archival.
|
|
42
|
+
- Landing: do not independently merge, push, deploy, or manually delete the worktree — the parent is the delivery owner and integrates the result, follows the repo profile, and deletes the branch after merge. If this task begins \`FIX:\` (a fix-spawn mission), hand the verified checkpoint to that owner without a human approval gate. If no live parent exists and this task carries the full-goal mission, become delivery owner. \`greprag fix spawn\` only prints the mission; visible Codex task dispatch creates the isolated checkout/worktree.`;
|
|
43
43
|
}
|
|
@@ -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')],
|
package/package.json
CHANGED
|
@@ -20,13 +20,13 @@ child sends the native parent-task reply
|
|
|
20
20
|
`IN-FLIGHT: <exact title> — setup complete; work started`; setup failure sends
|
|
21
21
|
`BLOCKED` with the exact failure. It has no lease, read-only, mandatory
|
|
22
22
|
nested-goal, or nonce/ACK requirement. Completion is another native
|
|
23
|
-
parent-child task
|
|
24
|
-
`DONE` or `BLOCKED`, commit hash if any, checks, caveats,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
parent-child task message: commit the durable result, then send the LEAD
|
|
24
|
+
`DONE` or `BLOCKED`, commit hash if any, checks, caveats, cleanup parameters,
|
|
25
|
+
and `Archive: yes` or `Archive: no — <reason>` in the actual sent message, not
|
|
26
|
+
only the child's final response. After successful delivery, `Archive: yes`
|
|
27
|
+
means the child archives its own Codex task; `Archive: no` leaves it open. The
|
|
28
|
+
lead remains responsible for integration and post-merge branch bookkeeping,
|
|
29
|
+
not routine child-task archival.
|
|
30
30
|
Review is a separate explicit review chip/session when the lead asks for it.
|
|
31
31
|
FIX landing (adr/codex-landing-doctrine.md): a mission whose first line
|
|
32
32
|
begins `FIX:` (from `greprag fix spawn`) uses the handoff's detected
|
|
@@ -133,27 +133,32 @@ Paste this at the end of the child prompt.
|
|
|
133
133
|
|
|
134
134
|
```text
|
|
135
135
|
## Report when done
|
|
136
|
-
Commit the durable result first. Then
|
|
137
|
-
|
|
138
|
-
caveats, cleanup parameters, and archive
|
|
136
|
+
Commit the durable result first. Then use the native Codex task-message tool to
|
|
137
|
+
send the LEAD `DONE` or `BLOCKED`, commit hash if any, concise result, checks,
|
|
138
|
+
material caveats, cleanup parameters, and the archive decision. Do not
|
|
139
|
+
substitute a final response in your own task: the lifecycle report must be the
|
|
140
|
+
actual message sent to the LEAD.
|
|
139
141
|
|
|
140
142
|
Include one cleanup line:
|
|
141
|
-
`Cleanup:
|
|
143
|
+
`Cleanup: child archives own task; Codex may prune managed worktree; parent may delete branch after merge`
|
|
142
144
|
or
|
|
143
|
-
`Cleanup:
|
|
145
|
+
`Cleanup: child archives own task; local mode has no worktree or branch to prune`
|
|
144
146
|
or
|
|
145
147
|
`Cleanup: keep task/worktree/branch because ...`
|
|
146
148
|
|
|
147
|
-
Include one
|
|
148
|
-
`
|
|
149
|
+
Include one archive line in that same sent message:
|
|
150
|
+
`Archive: yes`
|
|
149
151
|
or
|
|
150
|
-
`
|
|
152
|
+
`Archive: no — <reason>`
|
|
151
153
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
After the message is delivered, `Archive: yes` means call
|
|
155
|
+
`set_thread_archived` for your own task; `Archive: no` means leave it open. Do
|
|
156
|
+
not make the parent perform routine child-task archival.
|
|
157
|
+
|
|
158
|
+
Do not merge, push, deploy, or manually delete the worktree. The parent
|
|
159
|
+
integrates the commit and may delete the branch after merge; Codex owns managed
|
|
160
|
+
worktree pruning. If review is needed, the parent creates a fresh review
|
|
161
|
+
chip/session.
|
|
157
162
|
```
|
|
158
163
|
|
|
159
164
|
## FIX contract
|
|
@@ -188,12 +193,13 @@ require a writable task.
|
|
|
188
193
|
|
|
189
194
|
## Parent cleanup
|
|
190
195
|
|
|
191
|
-
After the parent
|
|
192
|
-
|
|
196
|
+
After integration, the parent may clear remaining GrepRAG manifest/branch
|
|
197
|
+
bookkeeping with:
|
|
193
198
|
|
|
194
199
|
```bash
|
|
195
200
|
greprag codex chip cleanup <id> --native-archived
|
|
196
201
|
```
|
|
197
202
|
|
|
198
|
-
|
|
199
|
-
|
|
203
|
+
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.
|