Compare commits

...
Author SHA1 Message Date
dev-guard b4f4976387 ci: retrigger tests 2026-11-12 01:11:34 +00:00
dev-guard 658d8fb143 fix(queue): accept punctuation after verified custody targets 2026-11-11 20:46:06 +00:00
3 changed files with 40 additions and 1 deletions

No files matched your search

+7
View File
@@ -1395,6 +1395,13 @@ export function queueCommand(depsOverride?: QueueDeps): Command {
.option("--summary <text>", "Summary persisted onto the item (human-seat parks, or standalone summary update without --state)")
.option("--evidence-ref <path>", "Pointer to the durable artifact, persisted onto the item on a human-seat park or a done close (--state done). For a code result, a JSON file of kind openrig.code-result/v1 (repo, base and revision as full commit ids, paths) lets a reader diff it exactly")
.option("--note <text>", "Transition note for the audit log")
.addHelpText("after", `
After reading an existing remote successor, record its exact closure target, including the host:
rig queue update <source-id> --note "custody-verified: receiver@team@remote-host. Registered-host read confirmed the successor"
The note can accompany the closing update or be appended later; a separate note is not required.
A trailing period, comma, semicolon, colon or closing parenthesis is accepted; a longer or different target is not.
For a new cross-host transfer, prefer rig queue handoff --host <registered-host>.
`)
.option("--source <name@external>", "Outside a managed seat: the external routine that appends the --note, recorded as an external actor (claimed:v1), never a seat; note only, on this host's daemon (a --host that resolves to another host is refused). A managed seat stays the actor. Like any note, it resets the item's stall and notification timing (and its recovery and operator episodes) and advances a claimed item's last activity, but never resets how long an unclaimed item has waited")
.option("--host <id>", QUEUE_HOST_ROW_OPTION_HELP)
.option("--full", "Print the whole response row(s) as today, even when output.compact is on (the receipt's waiting keeps only blocker and nextBackstop)")
@@ -290,7 +290,9 @@ function custodyVerifiedTargets(db: Database.Database, qitemId: string, targets:
for (const { transition_note: note } of notes) {
if (!note) continue;
for (const token of note.slice(CUSTODY_VERIFIED_PREFIX.length).trim().split(/\s+/)) {
const named = [token, ...token.split(",").map((t) => t.trim())].filter(Boolean);
const named = [token, ...token.split(",").map((t) => t.trim())]
.filter(Boolean)
.map((t) => targets.includes(t) ? t : t.replace(/[.,;:)]$/, ""));
if (!named.some((t) => targets.includes(t))) continue;
for (const t of named) verified.add(t);
break;
@@ -1767,6 +1767,36 @@ describe("S02 standing stuck sweep — both halves, routed findings, quiet-but-o
expect(await findingsFor(row.qitemId)).toHaveLength(0);
});
it.each(["", ".", ",", ";", ":", ")"])("CUSTODY PUNCTUATION: a closing note accepts the exact target followed by %j", async (punctuation) => {
const row = await mkRow();
const target = "qitem-20990101000000-punctuation@remote-host";
repo.update({ qitemId: row.qitemId, actorSession: "worker@r", state: "done",
closureReason: "handed_off_to", closureTarget: target,
transitionNote: `custody-verified: ${target}${punctuation} registered-host read confirmed the successor` });
await runSweep();
expect(await findingsFor(row.qitemId)).toHaveLength(0);
});
it.each(["x.", ".other.", ":123)"])("CUSTODY PUNCTUATION: extra target characters %j do not verify a prefix", async (suffix) => {
const row = await mkRow();
const target = "qitem-20990101000000-punctuation@remote-host";
repo.update({ qitemId: row.qitemId, actorSession: "worker@r", state: "done",
closureReason: "handed_off_to", closureTarget: target,
transitionNote: `custody-verified: ${target}${suffix} registered-host read confirmed another successor` });
await runSweep();
expect(await findingsFor(row.qitemId)).toHaveLength(1);
});
it("CUSTODY PUNCTUATION: a shortened target is not an exact target", async () => {
const row = await mkRow();
const target = "qitem-20990101000000-punctuation@remote-host";
repo.update({ qitemId: row.qitemId, actorSession: "worker@r", state: "done",
closureReason: "handed_off_to", closureTarget: target,
transitionNote: `custody-verified: ${target.slice(0, -1)}. checked elsewhere` });
await runSweep();
expect(await findingsFor(row.qitemId)).toHaveLength(1);
});
it("DISPOSITION CLOSES THE OPEN FINDING: verification landing after the finding minted auto-closes it on the next sweep, and the finding taught the recipe", async () => {
const row = await mkRow();
const missing = "qitem-20990101000000-precon02";