ferrycat 0.3.3 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -14
- package/README_zh.md +93 -14
- package/bin/ferrycat.js +20 -1
- package/dist/cli.js +196 -14
- package/dist/cli.js.map +1 -1
- package/dist/daemon.d.ts +137 -1
- package/dist/daemon.js +673 -10
- package/dist/daemon.js.map +1 -1
- package/dist/delivery.d.ts +48 -0
- package/dist/delivery.js +158 -0
- package/dist/delivery.js.map +1 -0
- package/dist/demo.d.ts +36 -0
- package/dist/demo.js +343 -0
- package/dist/demo.js.map +1 -0
- package/dist/engine.d.ts +15 -1
- package/dist/engine.js +287 -29
- package/dist/engine.js.map +1 -1
- package/dist/fingerprint.d.ts +60 -4
- package/dist/fingerprint.js +438 -9
- package/dist/fingerprint.js.map +1 -1
- package/dist/index.js +7 -4
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +62 -0
- package/dist/init.js +356 -0
- package/dist/init.js.map +1 -0
- package/dist/schemas.d.ts +64 -0
- package/dist/schemas.js +30 -0
- package/dist/schemas.js.map +1 -1
- package/dist/supervisor.d.ts +10 -0
- package/dist/supervisor.js +34 -26
- package/dist/supervisor.js.map +1 -1
- package/dist/types.d.ts +20 -0
- package/package.json +16 -4
- package/server.json +3 -3
package/dist/demo.js
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FerryCat Zero-Config Sandbox Demo (REQ-EXP-01).
|
|
3
|
+
*
|
|
4
|
+
* Runs a complete contract lifecycle — dispatch -> claim -> supervised execution -> TOCTOU
|
|
5
|
+
* re-verification -> COMPLETED — entirely inside an isolated temporary sandbox, so a brand-new
|
|
6
|
+
* user can see the deterministic handoff loop without configuring a single MCP server.
|
|
7
|
+
*
|
|
8
|
+
* Design constraints:
|
|
9
|
+
* - Zero pollution: every artifact (sample source, handler script, SQLite database) lives under
|
|
10
|
+
* `os.tmpdir()/ferrycat-demo-*`. The user's real workspace and `~/.ferrycat/mesh.db` are never touched.
|
|
11
|
+
* - No simulation shortcuts on the engine path: the demo drives the exact same public APIs a real
|
|
12
|
+
* daemon uses (`dispatchContract` / `pollNextTask` / `executeTaskAndFulfill` / `verifyContract`),
|
|
13
|
+
* so a green demo is genuine evidence rather than a puppet show.
|
|
14
|
+
* - Machine-readable mode: with `json: true` the function writes nothing to stdout and returns a
|
|
15
|
+
* plain object, keeping CI/upstream automation parseable.
|
|
16
|
+
*/
|
|
17
|
+
import fs from 'node:fs';
|
|
18
|
+
import os from 'node:os';
|
|
19
|
+
import path from 'node:path';
|
|
20
|
+
import { FerryCatEngine } from './engine.js';
|
|
21
|
+
import { executeTaskAndFulfill } from './supervisor.js';
|
|
22
|
+
const TOTAL_STEPS = 4;
|
|
23
|
+
const SAMPLE_REL_PATH = 'src/calc.ts';
|
|
24
|
+
/**
|
|
25
|
+
* Sample source under review. Deliberately contains exactly one advisory-level defect
|
|
26
|
+
* (`==` instead of `===`) so the demo handler has something real to find and the verdict
|
|
27
|
+
* is deterministic across runs and platforms.
|
|
28
|
+
*/
|
|
29
|
+
const SAMPLE_SOURCE = `export function add(a: number, b: number): number {
|
|
30
|
+
return a + b;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function divide(a: number, b: number): number {
|
|
34
|
+
if (b == 0) {
|
|
35
|
+
throw new Error('Division by zero');
|
|
36
|
+
}
|
|
37
|
+
return a / b;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const VERSION = '1.0.0';
|
|
41
|
+
`;
|
|
42
|
+
/**
|
|
43
|
+
* Handler script written into the sandbox. It reads the contract from stdin (same protocol as
|
|
44
|
+
* scripts/review-handler.js), inspects the real pointer file on disk, then emits a delivery
|
|
45
|
+
* envelope on stdout. `execDelayMs` keeps the child alive long enough for the supervisor
|
|
46
|
+
* heartbeat ticker to fire at least once, so the demo can prove lease renewal is live.
|
|
47
|
+
*/
|
|
48
|
+
function buildHandlerScript(execDelayMs) {
|
|
49
|
+
return `/**
|
|
50
|
+
* FerryCat demo handler (generated by \`ferrycat-cli demo\`).
|
|
51
|
+
* Reads the contract JSON from stdin, inspects the pointer file, prints a delivery envelope.
|
|
52
|
+
*/
|
|
53
|
+
const fs = require('node:fs');
|
|
54
|
+
const path = require('node:path');
|
|
55
|
+
|
|
56
|
+
const EXEC_DELAY_MS = ${execDelayMs};
|
|
57
|
+
|
|
58
|
+
function inspect(workspaceRoot, pointers) {
|
|
59
|
+
const issues = [];
|
|
60
|
+
for (const pointer of pointers || []) {
|
|
61
|
+
const absPath = path.resolve(workspaceRoot, pointer.path);
|
|
62
|
+
if (!fs.existsSync(absPath)) {
|
|
63
|
+
issues.push(pointer.path + ': file is missing on disk');
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const lines = fs.readFileSync(absPath, 'utf8').split(/\\r?\\n/);
|
|
67
|
+
lines.forEach((line, idx) => {
|
|
68
|
+
// Loose equality on a numeric/string guard is the classic review catch.
|
|
69
|
+
if (/(^|[^=!<>])==([^=]|$)/.test(line)) {
|
|
70
|
+
issues.push(pointer.path + ':' + (idx + 1) + " uses '==' instead of '===' (strict equality)");
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return issues;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function main() {
|
|
78
|
+
const raw = fs.readFileSync(0, 'utf8');
|
|
79
|
+
if (!raw.trim()) {
|
|
80
|
+
console.error('demo handler: no contract payload received on stdin');
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
const contract = JSON.parse(raw);
|
|
84
|
+
const workspaceRoot = process.env.FERRYCAT_WORKSPACE_ROOT || process.cwd();
|
|
85
|
+
const issues = inspect(workspaceRoot, contract.pointers);
|
|
86
|
+
|
|
87
|
+
const finish = () => {
|
|
88
|
+
// REQ-ENG-04: explicit delivery envelope; any other stdout line is treated as a log.
|
|
89
|
+
console.log('demo handler: review finished, emitting delivery envelope');
|
|
90
|
+
process.stdout.write(
|
|
91
|
+
JSON.stringify({
|
|
92
|
+
ferrycat_delivery: {
|
|
93
|
+
result_summary:
|
|
94
|
+
'Reviewed ' + (contract.pointers || []).length + ' file(s) for contract ' +
|
|
95
|
+
contract.contract_id + '; ' + issues.length + ' advisory finding(s).',
|
|
96
|
+
structured_output: {
|
|
97
|
+
passed: true,
|
|
98
|
+
issues,
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
}) + '\\n'
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
if (EXEC_DELAY_MS > 0) {
|
|
106
|
+
setTimeout(finish, EXEC_DELAY_MS);
|
|
107
|
+
} else {
|
|
108
|
+
finish();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
main();
|
|
113
|
+
`;
|
|
114
|
+
}
|
|
115
|
+
function makePainter(enabled) {
|
|
116
|
+
const wrap = (code) => (text) => enabled ? `\u001b[${code}m${text}\u001b[0m` : text;
|
|
117
|
+
return {
|
|
118
|
+
bold: wrap('1'),
|
|
119
|
+
dim: wrap('2'),
|
|
120
|
+
green: wrap('32'),
|
|
121
|
+
cyan: wrap('36'),
|
|
122
|
+
yellow: wrap('33'),
|
|
123
|
+
magenta: wrap('35'),
|
|
124
|
+
gray: wrap('90'),
|
|
125
|
+
red: wrap('31'),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function shortSha(sha) {
|
|
129
|
+
return sha.length <= 12 ? sha : `${sha.slice(0, 8)}...${sha.slice(-4)}`;
|
|
130
|
+
}
|
|
131
|
+
function removeSandbox(sandbox) {
|
|
132
|
+
// Windows keeps WAL/SHM handles briefly after close(); retries absorb that window.
|
|
133
|
+
fs.rmSync(sandbox, { recursive: true, force: true, maxRetries: 5, retryDelay: 50 });
|
|
134
|
+
}
|
|
135
|
+
export async function runDemo(options = {}) {
|
|
136
|
+
const startedAt = Date.now();
|
|
137
|
+
const execDelayMs = Math.max(0, options.execDelayMs ?? 1900);
|
|
138
|
+
const execTtlSec = Math.max(2, options.execTtlSec ?? 5);
|
|
139
|
+
const human = !options.json;
|
|
140
|
+
const colorOn = options.color ?? (human && Boolean(process.stdout.isTTY) && !process.env.NO_COLOR);
|
|
141
|
+
const paint = makePainter(colorOn);
|
|
142
|
+
const write = options.write ?? ((line) => process.stdout.write(`${line}\n`));
|
|
143
|
+
const say = (line = '') => {
|
|
144
|
+
if (human)
|
|
145
|
+
write(line);
|
|
146
|
+
};
|
|
147
|
+
const sandbox = fs.mkdtempSync(path.join(os.tmpdir(), 'ferrycat-demo-'));
|
|
148
|
+
let engine;
|
|
149
|
+
let succeeded = false;
|
|
150
|
+
const steps = [];
|
|
151
|
+
const warnings = [];
|
|
152
|
+
let heartbeatRenewals = 0;
|
|
153
|
+
let contractId = '';
|
|
154
|
+
let claimToken = '';
|
|
155
|
+
let status = 'UNKNOWN';
|
|
156
|
+
let verdict = 'PASSED';
|
|
157
|
+
let issues = [];
|
|
158
|
+
let dirtyFiles = 0;
|
|
159
|
+
const record = (index, title, fields) => {
|
|
160
|
+
steps.push({ index, total: TOTAL_STEPS, title, fields });
|
|
161
|
+
say('');
|
|
162
|
+
say(` ${paint.green('✔')} ${paint.bold(`[${index}/${TOTAL_STEPS}] ${title}`)}`);
|
|
163
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
164
|
+
say(` ${paint.gray(key.padEnd(10))}${value}`);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
try {
|
|
168
|
+
// ---------------------------------------------------------------------
|
|
169
|
+
// Sandbox scaffolding (isolated workspace + handler + SQLite database)
|
|
170
|
+
// ---------------------------------------------------------------------
|
|
171
|
+
const srcDir = path.join(sandbox, 'src');
|
|
172
|
+
fs.mkdirSync(srcDir, { recursive: true });
|
|
173
|
+
fs.writeFileSync(path.join(sandbox, SAMPLE_REL_PATH), SAMPLE_SOURCE, 'utf8');
|
|
174
|
+
const handlerPath = path.join(sandbox, 'demo-handler.cjs');
|
|
175
|
+
fs.writeFileSync(handlerPath, buildHandlerScript(execDelayMs), 'utf8');
|
|
176
|
+
engine = new FerryCatEngine({ dbPath: path.join(sandbox, 'demo-mesh.db') });
|
|
177
|
+
say('');
|
|
178
|
+
say(paint.bold('⚡ FerryCat Zero-Config Sandbox Demo ⚡'));
|
|
179
|
+
say(`${paint.gray('Sandbox:')} ${sandbox}`);
|
|
180
|
+
say(paint.gray('No MCP config. No daemon. Your real workspace and mesh.db are untouched.'));
|
|
181
|
+
// ---------------------------------------------------------------------
|
|
182
|
+
// [1/4] Dispatch — Antigravity locks the pointer fingerprint
|
|
183
|
+
// ---------------------------------------------------------------------
|
|
184
|
+
const dispatchRes = engine.dispatchContract({
|
|
185
|
+
requester_agent: 'antigravity',
|
|
186
|
+
target_agent: 'workbuddy',
|
|
187
|
+
task_type: 'code_review',
|
|
188
|
+
title: 'Review calc.ts for correctness and strict-equality hygiene',
|
|
189
|
+
context_summary: 'Sandbox demo contract. Inspect src/calc.ts and report any correctness or ' +
|
|
190
|
+
'strict-equality violations. This contract is generated by `ferrycat-cli demo`.',
|
|
191
|
+
workspace_root: sandbox,
|
|
192
|
+
pointers: [{ path: SAMPLE_REL_PATH }],
|
|
193
|
+
contract_schema: {
|
|
194
|
+
type: 'object',
|
|
195
|
+
properties: {
|
|
196
|
+
passed: { type: 'boolean' },
|
|
197
|
+
issues: { type: 'array', items: { type: 'string' } },
|
|
198
|
+
},
|
|
199
|
+
required: ['passed', 'issues'],
|
|
200
|
+
additionalProperties: false,
|
|
201
|
+
},
|
|
202
|
+
exec_ttl_sec: execTtlSec,
|
|
203
|
+
});
|
|
204
|
+
contractId = dispatchRes.contract_id;
|
|
205
|
+
const lockedFile = dispatchRes.files[0];
|
|
206
|
+
if (dispatchRes.warning) {
|
|
207
|
+
warnings.push(dispatchRes.warning);
|
|
208
|
+
}
|
|
209
|
+
record(1, 'Contract Dispatched', {
|
|
210
|
+
ID: contractId,
|
|
211
|
+
Actor: `antigravity -> workbuddy ${paint.dim('(task: code_review)')}`,
|
|
212
|
+
Locked: `${lockedFile.path} ${paint.dim(`(sha256: ${shortSha(lockedFile.sha256)})`)}`,
|
|
213
|
+
Status: `${paint.cyan('SUBMITTED')} ${paint.dim('-> queue')}`,
|
|
214
|
+
});
|
|
215
|
+
// ---------------------------------------------------------------------
|
|
216
|
+
// [2/4] Claim — WorkBuddy polls, verifies fingerprints, wins the CAS lease
|
|
217
|
+
// ---------------------------------------------------------------------
|
|
218
|
+
const pollRes = await engine.pollNextTask({ agent_id: 'workbuddy' });
|
|
219
|
+
if (!pollRes.has_task || !pollRes.contract || pollRes.status !== 'CLAIMED') {
|
|
220
|
+
throw new Error(`Demo claim failed: expected CLAIMED, got has_task=${pollRes.has_task} status=${pollRes.status ?? 'undefined'}. ` +
|
|
221
|
+
`${pollRes.message ?? ''}`.trim());
|
|
222
|
+
}
|
|
223
|
+
claimToken = pollRes.contract.claim_token ?? '';
|
|
224
|
+
const claimed = pollRes.contract;
|
|
225
|
+
record(2, 'Contract Claimed', {
|
|
226
|
+
Holder: claimed.target_agent,
|
|
227
|
+
Lease: claimToken || paint.yellow('(none)'),
|
|
228
|
+
Status: `${paint.dim('SUBMITTED ->')} ${paint.yellow('CLAIMED')}`,
|
|
229
|
+
Verify: `${paint.green('fingerprints matched')} ${paint.dim('(0 dirty files)')}`,
|
|
230
|
+
});
|
|
231
|
+
// ---------------------------------------------------------------------
|
|
232
|
+
// [3/4] Supervised execution — real child process, heartbeat, schema gate
|
|
233
|
+
// ---------------------------------------------------------------------
|
|
234
|
+
const execResult = await executeTaskAndFulfill(engine, claimed, { execFile: handlerPath }, {
|
|
235
|
+
onEvent: (event) => {
|
|
236
|
+
if (event.event === 'HEARTBEAT_RENEWED') {
|
|
237
|
+
heartbeatRenewals += 1;
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
if (!execResult.ok) {
|
|
242
|
+
throw new Error(`Supervised execution failed: ${execResult.error ?? execResult.status}`);
|
|
243
|
+
}
|
|
244
|
+
// The authoritative delivery lives on the row, not on the fulfill ack.
|
|
245
|
+
const finalState = engine.inspectMeshState({ contract_id: contractId });
|
|
246
|
+
const finalRow = finalState.contracts[0] ?? {};
|
|
247
|
+
status = String(finalRow.status ?? 'UNKNOWN');
|
|
248
|
+
const structured = finalRow.structured_output;
|
|
249
|
+
if (structured && Array.isArray(structured.issues)) {
|
|
250
|
+
issues = structured.issues.map((item) => String(item));
|
|
251
|
+
}
|
|
252
|
+
verdict = issues.length > 0 ? 'CHANGES_REQUESTED' : 'PASSED';
|
|
253
|
+
record(3, 'Execution & Schema Check', {
|
|
254
|
+
Handler: `${path.basename(handlerPath)} ${paint.dim('(sandboxed child process)')}`,
|
|
255
|
+
Schema: `${paint.green('passed Ajv validation')}`,
|
|
256
|
+
Heartbeat: heartbeatRenewals > 0
|
|
257
|
+
? `${paint.green(`${heartbeatRenewals} lease renewal(s)`)}`
|
|
258
|
+
: paint.dim('no renewal needed (short task)'),
|
|
259
|
+
Verdict: verdict === 'PASSED'
|
|
260
|
+
? paint.green('PASSED')
|
|
261
|
+
: paint.yellow(`CHANGES_REQUESTED ${paint.dim(`(${issues.length} advisory)`)}`),
|
|
262
|
+
});
|
|
263
|
+
// ---------------------------------------------------------------------
|
|
264
|
+
// [4/4] Delivery — second TOCTOU pass then terminal COMPLETED
|
|
265
|
+
// ---------------------------------------------------------------------
|
|
266
|
+
const verifyRes = engine.verifyContract({
|
|
267
|
+
contract_id: contractId,
|
|
268
|
+
agent_id: 'workbuddy',
|
|
269
|
+
});
|
|
270
|
+
dirtyFiles = verifyRes.dirty_files.length;
|
|
271
|
+
if (!verifyRes.valid) {
|
|
272
|
+
throw new Error(`Demo TOCTOU re-verification failed: ${verifyRes.dirty_files.length} dirty file(s).`);
|
|
273
|
+
}
|
|
274
|
+
if (status !== 'COMPLETED') {
|
|
275
|
+
throw new Error(`Demo expected terminal status COMPLETED, got ${status}.`);
|
|
276
|
+
}
|
|
277
|
+
record(4, 'Contract Completed', {
|
|
278
|
+
TOCTOU: `${paint.green(`fingerprints matched (${dirtyFiles} dirty files)`)}`,
|
|
279
|
+
Final: `${paint.green(paint.bold('COMPLETED'))} ${paint.dim(`(elapsed: ${Date.now() - startedAt}ms)`)}`,
|
|
280
|
+
Findings: issues.length === 0
|
|
281
|
+
? paint.dim('none')
|
|
282
|
+
: issues.map((item) => paint.dim(item)).join(`\n${' '.repeat(14)}`),
|
|
283
|
+
});
|
|
284
|
+
succeeded = true;
|
|
285
|
+
return {
|
|
286
|
+
ok: true,
|
|
287
|
+
sandbox,
|
|
288
|
+
sandbox_kept: Boolean(options.keep),
|
|
289
|
+
contract_id: contractId,
|
|
290
|
+
claim_token: claimToken,
|
|
291
|
+
status,
|
|
292
|
+
verdict,
|
|
293
|
+
issues,
|
|
294
|
+
dirty_files: dirtyFiles,
|
|
295
|
+
heartbeat_renewals: heartbeatRenewals,
|
|
296
|
+
elapsed_ms: Date.now() - startedAt,
|
|
297
|
+
steps,
|
|
298
|
+
warnings,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
finally {
|
|
302
|
+
if (engine) {
|
|
303
|
+
try {
|
|
304
|
+
engine.close();
|
|
305
|
+
}
|
|
306
|
+
catch {
|
|
307
|
+
// Closing is best-effort; the sandbox removal below is the real cleanup contract.
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
const retainSandbox = Boolean(options.keep || !succeeded);
|
|
311
|
+
if (retainSandbox) {
|
|
312
|
+
if (options.keep) {
|
|
313
|
+
say('');
|
|
314
|
+
say(`${paint.gray('Sandbox kept at:')} ${sandbox}`);
|
|
315
|
+
say(paint.gray(' Inspect it with: sqlite3 "<sandbox>/demo-mesh.db" ".tables"'));
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
try {
|
|
320
|
+
removeSandbox(sandbox);
|
|
321
|
+
}
|
|
322
|
+
catch (err) {
|
|
323
|
+
warnings.push(`Sandbox cleanup failed (${err instanceof Error ? err.message : String(err)}); remove "${sandbox}" manually.`);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (succeeded) {
|
|
327
|
+
say('');
|
|
328
|
+
say(paint.green(paint.bold(' 🎉 End-to-end multi-agent handoff verified successfully!')));
|
|
329
|
+
say('');
|
|
330
|
+
say(paint.bold(' Next steps:'));
|
|
331
|
+
say(` ${paint.gray('•')} Add to your IDE: ${paint.cyan('npx -y ferrycat')} ${paint.dim('(MCP server entry in mcpServers)')}`);
|
|
332
|
+
say(` ${paint.gray('•')} Inspect contracts: ${paint.cyan('npx ferrycat inspect --target workbuddy')}`);
|
|
333
|
+
say(` ${paint.gray('•')} Keep a sandbox: ${paint.cyan('npx ferrycat demo --keep')}`);
|
|
334
|
+
say(` ${paint.gray('•')} Full CLI help: ${paint.cyan('npx ferrycat --help')}`);
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
say('');
|
|
338
|
+
say(paint.red(' ✖ Demo did not reach a terminal COMPLETED state.'));
|
|
339
|
+
say(paint.gray(` Sandbox retained for debugging: ${sandbox}`));
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
//# sourceMappingURL=demo.js.map
|
package/dist/demo.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo.js","sourceRoot":"","sources":["../src/demo.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.d.ts
CHANGED
|
@@ -53,7 +53,20 @@ export declare class FerryCatEngine {
|
|
|
53
53
|
* Only acquires a write lock if expired active contracts actually exist.
|
|
54
54
|
*/
|
|
55
55
|
private sweepExpiredContractsIfNeeded;
|
|
56
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Evaluates whether a read-only contract carrying `git_patch` can safely operate in
|
|
58
|
+
* Self-Contained Patch Mode (FC-202) when the worker's local disk differs from the
|
|
59
|
+
* requester's working tree snapshot (e.g. different Git branch or disjoint checkout).
|
|
60
|
+
*
|
|
61
|
+
* Security invariant:
|
|
62
|
+
* - All pointer paths MUST still pass `assertSafePointerPath` (sensitive files & symlink escapes are never bypassed).
|
|
63
|
+
* - `git_patch` MUST pass `assertSafeGitPatch` and match `patch_sha256`.
|
|
64
|
+
*
|
|
65
|
+
* R5: every refusal carries a machine-readable `rejectReason` so a POINTER_STALE outcome can
|
|
66
|
+
* tell "your patch is unusable" apart from "the files really drifted on disk".
|
|
67
|
+
*/
|
|
68
|
+
private canAcceptSelfContainedPatch;
|
|
69
|
+
pollNextTask(input?: PollNextTaskInput, nowMs?: number): Promise<PollNextTaskResult>;
|
|
57
70
|
fulfillContract(input: FulfillContractInput, nowMs?: number): FulfillContractResult;
|
|
58
71
|
/**
|
|
59
72
|
* Shared holder guard for every CLAIMED-state mutation (fulfill / release / extend / fail):
|
|
@@ -92,6 +105,7 @@ export declare class FerryCatEngine {
|
|
|
92
105
|
*/
|
|
93
106
|
getLeaseSnapshot(contractId: string): {
|
|
94
107
|
status: string;
|
|
108
|
+
task_type: string;
|
|
95
109
|
claim_token: string | null;
|
|
96
110
|
claimed_at: number | null;
|
|
97
111
|
exec_ttl_sec: number;
|