@codedology/code-forge 0.13.0 → 0.14.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/CHANGELOG.md +12 -0
- package/README.md +12 -2
- package/docs/reference/blocks.json +153 -1
- package/docs/reference/config.md +2 -0
- package/package.json +1 -1
- package/schema/code-forge.schema.json +8 -0
- package/skill/references/adapters/claude-code.md +1 -1
- package/skill/references/adapters/solo.md +1 -1
- package/skill/references/code.md +3 -3
- package/skill/references/ledger.md +4 -2
- package/skill/references/proof.md +1 -1
- package/skill/references/review.md +13 -6
- package/skill/references/security.md +5 -3
- package/skill/scripts/forge +1 -1
- package/src/cli/block.mjs +103 -31
- package/src/cli/report.mjs +2 -2
- package/src/cli/review-file.mjs +47 -35
- package/src/ledger/export.mjs +1 -1
- package/src/ledger/report.mjs +9 -3
- package/src/review/accept-hit.mjs +78 -0
- package/src/review/agent-waiver.mjs +201 -0
- package/src/review/gate-check.mjs +33 -24
- package/src/review/reopen.mjs +35 -14
- package/src/state/config-snapshot.mjs +1 -0
- package/src/util/forbidden.mjs +22 -0
- package/src/worker/queue.mjs +18 -2
package/src/worker/queue.mjs
CHANGED
|
@@ -300,11 +300,13 @@ export function clearDone({ repoRoot, run, block, file, tree = null }) {
|
|
|
300
300
|
* A crash between the drop and the caller's enqueue leaves a re-runnable ticket with no marker:
|
|
301
301
|
* harmless — its ticket file is pending, and the next `review-file` queues it anyway. Synchronous.
|
|
302
302
|
* @param {string} repoRoot @param {string} ticket @param {Buffer} seen
|
|
303
|
-
*
|
|
303
|
+
* `once` records the join's one retry before releasing the claim. An existing retry marker
|
|
304
|
+
* keeps the result, including when another join has already finished the rerun.
|
|
305
|
+
* @param {{once?: boolean, link?: (from: string, to: string) => void, read?: (file: string) => Buffer, rename?: (from: string, to: string) => void, remove?: (file: string) => void, write?: (file: string, text: string) => void}} [io] - for
|
|
304
306
|
* tests (default `linkSync`, `readFileSync`, `renameSync`, `rmSync` with force, `writeFileSync`
|
|
305
307
|
* with flag `wx` and mode 0o600). A claim that cannot be read is restored the same way and
|
|
306
308
|
* refused `fresh-restore-failed`.
|
|
307
|
-
* @returns {'dropped' | 'gone' | 'changed'}
|
|
309
|
+
* @returns {'dropped' | 'gone' | 'changed' | 'kept'}
|
|
308
310
|
* @throws {WorkerError} `fresh-claim-failed` (the claim could not be taken, or not removed after
|
|
309
311
|
* the drop; nothing was queued) or `fresh-restore-failed` (the message says which state was left:
|
|
310
312
|
* put back, a newer marker, a refused marker, the claim kept, or nothing). A message names an
|
|
@@ -312,6 +314,8 @@ export function clearDone({ repoRoot, run, block, file, tree = null }) {
|
|
|
312
314
|
*/
|
|
313
315
|
export function dropDoneIf(repoRoot, ticket, seen, io = {}) {
|
|
314
316
|
const marker = path.join(queueDir(repoRoot), `${assertTicketId(ticket)}.done`);
|
|
317
|
+
const retried = path.join(queueDir(repoRoot), `${ticket}.retried`);
|
|
318
|
+
if (io.once && existsSync(retried)) return 'kept';
|
|
315
319
|
const claim = `${marker}.${process.pid}.${randomBytes(4).toString('hex')}.fresh`;
|
|
316
320
|
const remove = io.remove ?? ((/** @type {string} */ file) => rmSync(file, { force: true }));
|
|
317
321
|
try {
|
|
@@ -329,6 +333,16 @@ export function dropDoneIf(repoRoot, ticket, seen, io = {}) {
|
|
|
329
333
|
} catch (err) {
|
|
330
334
|
readFailed = codeOf(err);
|
|
331
335
|
}
|
|
336
|
+
let retryFailed = null;
|
|
337
|
+
if (same && io.once) {
|
|
338
|
+
try {
|
|
339
|
+
writeFileSync(retried, `${ticket}\n`, { flag: 'wx', mode: 0o600 });
|
|
340
|
+
} catch (err) {
|
|
341
|
+
// Restore the claim before keeping or refusing it. Only one join can spend the retry.
|
|
342
|
+
retryFailed = codeOf(err);
|
|
343
|
+
same = false;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
332
346
|
if (same) {
|
|
333
347
|
try {
|
|
334
348
|
remove(claim);
|
|
@@ -355,6 +369,8 @@ export function dropDoneIf(repoRoot, ticket, seen, io = {}) {
|
|
|
355
369
|
// the marker is back (or a newer one won), so the ticket is done; `clearDone` removes the claim
|
|
356
370
|
}
|
|
357
371
|
if (readFailed !== null) throw new WorkerError('fresh-restore-failed', `${unread}; ${linkFailed === 'EEXIST' ? 'a newer marker is in place' : 'it was put back'}; nothing was queued`);
|
|
372
|
+
if (retryFailed === 'EEXIST') return 'kept';
|
|
373
|
+
if (retryFailed !== null) throw new WorkerError('fresh-claim-failed', `the retry marker of ticket ${ticket} could not be written (${retryFailed}); the done marker was restored; nothing was queued`);
|
|
358
374
|
return 'changed';
|
|
359
375
|
}
|
|
360
376
|
|