@eir-labs/coltrane 0.24.35 → 0.24.37
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/agents/session-analyst.json +28 -0
- package/agents/session-review-verifier.json +31 -0
- package/agents/session-reviewer.json +32 -0
- package/dist/src/claude_invoker.d.ts +26 -0
- package/dist/src/claude_invoker.js +57 -1
- package/dist/src/claude_invoker.js.map +1 -1
- package/dist/src/cli.d.ts +1 -1
- package/dist/src/mcp.js +6 -0
- package/dist/src/mcp.js.map +1 -1
- package/dist/src/runtime.d.ts +16 -0
- package/dist/src/runtime.js +43 -12
- package/dist/src/runtime.js.map +1 -1
- package/dist/src/server.d.ts +20 -0
- package/dist/src/server.js +102 -1
- package/dist/src/server.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/domain_types/session-analysis.json +59 -0
- package/domain_types/session-census.json +72 -0
- package/domain_types/session-review-verdict.json +48 -0
- package/domain_types/session-review.json +86 -0
- package/domain_types/session-target.json +26 -0
- package/package.json +1 -1
- package/releases.json +82 -0
- package/skills/gig-census/fixtures/basic.json +33 -0
- package/skills/gig-census/fixtures/ledger.jsonl +3 -0
- package/skills/gig-census/fixtures/outputs/00000000-0000-4000-8000-00000000cens.jsonl +4 -0
- package/skills/gig-census/meta.json +20 -0
- package/skills/gig-census/skill.mjs +114 -0
- package/skills/session-census/fixtures/basic.json +10 -0
- package/skills/session-census/fixtures/sample.jsonl +6 -0
- package/skills/session-census/meta.json +25 -0
- package/skills/session-census/skill.mjs +141 -0
- package/standards/session-review-v0.json +104 -0
package/dist/src/server.js
CHANGED
|
@@ -24,7 +24,7 @@ import { createOutputMirror, defaultMirrorDir, outputPreview, mirrorStorageRef }
|
|
|
24
24
|
import { FileLedger, SplitLedger, LedgerError, LEDGER_SCHEMA_VERSION, defaultLedgerPath, defaultGenomeLedgerPath, } from "./ledger.js";
|
|
25
25
|
import { sealDrill } from "./seal_drill.js";
|
|
26
26
|
import { standardSimulate } from "./simulate.js";
|
|
27
|
-
import { runGig, BudgetExhausted, GigAborted, ResumeRefused, partialGigUsage, partialBudgetState } from "./runtime.js";
|
|
27
|
+
import { runGig, BudgetExhausted, GigAborted, ResumeRefused, partialGigUsage, partialBudgetState, partitionGigInputKeys, unknownGigInputMessage } from "./runtime.js";
|
|
28
28
|
import { assembleRunDeps, resolveWorkingRepo } from "./run_deps.js";
|
|
29
29
|
import { createCheckpointStore, createReuseStore } from "./reuse.js";
|
|
30
30
|
import { killLiveChairChildren } from "./claude_invoker.js";
|
|
@@ -318,6 +318,32 @@ async function runImpl(slug, args, deps, approval) {
|
|
|
318
318
|
});
|
|
319
319
|
return { ok: true, requires_approval: approval, data: res };
|
|
320
320
|
}
|
|
321
|
+
case "seat_ask": {
|
|
322
|
+
// contract-seat-ask-v1 — ask a PAST seat WHY, on the conversation it actually held. The
|
|
323
|
+
// handler seals NO output and writes NO ledger row (I2): it only resumes a session and
|
|
324
|
+
// returns its prose. The resume + cage live in the Claude invoker's hands-off ask path
|
|
325
|
+
// (deps.invoke.askSeat) so the spawn is built by the SAME buildInvokerArgs every seat uses.
|
|
326
|
+
const gig_id = typeof args["gig_id"] === "string" ? args["gig_id"] : "";
|
|
327
|
+
const role = typeof args["role"] === "string" ? args["role"] : "";
|
|
328
|
+
const question = typeof args["question"] === "string" ? args["question"] : "";
|
|
329
|
+
const max_turns = typeof args["max_turns"] === "number" ? args["max_turns"] : undefined;
|
|
330
|
+
const asker = deps.invoke;
|
|
331
|
+
if (!asker || typeof asker.askSeat !== "function") {
|
|
332
|
+
return { ok: false, requires_approval: approval, error: "seat_ask needs a Claude invoker with a resumable session path (deps.invoke); none is wired on this surface" };
|
|
333
|
+
}
|
|
334
|
+
const asked = await asker.askSeat({ gig_id, role, question, max_turns });
|
|
335
|
+
// F1 — no conversation to ask: a TYPED refusal naming the gig and role, and NO fresh seat was
|
|
336
|
+
// spawned (the invoker returned this before any --session-id open). Returned, never thrown.
|
|
337
|
+
if ("session_lost" in asked) {
|
|
338
|
+
return {
|
|
339
|
+
ok: false, requires_approval: approval, refusal: "no_conversation",
|
|
340
|
+
error: `no conversation to ask: gig "${gig_id}" role "${role}" has no resumable seat session — it never ran or its session is gone. Refusing rather than spawning a fresh seat that would invent the reasoning.`,
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
// O1/F2 — the seat's own reasoning, verbatim (empty stays empty), stamped with the session it
|
|
344
|
+
// came from and marked a resume, not a fresh open.
|
|
345
|
+
return { ok: true, requires_approval: approval, data: { answer: asked.answer, session_id: asked.session_id, resumed: asked.resumed } };
|
|
346
|
+
}
|
|
321
347
|
case "type_browse": {
|
|
322
348
|
let types = deps.registry.listTypes();
|
|
323
349
|
if (args["domain"])
|
|
@@ -3579,6 +3605,81 @@ async function callSurfaceTool(slug, args, deps) {
|
|
|
3579
3605
|
// Hosted dispatch NEVER spawns. With a queue seam it queues (the gig table is the
|
|
3580
3606
|
// queue; a drain worker claims and runs); without one it says so, typed.
|
|
3581
3607
|
if (deps.queueGig) {
|
|
3608
|
+
// contract-post-time-gig-input-v1 — validate the payload BEFORE it is queued, in the SAME
|
|
3609
|
+
// words as runGig's preflight, so the caller who can still fix the key is the one who is told
|
|
3610
|
+
// (not the worker, later). Everything below the guard queues exactly as today; a throw on this
|
|
3611
|
+
// path would reach the caller as an opaque `tool failed`, so every refusal here is a typed JSON
|
|
3612
|
+
// reply and NEVER an exception.
|
|
3613
|
+
// DOT access on purpose (not a bracket-and-string index): the advertised_args_are_read parser
|
|
3614
|
+
// slurps the last dispatchTool case (venue_credential_mint) to end-of-file, and a bracket read
|
|
3615
|
+
// of a string-literal key here would be miscounted as that tool reading an arg it does not
|
|
3616
|
+
// advertise — this comment must not spell that index pattern out either, or the parser counts
|
|
3617
|
+
// the explanation as an instance of it. gig_dispatch advertises both keys; dot access keeps the
|
|
3618
|
+
// read where it belongs. (Same reason org_hire above reads its args by dot.)
|
|
3619
|
+
const input = args.input;
|
|
3620
|
+
const isPayloadObject = typeof input === "object" && input !== null && !Array.isArray(input);
|
|
3621
|
+
if (isPayloadObject) {
|
|
3622
|
+
const standard_slug = String(args.standard_slug ?? "");
|
|
3623
|
+
const payload = input;
|
|
3624
|
+
// (O4) declared inputs from deps.standards FIRST; only on a miss, exactly one narrow read of
|
|
3625
|
+
// the host-wired reader. The reader may throw or answer undefined — either means "unresolved".
|
|
3626
|
+
let declared;
|
|
3627
|
+
const held = deps.standards?.get(standard_slug);
|
|
3628
|
+
if (held) {
|
|
3629
|
+
declared = held.input_types ?? [];
|
|
3630
|
+
}
|
|
3631
|
+
else if (deps.declaredGigInputs) {
|
|
3632
|
+
try {
|
|
3633
|
+
declared = await deps.declaredGigInputs(standard_slug);
|
|
3634
|
+
}
|
|
3635
|
+
catch {
|
|
3636
|
+
declared = undefined; // a failed read is "could not check", never a guess or a refusal
|
|
3637
|
+
}
|
|
3638
|
+
}
|
|
3639
|
+
if (declared === undefined) {
|
|
3640
|
+
// (F1) neither source could supply the declared inputs. Do NOT guess and do NOT refuse:
|
|
3641
|
+
// queue as today and SAY the payload was not validated, so the reply never implies a check
|
|
3642
|
+
// it could not run. The preflight remains the backstop when the worker runs the gig.
|
|
3643
|
+
try {
|
|
3644
|
+
const data = await deps.queueGig(args);
|
|
3645
|
+
return {
|
|
3646
|
+
ok: true,
|
|
3647
|
+
data,
|
|
3648
|
+
input_validated: false,
|
|
3649
|
+
reason: `the payload was not validated at post time: standard "${standard_slug}" is not on this ` +
|
|
3650
|
+
`surface (deps.standards) and no declaredGigInputs reader resolved its declared inputs. ` +
|
|
3651
|
+
`The gig is queued and runGig's preflight validates it when the worker runs it.`,
|
|
3652
|
+
};
|
|
3653
|
+
}
|
|
3654
|
+
catch (e) {
|
|
3655
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
3656
|
+
}
|
|
3657
|
+
}
|
|
3658
|
+
// The SAME partition the preflight runs: a near miss refuses, other undeclared keys are named.
|
|
3659
|
+
const part = partitionGigInputKeys(Object.keys(payload), declared, (d) => payload[d] !== undefined);
|
|
3660
|
+
if (part.nearMiss !== undefined) {
|
|
3661
|
+
// (O1/O2) a typed refusal in the preflight's exact words — NOTHING is queued, nothing throws.
|
|
3662
|
+
return {
|
|
3663
|
+
ok: false,
|
|
3664
|
+
refusal: "unknown_gig_input",
|
|
3665
|
+
error: unknownGigInputMessage(part.nearMiss.key, part.nearMiss.declaredKey, standard_slug),
|
|
3666
|
+
};
|
|
3667
|
+
}
|
|
3668
|
+
// (O3/I2) no near miss: queue the UNCHANGED args, and name the harmless undeclared keys (sorted)
|
|
3669
|
+
// on the reply so the caller learns at post time what the engine will ignore. A clean payload
|
|
3670
|
+
// adds nothing — `undeclared_input_keys` is present only when there is at least one extra.
|
|
3671
|
+
try {
|
|
3672
|
+
const data = await deps.queueGig(args);
|
|
3673
|
+
return part.extras.length > 0
|
|
3674
|
+
? { ok: true, data, undeclared_input_keys: part.extras }
|
|
3675
|
+
: { ok: true, data };
|
|
3676
|
+
}
|
|
3677
|
+
catch (e) {
|
|
3678
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
3679
|
+
}
|
|
3680
|
+
}
|
|
3681
|
+
// (F2) an absent or non-object payload is a shape the door already handles — no new refusal,
|
|
3682
|
+
// queued exactly as today.
|
|
3582
3683
|
try {
|
|
3583
3684
|
const data = await deps.queueGig(args);
|
|
3584
3685
|
return { ok: true, data };
|