greprag 5.74.11 → 5.74.13
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-chip-hooks.js +1 -1
- package/dist/codex-delivery-coordination.js +213 -0
- package/dist/codex-fast-hook.js +5 -8
- package/dist/commands/codex-chip/inbox.js +2 -2
- package/dist/commands/codex-chip/prompt.js +1 -1
- package/dist/commands/collision-check.js +1 -1
- package/dist/commands/config.js +75 -0
- package/dist/commands/coordinate-gate.js +2 -2
- package/dist/commands/delivery-reminder.js +8 -9
- package/dist/commands/fix.js +2 -2
- package/dist/commands/init.js +11 -20
- package/dist/commands/mechanic-spawn.js +3 -3
- package/dist/commands/memory.js +2 -3
- package/dist/commands/opencode-chip-mission.js +1 -1
- package/dist/commands/os-primer-reminder.js +1 -1
- package/dist/commands/procedure.js +5 -5
- package/dist/hook.js +8 -9
- package/dist/index.js +1 -24
- package/dist/opencode-plugin-helpers.js +1 -1
- package/dist/opencode-plugin.bundle.js +11 -12
- package/dist/procedure-run.js +15 -8
- package/dist/procedure.js +2 -2
- package/package.json +3 -2
- package/skill/greprag/SKILL.md +1 -1
- package/skill/greprag/docs/codex-chip.md +1 -1
- package/skill/mechanic/SKILL.md +2 -2
- package/skill/templates/chip-spawn.md +1 -1
- package/skill/templates/codex-chip-spawn.md +1 -1
- package/dist/codex-checkpoint-hook.js +0 -184
- package/dist/commands/checkpoint-helpers.js +0 -256
- package/dist/commands/checkpoint.js +0 -333
package/dist/codex-chip-hooks.js
CHANGED
|
@@ -66,7 +66,7 @@ function context(input) {
|
|
|
66
66
|
`Parent session: ${chip.parent.sessionId || 'not recorded'}`,
|
|
67
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, 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
|
|
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 commit/result 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 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.');
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** Codex delivery coordination - interrupt the first delivery action once,
|
|
3
|
+
* then keep the rest of that delivery run non-blocking.
|
|
4
|
+
*
|
|
5
|
+
* The hook cannot call native Codex task tools. It names the exact agent-owned
|
|
6
|
+
* discovery and messaging actions, persists the open delivery window before
|
|
7
|
+
* denying, and never waits for peer replies or attestation.
|
|
8
|
+
*
|
|
9
|
+
* adr: adr/codex-coordinate-gate.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.DELIVERY_COORDINATION_WINDOW_MS = void 0;
|
|
45
|
+
exports.codexDeliveryTrigger = codexDeliveryTrigger;
|
|
46
|
+
exports.codexDeliveryCoordinationText = codexDeliveryCoordinationText;
|
|
47
|
+
exports.evaluateCodexDeliveryCoordination = evaluateCodexDeliveryCoordination;
|
|
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
|
+
const coordinate_gate_1 = require("./commands/coordinate-gate");
|
|
53
|
+
exports.DELIVERY_COORDINATION_WINDOW_MS = 30 * 60 * 1000;
|
|
54
|
+
function homeDir() {
|
|
55
|
+
return process.env.USERPROFILE || process.env.HOME || '';
|
|
56
|
+
}
|
|
57
|
+
function normalize(value) {
|
|
58
|
+
return path.resolve(value).replace(/\\/g, '/').toLowerCase();
|
|
59
|
+
}
|
|
60
|
+
function gitRoot(cwd) {
|
|
61
|
+
try {
|
|
62
|
+
const root = (0, child_process_1.execFileSync)('git', ['rev-parse', '--show-toplevel'], {
|
|
63
|
+
cwd,
|
|
64
|
+
encoding: 'utf8',
|
|
65
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
66
|
+
windowsHide: true,
|
|
67
|
+
}).trim();
|
|
68
|
+
return root ? normalize(root) : null;
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function statePath(input, repoRoot) {
|
|
75
|
+
const home = homeDir();
|
|
76
|
+
const session = (input.session_id || '').trim();
|
|
77
|
+
if (!home || !session)
|
|
78
|
+
return null;
|
|
79
|
+
const key = crypto.createHash('sha256')
|
|
80
|
+
.update(`${session}\0${repoRoot}`)
|
|
81
|
+
.digest('hex')
|
|
82
|
+
.slice(0, 24);
|
|
83
|
+
return path.join(home, '.greprag', 'state', `codex-delivery-${key}.json`);
|
|
84
|
+
}
|
|
85
|
+
function readWindow(file) {
|
|
86
|
+
try {
|
|
87
|
+
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function writeWindow(file, window) {
|
|
94
|
+
try {
|
|
95
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
96
|
+
fs.writeFileSync(file, JSON.stringify(window, null, 2) + '\n');
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function isShellCapableTool(input) {
|
|
104
|
+
const name = (input.tool_name || '').toLowerCase();
|
|
105
|
+
return /(?:^|[.:/_-])(bash|shell|exec|exec_command)$/.test(name);
|
|
106
|
+
}
|
|
107
|
+
function decodeQuoted(value) {
|
|
108
|
+
if (value.startsWith('"')) {
|
|
109
|
+
try {
|
|
110
|
+
return JSON.parse(value);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (value.startsWith("'")) {
|
|
117
|
+
return value.slice(1, -1).replace(/\\'/g, "'").replace(/\\\\/g, '\\');
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
function embeddedCommands(code) {
|
|
122
|
+
const commands = [];
|
|
123
|
+
const re = /(?:command|cmd)\s*:\s*("(?:\\.|[^"])*"|'(?:\\.|[^'])*')/g;
|
|
124
|
+
for (const match of code.matchAll(re)) {
|
|
125
|
+
const decoded = decodeQuoted(match[1]);
|
|
126
|
+
if (decoded)
|
|
127
|
+
commands.push(decoded);
|
|
128
|
+
}
|
|
129
|
+
return commands;
|
|
130
|
+
}
|
|
131
|
+
function commandCandidates(input) {
|
|
132
|
+
if (!isShellCapableTool(input))
|
|
133
|
+
return [];
|
|
134
|
+
const toolInput = input.tool_input;
|
|
135
|
+
if (typeof toolInput === 'string')
|
|
136
|
+
return embeddedCommands(toolInput);
|
|
137
|
+
if (!toolInput || typeof toolInput !== 'object')
|
|
138
|
+
return [];
|
|
139
|
+
const candidates = [];
|
|
140
|
+
const fields = toolInput;
|
|
141
|
+
for (const key of ['command', 'cmd', 'script']) {
|
|
142
|
+
const value = fields[key];
|
|
143
|
+
if (typeof value === 'string')
|
|
144
|
+
candidates.push(value);
|
|
145
|
+
}
|
|
146
|
+
for (const key of ['code', 'input']) {
|
|
147
|
+
const value = fields[key];
|
|
148
|
+
if (typeof value === 'string')
|
|
149
|
+
candidates.push(...embeddedCommands(value));
|
|
150
|
+
}
|
|
151
|
+
return candidates;
|
|
152
|
+
}
|
|
153
|
+
function codexDeliveryTrigger(input) {
|
|
154
|
+
for (const command of commandCandidates(input)) {
|
|
155
|
+
const trigger = (0, coordinate_gate_1.classifyRiskyCommand)(command);
|
|
156
|
+
if (trigger)
|
|
157
|
+
return trigger;
|
|
158
|
+
}
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
function codexDeliveryCoordinationText(trigger) {
|
|
162
|
+
return `[DELIVERY NOW]
|
|
163
|
+
|
|
164
|
+
Before ${trigger.label}, call codex_app.list_threads unfiltered and keep only peers in the same repo. Use codex_app.send_message_to_thread once for peers with ready or overlapping work; include your branch/commit and ask only for ready commits or concrete blockers.
|
|
165
|
+
|
|
166
|
+
Include ready handoffs and clear known blockers, then retry immediately. Do not call wait_threads, wait for replies, or send follow-ups. Missing replies and unfinished peer work do not block delivery.`;
|
|
167
|
+
}
|
|
168
|
+
/** First delivery action opens a 30-minute session/repo window and interrupts
|
|
169
|
+
* once. Later merge/push/deploy/release actions refresh the same window and
|
|
170
|
+
* proceed without another coordination round. */
|
|
171
|
+
function evaluateCodexDeliveryCoordination(input, now = Date.now()) {
|
|
172
|
+
if (input.hook_event_name !== 'PreToolUse')
|
|
173
|
+
return null;
|
|
174
|
+
const trigger = codexDeliveryTrigger(input);
|
|
175
|
+
if (!trigger)
|
|
176
|
+
return null;
|
|
177
|
+
const cwd = input.cwd || process.cwd();
|
|
178
|
+
const repoRoot = gitRoot(cwd);
|
|
179
|
+
if (!repoRoot)
|
|
180
|
+
return null;
|
|
181
|
+
const file = statePath(input, repoRoot);
|
|
182
|
+
if (!file)
|
|
183
|
+
return null;
|
|
184
|
+
const previous = readWindow(file);
|
|
185
|
+
const previousLastAction = previous ? Date.parse(previous.lastActionAt) : NaN;
|
|
186
|
+
if (previous
|
|
187
|
+
&& previous.repoRoot === repoRoot
|
|
188
|
+
&& Number.isFinite(previousLastAction)
|
|
189
|
+
&& now - previousLastAction < exports.DELIVERY_COORDINATION_WINDOW_MS) {
|
|
190
|
+
writeWindow(file, {
|
|
191
|
+
...previous,
|
|
192
|
+
lastActionAt: new Date(now).toISOString(),
|
|
193
|
+
});
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
const openedAt = new Date(now).toISOString();
|
|
197
|
+
if (!writeWindow(file, {
|
|
198
|
+
sessionId: input.session_id || '',
|
|
199
|
+
repoRoot,
|
|
200
|
+
openedAt,
|
|
201
|
+
lastActionAt: openedAt,
|
|
202
|
+
})) {
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
hookSpecificOutput: {
|
|
207
|
+
hookEventName: 'PreToolUse',
|
|
208
|
+
additionalContext: codexDeliveryCoordinationText(trigger),
|
|
209
|
+
permissionDecision: 'deny',
|
|
210
|
+
permissionDecisionReason: `Run one same-repo coordination pass, then retry ${trigger.label} immediately; peer replies are not required.`,
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
}
|
package/dist/codex-fast-hook.js
CHANGED
|
@@ -83,10 +83,8 @@ async function main() {
|
|
|
83
83
|
return;
|
|
84
84
|
}
|
|
85
85
|
if (subcommand === 'codex-posttooluse') {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (result)
|
|
89
|
-
process.stdout.write(JSON.stringify(result) + '\n');
|
|
86
|
+
// Compatibility no-op for installed configs predating the delivery-boundary
|
|
87
|
+
// cutover. `greprag init --codex` removes this hook.
|
|
90
88
|
return;
|
|
91
89
|
}
|
|
92
90
|
const { evaluateCodexChipHook } = await Promise.resolve().then(() => __importStar(require('./codex-chip-hooks')));
|
|
@@ -97,10 +95,9 @@ async function main() {
|
|
|
97
95
|
return;
|
|
98
96
|
}
|
|
99
97
|
let result = chipResult;
|
|
100
|
-
if (subcommand === 'codex-pretooluse') {
|
|
101
|
-
const {
|
|
102
|
-
result = mergeOutputs(result,
|
|
103
|
-
recordCodexGitBoundary(input);
|
|
98
|
+
if (subcommand === 'codex-pretooluse' && !result?.hookSpecificOutput.permissionDecision) {
|
|
99
|
+
const { evaluateCodexDeliveryCoordination } = await Promise.resolve().then(() => __importStar(require('./codex-delivery-coordination')));
|
|
100
|
+
result = mergeOutputs(result, evaluateCodexDeliveryCoordination(input));
|
|
104
101
|
}
|
|
105
102
|
if (!result?.hookSpecificOutput.permissionDecision && input.tool_name === 'Bash') {
|
|
106
103
|
const { runSearchGuard } = await Promise.resolve().then(() => __importStar(require('./commands/search-guard')));
|
|
@@ -38,7 +38,7 @@ exports.sendChipEvent = sendChipEvent;
|
|
|
38
38
|
const crypto = __importStar(require("crypto"));
|
|
39
39
|
const os = __importStar(require("os"));
|
|
40
40
|
const path = __importStar(require("path"));
|
|
41
|
-
const
|
|
41
|
+
const config_1 = require("../config");
|
|
42
42
|
const identity_1 = require("../identity");
|
|
43
43
|
const model_1 = require("./model");
|
|
44
44
|
const store_1 = require("./store");
|
|
@@ -71,7 +71,7 @@ async function sendChipEvent(manifest, targetSession, event, fromSession) {
|
|
|
71
71
|
try {
|
|
72
72
|
if (!targetSession)
|
|
73
73
|
throw new Error('Chip lifecycle event has no target parent session.');
|
|
74
|
-
const cfg = (0,
|
|
74
|
+
const cfg = (0, config_1.getConfig)();
|
|
75
75
|
if (!cfg.apiKey)
|
|
76
76
|
throw new Error('Chip lifecycle inbox delivery has no API key.');
|
|
77
77
|
const handle = await ownHandle(cfg.apiUrl, cfg.apiKey);
|
|
@@ -40,5 +40,5 @@ Report when done:
|
|
|
40
40
|
${reportInstruction}
|
|
41
41
|
- 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 ...\`.
|
|
42
42
|
- 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.
|
|
43
|
-
- 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
|
|
43
|
+
- 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 commit/result 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.`;
|
|
44
44
|
}
|
|
@@ -127,7 +127,7 @@ function buildCollisionDirective(peers, myShort, alias) {
|
|
|
127
127
|
+ `GrepRAG watcher/cross-harness peers: \`greprag send "…what you're about to touch…" --to ${handle}@greprag.com/<their-8hex> --from-session ${myShort}\` `
|
|
128
128
|
+ `(YOU compose and send it — this is a notice, not an auto-send; watcher rows are not the Codex peer source of truth); `
|
|
129
129
|
+ `(2) do your code work in a worktree on its own branch (\`git worktree add .claude/worktrees/<slug> -b <branch>\`); `
|
|
130
|
-
+ `(3) at completion resolve \`.greprag/delivery.json\`, include every ready peer
|
|
130
|
+
+ `(3) at completion resolve \`.greprag/delivery.json\`, include every ready peer commit/result, and let one delivery owner `
|
|
131
131
|
+ `integrate and finish the declared push/deploy/release path. Never edit the shared default checkout concurrently.`);
|
|
132
132
|
}
|
|
133
133
|
/** Reduce the watcher list to OTHER live sessions that are NOT in my repo
|
|
@@ -0,0 +1,75 @@
|
|
|
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.loadEnvFile = loadEnvFile;
|
|
37
|
+
exports.getConfig = getConfig;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const API_URL_DEFAULT = 'https://api.greprag.com';
|
|
41
|
+
function loadEnvFile(filePath) {
|
|
42
|
+
try {
|
|
43
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
44
|
+
for (const line of content.split('\n')) {
|
|
45
|
+
const trimmed = line.trim();
|
|
46
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
47
|
+
continue;
|
|
48
|
+
const eqIdx = trimmed.indexOf('=');
|
|
49
|
+
if (eqIdx < 1)
|
|
50
|
+
continue;
|
|
51
|
+
const key = trimmed.slice(0, eqIdx).trim();
|
|
52
|
+
let value = trimmed.slice(eqIdx + 1).trim();
|
|
53
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
54
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
55
|
+
value = value.slice(1, -1);
|
|
56
|
+
}
|
|
57
|
+
if (!process.env[key])
|
|
58
|
+
process.env[key] = value;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Missing env files are fine.
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function getConfig() {
|
|
66
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
|
|
67
|
+
if (homeDir)
|
|
68
|
+
loadEnvFile(path.join(homeDir, '.greprag', '.env'));
|
|
69
|
+
if (!process.env.GREPRAG_API_KEY)
|
|
70
|
+
loadEnvFile(path.join(process.cwd(), '.env'));
|
|
71
|
+
return {
|
|
72
|
+
apiUrl: process.env.GREPRAG_API_URL || API_URL_DEFAULT,
|
|
73
|
+
apiKey: process.env.GREPRAG_API_KEY || '',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
* dedups to stay quiet), the merge gate must reflect live truth each time.
|
|
28
28
|
*
|
|
29
29
|
* EFFECT is the adapter's choice, not the eval's: Claude/OpenCode inject the
|
|
30
|
-
* fresh roster as context
|
|
31
|
-
*
|
|
30
|
+
* fresh roster as context. Codex uses the separate local, bounded delivery
|
|
31
|
+
* interrupt in codex-delivery-coordination.ts and carries no attestation. An
|
|
32
32
|
* ingress-source wrapper would inject instead. The eval below only produces
|
|
33
33
|
* the message.
|
|
34
34
|
*
|
|
@@ -12,27 +12,26 @@ exports.buildDeliveryAnnounce = buildDeliveryAnnounce;
|
|
|
12
12
|
// adr: adr/delivery-announce-pilot.md
|
|
13
13
|
function coordinationLine(platform) {
|
|
14
14
|
if (platform === 'codex') {
|
|
15
|
-
return 'Codex
|
|
15
|
+
return 'Codex: at the merge/deploy gate, call codex_app.list_threads unfiltered, filter to peers in the same repo, then use codex_app.send_message_to_thread once for ready or overlapping work.';
|
|
16
16
|
}
|
|
17
17
|
if (platform === 'claude-code') {
|
|
18
|
-
return 'Claude Code
|
|
18
|
+
return 'Claude Code: at the merge/deploy gate, discover peers in the same repo and send one concise delivery notice to peers with ready or overlapping work.';
|
|
19
19
|
}
|
|
20
20
|
if (platform === 'opencode') {
|
|
21
|
-
return 'OpenCode
|
|
21
|
+
return 'OpenCode: at the merge/deploy gate, use the GrepRAG project/session registry and send one concise delivery notice to peers with ready or overlapping work.';
|
|
22
22
|
}
|
|
23
|
-
return '
|
|
23
|
+
return 'At the merge/deploy gate, coordinate once with peers in the same repo who have ready or overlapping work.';
|
|
24
24
|
}
|
|
25
25
|
function buildDeliveryAnnounce(env) {
|
|
26
26
|
if (!env.deliveryRepo)
|
|
27
27
|
return null;
|
|
28
28
|
const project = env.projectName?.trim() || 'current repo';
|
|
29
29
|
return [
|
|
30
|
-
`[DELIVERY
|
|
31
|
-
'
|
|
30
|
+
`[DELIVERY — ${project}]`,
|
|
31
|
+
'Commit useful, passing work.',
|
|
32
32
|
coordinationLine(env.platform),
|
|
33
|
-
'
|
|
34
|
-
'Use
|
|
35
|
-
'A full-goal delivery mission already provisions ordinary repo-scoped commit, merge, push, deploy, and verification; do not wait for a second keyword.',
|
|
33
|
+
'Include ready peer commits and clear known blockers, then merge to the default branch and deploy immediately. Missing replies and unfinished peer work do not block delivery.',
|
|
34
|
+
'Use this repo\'s delivery profile and verify production.',
|
|
36
35
|
].join('\n');
|
|
37
36
|
}
|
|
38
37
|
exports.deliveryControlModule = {
|
package/dist/commands/fix.js
CHANGED
|
@@ -577,7 +577,7 @@ USAGE
|
|
|
577
577
|
surface. The caller dispatches it as a visible chip
|
|
578
578
|
using detected workspaceMode: Git -> worktree,
|
|
579
579
|
non-Git/no-commit -> serialized project-local;
|
|
580
|
-
the chip fixes, verifies,
|
|
580
|
+
the chip fixes, verifies, commits useful work, then hands off.
|
|
581
581
|
greprag fix log "<text>" [--scope <s>] [--repaired] Audit/design-input note (NOT the friction reflex).
|
|
582
582
|
--repaired records a known rule directly.
|
|
583
583
|
greprag fix list [--all] [--repaired] [--format json] List fixes — open by default;
|
|
@@ -623,7 +623,7 @@ async function runFix(args) {
|
|
|
623
623
|
// THE friction reflex (grepragOS, 2026-07-12): one unit of friction ⇒
|
|
624
624
|
// one fix-chip mission now. The mission detects Git capability and tells
|
|
625
625
|
// native dispatch to use a worktree or serialized project-local mode;
|
|
626
|
-
// the chip fixes, verifies,
|
|
626
|
+
// the chip fixes, verifies, commits useful work, then hands to the delivery owner. Replaces queue-first
|
|
627
627
|
// `fix log` as doctrine.
|
|
628
628
|
return (0, mechanic_spawn_1.fixSpawn)(rest);
|
|
629
629
|
}
|
package/dist/commands/init.js
CHANGED
|
@@ -1130,18 +1130,9 @@ 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
|
|
1134
|
-
|
|
1135
|
-
|
|
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)');
|
|
1133
|
+
const removedPostToolCoord = removeGrepragHook(config.hooks, 'PostToolUse', 'codex-posttooluse');
|
|
1134
|
+
if (removedPostToolCoord) {
|
|
1135
|
+
changes.push(`Removed ${removedPostToolCoord} Codex commit-triggered coordination hook(s); delivery coordination now starts at PreToolUse`);
|
|
1145
1136
|
}
|
|
1146
1137
|
const permissionHook = {
|
|
1147
1138
|
matcher: '',
|
|
@@ -1199,8 +1190,8 @@ function applyCodexHooks(config) {
|
|
|
1199
1190
|
];
|
|
1200
1191
|
// adr: adr/codex-hook-latency.md
|
|
1201
1192
|
// Collapse the hot PreToolUse safety pair into one fast command process. It
|
|
1202
|
-
// runs the chip/apply_patch guard
|
|
1203
|
-
//
|
|
1193
|
+
// runs the chip/apply_patch guard, one-shot delivery coordination, and local
|
|
1194
|
+
// Bash safety checks. The legacy split coordination gate is removed.
|
|
1204
1195
|
const removedPreToolChip = removeGrepragHook(config.hooks, 'PreToolUse', 'codex-chip-hook');
|
|
1205
1196
|
const removedPreToolCoord = removeGrepragHook(config.hooks, 'PreToolUse', 'codex-coordinate-gate');
|
|
1206
1197
|
if (removedPreToolChip || removedPreToolCoord) {
|
|
@@ -1208,16 +1199,16 @@ function applyCodexHooks(config) {
|
|
|
1208
1199
|
}
|
|
1209
1200
|
const preToolUseHook = {
|
|
1210
1201
|
matcher: '',
|
|
1211
|
-
hooks: [commandHook('codex-pretooluse', 10, 'Checking GrepRAG Codex safety', 'greprag-codex-hook')],
|
|
1202
|
+
hooks: [commandHook('codex-pretooluse', 10, 'Checking GrepRAG Codex delivery and safety', 'greprag-codex-hook')],
|
|
1212
1203
|
};
|
|
1213
1204
|
if (!hasGrepragHookWithMatcher(config.hooks.PreToolUse, 'codex-pretooluse', preToolUseHook.matcher)) {
|
|
1214
1205
|
if (!config.hooks.PreToolUse)
|
|
1215
1206
|
config.hooks.PreToolUse = [];
|
|
1216
1207
|
config.hooks.PreToolUse.push(preToolUseHook);
|
|
1217
|
-
changes.push('Added Codex PreToolUse hook (
|
|
1208
|
+
changes.push('Added Codex PreToolUse hook (delivery coordination + local safety)');
|
|
1218
1209
|
}
|
|
1219
1210
|
else {
|
|
1220
|
-
changes.push('Codex PreToolUse
|
|
1211
|
+
changes.push('Codex PreToolUse delivery/safety hook already configured (skipped)');
|
|
1221
1212
|
}
|
|
1222
1213
|
const removedStopChip = removeGrepragHook(config.hooks, 'Stop', 'codex-chip-hook');
|
|
1223
1214
|
if (removedStopChip) {
|
|
@@ -1278,7 +1269,7 @@ function normalizeCodexHookCommands(hooks) {
|
|
|
1278
1269
|
'codex-permission-context': { timeout: 3, statusMessage: 'Loading GrepRAG approval context' },
|
|
1279
1270
|
'codex-subagent-start': { timeout: 3, statusMessage: 'Recording GrepRAG subagent metadata' },
|
|
1280
1271
|
'codex-chip-hook': { timeout: 3, statusMessage: 'Enforcing Codex chip contract', runner: 'greprag-codex-hook' },
|
|
1281
|
-
'codex-pretooluse': { timeout: 10, statusMessage: 'Checking GrepRAG Codex safety', runner: 'greprag-codex-hook' },
|
|
1272
|
+
'codex-pretooluse': { timeout: 10, statusMessage: 'Checking GrepRAG Codex delivery and safety', runner: 'greprag-codex-hook' },
|
|
1282
1273
|
'codex-coordinate-gate': { timeout: 10, statusMessage: 'Checking peer coordination' },
|
|
1283
1274
|
'codex-store': { timeout: 3, statusMessage: 'Storing GrepRAG turn', runner: 'greprag-codex-hook' },
|
|
1284
1275
|
};
|
|
@@ -1789,7 +1780,7 @@ const GREPRAG_CLI_BODY = `## greprag CLI (cross-project memory + async messaging
|
|
|
1789
1780
|
- \`email send --to <real-addr> --from <handle>@greprag.com --subject "s" (--body "t" | --body-file <f|->)\` — sends a **REAL outbound SMTP email** from your greprag address to any recipient (\`--attach\`/\`--cc\`/\`--bcc\`/\`--html-file\` available). \`email pending\` · \`email pull\` = drain inbound. **Use this — not \`send\` — when the user says "email X".** The \`send\`-vs-\`email send\` collision is the trap: only \`email send\` is actual email.
|
|
1790
1781
|
- \`memory search "q"\` · \`memory recap\` (alias \`briefing\`) — search a topic/bug · session catch-up digest; narrative-pyramid tiers \`turns\`·\`hourly\`·\`daily\`·\`weekly\`·\`ships\` (commits/PRs/deploys), each \`--last N\` · \`--from/--to ISO\` · \`--project\`
|
|
1791
1782
|
- \`corpus upload <file|url> --raw|--enriched [--index]\` · \`corpus search "q" --all\` — ingest + search arbitrary text (books, codebases, refs); \`--raw\` lexical, \`--enriched\` adds LLM vocab bridge; \`--index\` = a multi-doc "index, no bundle" source (llms.txt/sitemap) → one library store, members refreshed cheap-signal-only (ETag→lastmod→content-length, no full-read floor)
|
|
1792
|
-
- \`fix spawn "<one unit of friction>"\` · \`fix search|repair\`
|
|
1783
|
+
- \`fix spawn "<one unit of friction>"\` · \`fix search|repair\` — THE friction reflex: one visible fix-chip mission per unit; it detects Git before dispatch (worktree for Git, serialized project-local for non-Git/no-commit); the chip fixes, verifies, commits useful work, and hands it to the mission delivery owner (\`fix log\` = audit notes only) · search/repair the fix queue
|
|
1793
1784
|
- \`status\` · \`doctor\` — install/auth/hooks state · repair orphan project_id + identity drift
|
|
1794
1785
|
Hard rule: AI never auto-acts on a brief — summarize + confirm.`;
|
|
1795
1786
|
/** The previous SHIPPED default (v5.39.x and earlier, pre-markers, unmarked).
|
|
@@ -1802,7 +1793,7 @@ const GREPRAG_CLI_BODY_V1 = `## greprag CLI (cross-project memory + async messag
|
|
|
1802
1793
|
- \`send "md" --to <handle>@greprag.com[/<8hex>]\` — message a session (\`/<8hex>\`) or cold-open a front desk (bare handle); Discord DM: \`--to discord:<snowflake>\`
|
|
1803
1794
|
- \`memory search "q"\` · \`memory recap\` (alias \`briefing\`) — search a topic/bug · session catch-up digest; narrative-pyramid tiers \`turns\`·\`hourly\`·\`daily\`·\`ships\` (commits/PRs/deploys), each \`--last N\` · \`--from/--to ISO\` · \`--project\`
|
|
1804
1795
|
- \`corpus upload <file|url> --raw|--enriched\` · \`corpus search "q" --all\` — ingest + search arbitrary text (books, codebases, refs); \`--raw\` lexical, \`--enriched\` adds LLM vocab bridge
|
|
1805
|
-
- \`fix spawn "<unit>"\`|\`fix search\`
|
|
1796
|
+
- \`fix spawn "<unit>"\`|\`fix search\` — emit one visible fix-chip mission per friction unit; native dispatch creates the isolated checkout/worktree; the chip fixes, verifies, commits useful work, and hands it to the mission delivery owner
|
|
1806
1797
|
- \`status\` · \`doctor\` — install/auth/hooks state · repair orphan project_id + identity drift
|
|
1807
1798
|
Hard rule: AI never auto-acts on a brief — summarize + confirm.`;
|
|
1808
1799
|
/** The managed-section registry for ~/.claude/CLAUDE.md. Add a spec here to put
|
|
@@ -19,7 +19,7 @@ exports.mechanicSpawn = mechanicSpawn;
|
|
|
19
19
|
*
|
|
20
20
|
* The chip's contract is simple: identify the exact friction, make the
|
|
21
21
|
* smallest durable root-cause fix, explain the friction and fix in human
|
|
22
|
-
* terms, then hand its
|
|
22
|
+
* terms, then hand its commit/result to the mission's delivery owner. A full-goal
|
|
23
23
|
* chip with no live parent becomes that owner and follows the repo profile.
|
|
24
24
|
*
|
|
25
25
|
* This command does NOT create the child task or its workspace. The caller
|
|
@@ -116,7 +116,7 @@ function buildFixMission(friction, scope, parentSession, type = inferFixType(fri
|
|
|
116
116
|
'3. Confirm you are not in the caller/parent checkout. If you are, STOP and report `CHIP DISPATCH BLOCKED: workspaceMode=worktree was not honored`.',
|
|
117
117
|
],
|
|
118
118
|
work: 'Work as an ordinary unrestricted read/write session in the dispatch-provided isolated worktree.',
|
|
119
|
-
completion: 'Use focused tests or checks that prove the fix and commit
|
|
119
|
+
completion: 'Use focused tests or checks that prove the fix and commit useful work. If a live parent owns delivery, report the commit and checks so it can integrate and clean up. If no live parent exists and this is the full-goal mission, resolve `.greprag/delivery.json` and become the delivery owner. Gate only effects outside ordinary repo delivery.',
|
|
120
120
|
}
|
|
121
121
|
: {
|
|
122
122
|
selected: 'Workspace mode: local -> no usable Git HEAD detected; native dispatch targets the current project directory directly.',
|
|
@@ -202,7 +202,7 @@ async function fixSpawn(args, opts = {}) {
|
|
|
202
202
|
parentSession: parentSession || null,
|
|
203
203
|
mission,
|
|
204
204
|
dispatch: workspaceMode === 'worktree'
|
|
205
|
-
? 'Create a visible native chip/task using the harness worktree path, then send this mission as its first turn. The chip fixes, verifies, commits, and hands the
|
|
205
|
+
? 'Create a visible native chip/task using the harness worktree path, then send this mission as its first turn. The chip fixes, verifies, commits, and hands the result to the mission delivery owner.'
|
|
206
206
|
: 'No usable Git HEAD was detected. Create a visible native chip/task using the harness project-local path; do not attempt a worktree or initialize Git. Yield caller file writes until the chip reports back. The chip fixes, verifies, and hands the result to the mission owner.',
|
|
207
207
|
};
|
|
208
208
|
console.log(JSON.stringify(handoff, null, 2));
|
package/dist/commands/memory.js
CHANGED
|
@@ -582,8 +582,7 @@ Subcommands:
|
|
|
582
582
|
least one filter is required (a bare delete is
|
|
583
583
|
refused).
|
|
584
584
|
[--project <name>] Narrow to one project (default: all projects).
|
|
585
|
-
[--shape <name>] turn / hourly / daily / weekly /
|
|
586
|
-
ship-event.
|
|
585
|
+
[--shape <name>] turn / hourly / daily / weekly / ship-event.
|
|
587
586
|
[--from ISO] [--to ISO] Created-at range (half-open: >= from, < to).
|
|
588
587
|
[--session <id>] One session's external id.
|
|
589
588
|
[--yes] Execute the delete (omit for a dry run).
|
|
@@ -626,7 +625,7 @@ async function deleteCmd(args) {
|
|
|
626
625
|
const projectArg = getFlag(args, '--project');
|
|
627
626
|
const confirmed = args.includes('--yes');
|
|
628
627
|
if (!shape && !from && !to && !session && !projectArg) {
|
|
629
|
-
console.error('Usage: greprag memory delete [--project <name>] [--shape <turn|hourly|daily|weekly|
|
|
628
|
+
console.error('Usage: greprag memory delete [--project <name>] [--shape <turn|hourly|daily|weekly|ship-event>] [--from ISO] [--to ISO] [--session <id>] [--yes]');
|
|
630
629
|
console.error('At least one filter is required (a bare delete is refused).');
|
|
631
630
|
process.exit(1);
|
|
632
631
|
}
|
|
@@ -69,7 +69,7 @@ function buildMission(input) {
|
|
|
69
69
|
'**Repair contract**',
|
|
70
70
|
'Work as an ordinary unrestricted read/write session in the isolated checkout.',
|
|
71
71
|
'Find and repair the reusable root mechanism; own discovery, repair, tests, verification, and commit.',
|
|
72
|
-
'Finish it through the Delivery System: confer with live peers first (`greprag inbox watchers`), resolve `.greprag/delivery.json`, include every ready
|
|
72
|
+
'Finish it through the Delivery System: confer with live peers first (`greprag inbox watchers`), resolve `.greprag/delivery.json`, include every ready peer commit/result, and let one delivery owner integrate, verify, push, deploy, or release exactly as the profile declares. If a live parent already owns delivery, report your commit and checks for integration; if no parent is available and this is the full-goal mission, become the delivery owner. Gate only effects outside ordinary repo delivery.',
|
|
73
73
|
'Report DONE or BLOCKED natively to the parent task; do not use a mandatory GrepRAG completion ceremony.',
|
|
74
74
|
'',
|
|
75
75
|
'**Friction / mission**',
|
|
@@ -26,7 +26,7 @@ function buildOsPrimer(env) {
|
|
|
26
26
|
'• 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.',
|
|
27
27
|
'• 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.',
|
|
28
28
|
'• Pull before derive: `greprag memory search` / `corpus search` / `load` BEFORE asking the operator or re-deriving what the project already knows. Friction or an env/toolchain/worktree/secret bootstrap roadblock → search Memory for the exact error/friction + repo/tool before inventing a workaround. Clear overcome → apply it and continue. Named person/org/project/repo/customer/handle or unexplained proper noun → search Memory before guessing, unless fully defined in-turn.',
|
|
29
|
-
`• Unresolved friction ⇒ fix: only when Memory has no answer, the remembered overcome fails, or the same friction repeats. Then 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 unresolved unit per chip; the chip fixes, verifies,
|
|
29
|
+
`• Unresolved friction ⇒ fix: only when Memory has no answer, the remembered overcome fails, or the same friction repeats. Then 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 unresolved unit per chip; the chip fixes, verifies, commits useful work, and hands it to the mission delivery owner.`,
|
|
30
30
|
'• Teach the system, not the chat: explained twice by the operator ⇒ it belongs in a skill / load entry / STATE block / ADR, not the conversation.',
|
|
31
31
|
].join('\n');
|
|
32
32
|
}
|
|
@@ -331,10 +331,10 @@ async function runProcedure(args) {
|
|
|
331
331
|
console.log(` started: ${run.startedAt}`);
|
|
332
332
|
console.log(` fingerprint: ${run.artifactFingerprint}`);
|
|
333
333
|
console.log(` outcome: ${run.outcome || 'active'}`);
|
|
334
|
-
console.log('
|
|
335
|
-
if (!run.
|
|
334
|
+
console.log(' attestations:');
|
|
335
|
+
if (!run.attestations.length)
|
|
336
336
|
console.log(' (none)');
|
|
337
|
-
for (const c of run.
|
|
337
|
+
for (const c of run.attestations)
|
|
338
338
|
console.log(` ${c.kind} · ${c.via || '-'} · ${c.ref || '-'} · ${c.artifactFingerprint.slice(0, 12)}`);
|
|
339
339
|
return;
|
|
340
340
|
}
|
|
@@ -357,11 +357,11 @@ async function runProcedure(args) {
|
|
|
357
357
|
process.exit(1);
|
|
358
358
|
}
|
|
359
359
|
try {
|
|
360
|
-
const next = (0, procedure_run_1.
|
|
360
|
+
const next = (0, procedure_run_1.attestProcedureEvidence)({
|
|
361
361
|
run, kind, cwd: process.cwd(), via: viaRaw,
|
|
362
362
|
ref: getFlag(rest.slice(2), '--ref'),
|
|
363
363
|
});
|
|
364
|
-
const c = next.
|
|
364
|
+
const c = next.attestations[next.attestations.length - 1];
|
|
365
365
|
console.log(`Attested ${verb}:${kind} for ${c.artifactFingerprint}.`);
|
|
366
366
|
}
|
|
367
367
|
catch (e) {
|