@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.
Files changed (34) hide show
  1. package/agents/session-analyst.json +28 -0
  2. package/agents/session-review-verifier.json +31 -0
  3. package/agents/session-reviewer.json +32 -0
  4. package/dist/src/claude_invoker.d.ts +26 -0
  5. package/dist/src/claude_invoker.js +57 -1
  6. package/dist/src/claude_invoker.js.map +1 -1
  7. package/dist/src/cli.d.ts +1 -1
  8. package/dist/src/mcp.js +6 -0
  9. package/dist/src/mcp.js.map +1 -1
  10. package/dist/src/runtime.d.ts +16 -0
  11. package/dist/src/runtime.js +43 -12
  12. package/dist/src/runtime.js.map +1 -1
  13. package/dist/src/server.d.ts +20 -0
  14. package/dist/src/server.js +102 -1
  15. package/dist/src/server.js.map +1 -1
  16. package/dist/src/version.d.ts +1 -1
  17. package/dist/src/version.js +1 -1
  18. package/domain_types/session-analysis.json +59 -0
  19. package/domain_types/session-census.json +72 -0
  20. package/domain_types/session-review-verdict.json +48 -0
  21. package/domain_types/session-review.json +86 -0
  22. package/domain_types/session-target.json +26 -0
  23. package/package.json +1 -1
  24. package/releases.json +82 -0
  25. package/skills/gig-census/fixtures/basic.json +33 -0
  26. package/skills/gig-census/fixtures/ledger.jsonl +3 -0
  27. package/skills/gig-census/fixtures/outputs/00000000-0000-4000-8000-00000000cens.jsonl +4 -0
  28. package/skills/gig-census/meta.json +20 -0
  29. package/skills/gig-census/skill.mjs +114 -0
  30. package/skills/session-census/fixtures/basic.json +10 -0
  31. package/skills/session-census/fixtures/sample.jsonl +6 -0
  32. package/skills/session-census/meta.json +25 -0
  33. package/skills/session-census/skill.mjs +141 -0
  34. package/standards/session-review-v0.json +104 -0
@@ -1,5 +1,5 @@
1
1
  /** Engine semver. Keep in lockstep with package.json `version` (enforced by test). */
2
- export declare const COLTRANE_VERSION = "0.24.35";
2
+ export declare const COLTRANE_VERSION = "0.24.37";
3
3
  /**
4
4
  * The commit this engine checkout is sitting on, or null when it can't be determined.
5
5
  *
@@ -17,7 +17,7 @@ import { existsSync, readFileSync, statSync } from "node:fs";
17
17
  import { dirname, join, resolve } from "node:path";
18
18
  import { fileURLToPath } from "node:url";
19
19
  /** Engine semver. Keep in lockstep with package.json `version` (enforced by test). */
20
- export const COLTRANE_VERSION = "0.24.35";
20
+ export const COLTRANE_VERSION = "0.24.37";
21
21
  /**
22
22
  * The commit this engine checkout is sitting on, or null when it can't be determined.
23
23
  *
@@ -0,0 +1,59 @@
1
+ {
2
+ "slug": "session-analysis",
3
+ "version": 1,
4
+ "extends": "Interpretation",
5
+ "domain": "session-review",
6
+ "status": "active",
7
+ "schema": {
8
+ "type": "object",
9
+ "properties": {
10
+ "where_the_cost_went": {
11
+ "type": "array",
12
+ "description": "each finding {finding, evidence, value} — which token class, which tool, which phase carried the bill",
13
+ "items": {
14
+ "type": "object"
15
+ }
16
+ },
17
+ "where_the_time_went": {
18
+ "type": "array",
19
+ "items": {
20
+ "type": "object"
21
+ }
22
+ },
23
+ "rework": {
24
+ "type": "array",
25
+ "description": "work that had to be done twice, with the census evidence that shows it (errors, denials, repeated operator corrections)",
26
+ "items": {
27
+ "type": "object"
28
+ }
29
+ },
30
+ "said_vs_done": {
31
+ "type": "array",
32
+ "description": "where the operator's messages and the tool histogram disagree — what was asked for versus what the session spent itself on",
33
+ "items": {
34
+ "type": "object"
35
+ }
36
+ },
37
+ "turning_points": {
38
+ "type": "array",
39
+ "description": "the moments the session changed direction, each anchored to an operator message",
40
+ "items": {
41
+ "type": "object"
42
+ }
43
+ },
44
+ "caveats": {
45
+ "type": "array",
46
+ "description": "what the census cannot show, stated so the writer does not fill the gap",
47
+ "items": {
48
+ "type": "string"
49
+ }
50
+ }
51
+ }
52
+ },
53
+ "required_fields": [
54
+ "where_the_cost_went",
55
+ "rework",
56
+ "turning_points",
57
+ "caveats"
58
+ ]
59
+ }
@@ -0,0 +1,72 @@
1
+ {
2
+ "slug": "session-census",
3
+ "version": 1,
4
+ "extends": "Signal",
5
+ "domain": "session-review",
6
+ "status": "active",
7
+ "schema": {
8
+ "type": "object",
9
+ "properties": {
10
+ "transcript": {
11
+ "type": "string"
12
+ },
13
+ "bytes": {
14
+ "type": "number"
15
+ },
16
+ "records": {
17
+ "type": "number"
18
+ },
19
+ "span": {
20
+ "type": "object",
21
+ "description": "{first, last} timestamps of the transcript"
22
+ },
23
+ "turns": {
24
+ "type": "object",
25
+ "description": "assistant turns and the token classes they reported, plus the peak context"
26
+ },
27
+ "tools": {
28
+ "type": "array",
29
+ "description": "{name, calls}, most-called first",
30
+ "items": {
31
+ "type": "object"
32
+ }
33
+ },
34
+ "operator_messages": {
35
+ "type": "array",
36
+ "description": "the operator's own messages, identical ones collapsed to {text, count, first, last} — a repeated cron prompt is one decision said many times",
37
+ "items": {
38
+ "type": "object"
39
+ }
40
+ },
41
+ "interruptions": {
42
+ "type": "number"
43
+ },
44
+ "denials": {
45
+ "type": "array",
46
+ "items": {
47
+ "type": "object"
48
+ }
49
+ },
50
+ "errors": {
51
+ "type": "array",
52
+ "items": {
53
+ "type": "object"
54
+ }
55
+ },
56
+ "error": {
57
+ "type": "string",
58
+ "description": "set when the transcript could not be read; the census is then a refusal, not an empty count"
59
+ },
60
+ "source": {
61
+ "type": "string"
62
+ }
63
+ }
64
+ },
65
+ "required_fields": [
66
+ "transcript",
67
+ "records",
68
+ "turns",
69
+ "tools",
70
+ "operator_messages"
71
+ ]
72
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "slug": "session-review-verdict",
3
+ "version": 1,
4
+ "extends": "Verdict",
5
+ "domain": "session-review",
6
+ "status": "active",
7
+ "schema": {
8
+ "type": "object",
9
+ "properties": {
10
+ "pass": {
11
+ "type": "boolean"
12
+ },
13
+ "unsupported_claims": {
14
+ "type": "array",
15
+ "description": "claims whose evidence path is absent from the census, or whose value disagrees with it",
16
+ "items": {
17
+ "type": "object"
18
+ }
19
+ },
20
+ "misquoted_decisions": {
21
+ "type": "array",
22
+ "description": "decisions whose quote does not appear verbatim in the census's operator messages",
23
+ "items": {
24
+ "type": "object"
25
+ }
26
+ },
27
+ "omissions": {
28
+ "type": "array",
29
+ "description": "what the census carries that the review does not mention and should",
30
+ "items": {
31
+ "type": "string"
32
+ }
33
+ },
34
+ "checks": {
35
+ "type": "array",
36
+ "items": {
37
+ "type": "object"
38
+ }
39
+ }
40
+ }
41
+ },
42
+ "required_fields": [
43
+ "pass",
44
+ "checks",
45
+ "unsupported_claims",
46
+ "misquoted_decisions"
47
+ ]
48
+ }
@@ -0,0 +1,86 @@
1
+ {
2
+ "slug": "session-review",
3
+ "version": 1,
4
+ "extends": "Artifact",
5
+ "domain": "session-review",
6
+ "status": "active",
7
+ "schema": {
8
+ "type": "object",
9
+ "properties": {
10
+ "title": {
11
+ "type": "string"
12
+ },
13
+ "span": {
14
+ "type": "string",
15
+ "description": "the session's start and end, from the census"
16
+ },
17
+ "what_happened": {
18
+ "type": "string",
19
+ "description": "the arc of the session in plain prose: what was asked, what was built, what was decided"
20
+ },
21
+ "what_it_cost": {
22
+ "type": "string",
23
+ "description": "the measured shape of the spend and the context, from the census and the ledger rows carried in"
24
+ },
25
+ "what_went_wrong": {
26
+ "type": "string",
27
+ "description": "defects, dead ends, wasted work and their causes — named, not softened"
28
+ },
29
+ "decisions": {
30
+ "type": "array",
31
+ "description": "the operator's decisions, each quoted from their own message in the census",
32
+ "items": {
33
+ "type": "object",
34
+ "properties": {
35
+ "decision": {
36
+ "type": "string"
37
+ },
38
+ "quote": {
39
+ "type": "string"
40
+ }
41
+ },
42
+ "required": [
43
+ "decision",
44
+ "quote"
45
+ ]
46
+ }
47
+ },
48
+ "open": {
49
+ "type": "array",
50
+ "description": "what the session left open",
51
+ "items": {
52
+ "type": "string"
53
+ }
54
+ },
55
+ "claims": {
56
+ "type": "array",
57
+ "description": "every factual claim the prose makes, paired with the census path or ledger field that supports it",
58
+ "items": {
59
+ "type": "object",
60
+ "properties": {
61
+ "text": {
62
+ "type": "string"
63
+ },
64
+ "evidence": {
65
+ "type": "string"
66
+ },
67
+ "value": {
68
+ "type": "string"
69
+ }
70
+ },
71
+ "required": [
72
+ "text",
73
+ "evidence"
74
+ ]
75
+ }
76
+ }
77
+ }
78
+ },
79
+ "required_fields": [
80
+ "title",
81
+ "what_happened",
82
+ "what_it_cost",
83
+ "what_went_wrong",
84
+ "claims"
85
+ ]
86
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "slug": "session-target",
3
+ "version": 1,
4
+ "extends": "Signal",
5
+ "domain": "session-review",
6
+ "status": "active",
7
+ "schema": {
8
+ "type": "object",
9
+ "properties": {
10
+ "transcript": {
11
+ "type": "string",
12
+ "description": "absolute path to one Claude Code session transcript (.jsonl)"
13
+ },
14
+ "label": {
15
+ "type": "string",
16
+ "description": "what this session was, in the operator's words — carried, never inferred"
17
+ },
18
+ "source": {
19
+ "type": "string"
20
+ }
21
+ }
22
+ },
23
+ "required_fields": [
24
+ "transcript"
25
+ ]
26
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eir-labs/coltrane",
3
- "version": "0.24.35",
3
+ "version": "0.24.37",
4
4
  "description": "A methodology engine \u2014 a typed substrate for defining agents, composing multi-phase standards, dispatching gigs, and sealing every output to a content-addressed ledger. Ships as an MCP server.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
package/releases.json CHANGED
@@ -1,6 +1,88 @@
1
1
  {
2
2
  "generated_from": "compileReleases",
3
3
  "releases": [
4
+ {
5
+ "version": "0.24.36",
6
+ "tag": "v0.24.36",
7
+ "date": "2026-09-18T17:21:59+02:00",
8
+ "commits": [
9
+ {
10
+ "sha": "158770e08b12936f976133f8b450d3129107e4b7",
11
+ "subject": "the hosted door validates the payload at post time (#542)"
12
+ }
13
+ ],
14
+ "bump": "patch",
15
+ "laws": {
16
+ "before": 3925,
17
+ "after": 3933,
18
+ "files": 410
19
+ },
20
+ "surface": {
21
+ "mcp_tools": {
22
+ "added": [],
23
+ "removed": []
24
+ },
25
+ "mcp_tool_args": {
26
+ "added": [],
27
+ "removed": []
28
+ },
29
+ "cli_flags": {
30
+ "added": [],
31
+ "removed": []
32
+ },
33
+ "env_vars": {
34
+ "added": [],
35
+ "removed": []
36
+ },
37
+ "domain_types": {
38
+ "added": [],
39
+ "removed": []
40
+ }
41
+ },
42
+ "surface_unread": [],
43
+ "pending": false
44
+ },
45
+ {
46
+ "version": "0.24.35",
47
+ "tag": "v0.24.35",
48
+ "date": "2026-09-18T15:08:15+02:00",
49
+ "commits": [
50
+ {
51
+ "sha": "5693588c2ca04935d120ac8da32ae925ce0e5afe",
52
+ "subject": "no dispatch payload key is silently ignored (#541)"
53
+ }
54
+ ],
55
+ "bump": "patch",
56
+ "laws": {
57
+ "before": 3918,
58
+ "after": 3925,
59
+ "files": 409
60
+ },
61
+ "surface": {
62
+ "mcp_tools": {
63
+ "added": [],
64
+ "removed": []
65
+ },
66
+ "mcp_tool_args": {
67
+ "added": [],
68
+ "removed": []
69
+ },
70
+ "cli_flags": {
71
+ "added": [],
72
+ "removed": []
73
+ },
74
+ "env_vars": {
75
+ "added": [],
76
+ "removed": []
77
+ },
78
+ "domain_types": {
79
+ "added": [],
80
+ "removed": []
81
+ }
82
+ },
83
+ "surface_unread": [],
84
+ "pending": false
85
+ },
4
86
  {
5
87
  "version": "0.24.34",
6
88
  "tag": "v0.24.34",
@@ -0,0 +1,33 @@
1
+ {
2
+ "id": "basic",
3
+ "description": "contract: the census counts what a gig DID \u2014 one amend round for the chair that sealed the same type twice, the failed verdict, the departure, and the spend \u2014 from records shipped with the skill.",
4
+ "input": {
5
+ "gig-target": {
6
+ "gig_id": "00000000-0000-4000-8000-00000000cens",
7
+ "outputs_dir": "skills/gig-census/fixtures/outputs",
8
+ "ledger_path": "skills/gig-census/fixtures/ledger.jsonl"
9
+ }
10
+ },
11
+ "assertions": [
12
+ {
13
+ "path": "gig_id",
14
+ "op": "equals",
15
+ "value": "00000000-0000-4000-8000-00000000cens"
16
+ },
17
+ {
18
+ "path": "chairs.0.amend_rounds",
19
+ "op": "equals",
20
+ "value": 1
21
+ },
22
+ {
23
+ "path": "failed_verdicts",
24
+ "op": "equals",
25
+ "value": 1
26
+ },
27
+ {
28
+ "path": "spend.completed",
29
+ "op": "equals",
30
+ "value": true
31
+ }
32
+ ]
33
+ }
@@ -0,0 +1,3 @@
1
+ {"kind": "chair_spend", "gig_id": "00000000-0000-4000-8000-00000000cens", "role": "make"}
2
+ {"kind": "chair_spend", "gig_id": "00000000-0000-4000-8000-00000000cens", "role": "check"}
3
+ {"kind": "gig", "gig_id": "00000000-0000-4000-8000-00000000cens", "status": "complete"}
@@ -0,0 +1,4 @@
1
+ {"id": "o1", "gig_id": "00000000-0000-4000-8000-00000000cens", "from_role": "make", "agent_slug": "maker", "domain_type": "artifact", "created_at": "2026-09-19T00:00:00Z", "cost_usd": 1.5, "model": "model-a", "data": {"value": "v1"}}
2
+ {"id": "o2", "gig_id": "00000000-0000-4000-8000-00000000cens", "from_role": "check", "agent_slug": "checker", "domain_type": "verdict", "created_at": "2026-09-19T00:01:00Z", "cost_usd": 0.25, "model": "model-b", "data": {"pass": false}}
3
+ {"id": "o3", "gig_id": "00000000-0000-4000-8000-00000000cens", "from_role": "make", "agent_slug": "maker", "domain_type": "artifact", "created_at": "2026-09-19T00:02:00Z", "cost_usd": 1.0, "model": "model-a", "data": {"value": "v2", "departures": [{"from_step": "P1", "instead": "left red", "why": "the law's fixture could not build"}]}}
4
+ {"id": "o4", "gig_id": "00000000-0000-4000-8000-00000000cens", "from_role": "check", "agent_slug": "checker", "domain_type": "verdict", "created_at": "2026-09-19T00:03:00Z", "cost_usd": 0.25, "model": "model-b", "data": {"pass": true}}
@@ -0,0 +1,20 @@
1
+ {
2
+ "slug": "gig-census",
3
+ "version": 1,
4
+ "skill_type": "analysis",
5
+ "permission": { "tier": 1 },
6
+ "determinism_ratio": 1.0,
7
+ "input_type": "gig-target",
8
+ "output_type": "gig-census",
9
+ "output_schema": {
10
+ "type": "object",
11
+ "properties": {
12
+ "gig_id": { "type": "string" },
13
+ "chairs": { "type": "array" },
14
+ "verdicts": { "type": "array" },
15
+ "departures": { "type": "array" },
16
+ "spend": { "type": "object" }
17
+ },
18
+ "required": ["gig_id", "chairs", "spend"]
19
+ }
20
+ }
@@ -0,0 +1,114 @@
1
+ // What a gig ACTUALLY did (determinism 1.0): read the sealed outputs and the ledger rows for one
2
+ // gig_id and count them. This is the evidence half of reconciliation, and it exists so the question
3
+ // "what happened" is never put to the agent that did it — a seat asked to recall its own run will
4
+ // answer with a story, and a story is what a ledger must not accrue.
5
+ //
6
+ // What the agent CAN answer — why, and what it would do differently — is the other half, and it is a
7
+ // hypothesis marked as one, never a finding.
8
+ import { readFileSync, existsSync } from "node:fs";
9
+ import { join } from "node:path";
10
+ import { homedir } from "node:os";
11
+
12
+ const readJsonl = (path) => {
13
+ if (!existsSync(path)) return [];
14
+ const out = [];
15
+ for (const line of readFileSync(path, "utf8").split("\n")) {
16
+ const t = line.trim();
17
+ if (!t) continue;
18
+ try { out.push(JSON.parse(t)); } catch { /* a torn line is not a record */ }
19
+ }
20
+ return out;
21
+ };
22
+
23
+ const ms = (a, b) => (a && b ? Math.max(0, Date.parse(b) - Date.parse(a)) : null);
24
+
25
+ export default async function run(input) {
26
+ const target = (input && typeof input === "object" && input["gig-target"]) || input || {};
27
+ const gig_id = target.gig_id ? String(target.gig_id) : "";
28
+ if (!gig_id) throw new Error("gig-census: no `gig_id` in the input");
29
+
30
+ const outputsDir = target.outputs_dir
31
+ ? String(target.outputs_dir)
32
+ : join(process.env.COLTRANE_OUTPUTS_DIR ?? join(homedir(), ".eir", "coltrane_outputs"), "outputs");
33
+ const ledgerPath = target.ledger_path ? String(target.ledger_path) : join(process.cwd(), ".coltrane", "ledger.jsonl");
34
+
35
+ const outPath = join(outputsDir, `${gig_id}.jsonl`);
36
+ if (!existsSync(outPath)) throw new Error(`gig-census: no sealed outputs for gig "${gig_id}" at ${outPath}`);
37
+ const records = readJsonl(outPath);
38
+
39
+ // Every sealed record, in order, by the chair that sealed it. A role appearing more than once is an
40
+ // AMEND ROUND, which is the single most informative fact about how a gig went.
41
+ const byRole = new Map();
42
+ const seals = [];
43
+ for (const r of records) {
44
+ const role = r.from_role ?? "(none)";
45
+ const slot = byRole.get(role) ?? { role, agent: r.agent_slug, seals: 0, cost_usd: 0, models: new Set(), types: new Set(), perType: new Map() };
46
+ slot.seals += 1;
47
+ // An AMEND ROUND is the same chair sealing the same TYPE again — not the same chair sealing two
48
+ // different types once each. A builder that seals a change-set and a primer in one round is not a
49
+ // builder that ran twice, and counting it as one would put a failure in the ledger that never
50
+ // happened.
51
+ if (r.domain_type) slot.perType.set(r.domain_type, (slot.perType.get(r.domain_type) ?? 0) + 1);
52
+ if (typeof r.cost_usd === "number") slot.cost_usd += r.cost_usd;
53
+ if (r.model) slot.models.add(r.model);
54
+ if (r.domain_type) slot.types.add(r.domain_type);
55
+ byRole.set(role, slot);
56
+ const d = r.data ?? {};
57
+ seals.push({
58
+ at: r.created_at, role, agent: r.agent_slug, type: r.domain_type,
59
+ cost_usd: typeof r.cost_usd === "number" ? r.cost_usd : null,
60
+ model: r.model ?? null,
61
+ ...(typeof d.pass === "boolean" ? { pass: d.pass } : {}),
62
+ ...(Array.isArray(d.departures) && d.departures.length > 0 ? { departures: d.departures.length } : {}),
63
+ });
64
+ }
65
+
66
+ // A verdict that failed, and the departures a maker recorded rather than bridging: the two places a
67
+ // gig says out loud that it did not go cleanly.
68
+ const verdicts = records
69
+ .filter((r) => typeof (r.data ?? {}).pass === "boolean")
70
+ .map((r) => ({ at: r.created_at, role: r.from_role, pass: r.data.pass }));
71
+ const departures = [];
72
+ for (const r of records) {
73
+ for (const dep of (r.data ?? {}).departures ?? []) {
74
+ departures.push({ role: r.from_role, from_step: dep.from_step ?? null, instead: dep.instead ?? null, why: dep.why ?? null });
75
+ }
76
+ }
77
+
78
+ const primers = records
79
+ .filter((r) => r.domain_type === "seat-primer")
80
+ .map((r) => ({ role: r.from_role, agent: r.data?.agent_slug, area: r.data?.area, context_tokens: r.data?.context_tokens ?? null, frontier: r.data?.frontier ?? null, files: (r.data?.files ?? []).length }));
81
+
82
+ const ledgerRows = readJsonl(ledgerPath).filter((row) => row.gig_id === gig_id);
83
+ const spendRows = ledgerRows.filter((row) => row.kind === "chair_spend");
84
+ const gigRows = ledgerRows.filter((row) => row.kind === "gig");
85
+
86
+ const first = records[0]?.created_at ?? null;
87
+ const last = records[records.length - 1]?.created_at ?? null;
88
+ const sealedCost = records.reduce((a, r) => a + (typeof r.cost_usd === "number" ? r.cost_usd : 0), 0);
89
+
90
+ return {
91
+ source: `gig-census://${gig_id}`,
92
+ gig_id,
93
+ span: { first, last, duration_ms: ms(first, last) },
94
+ chairs: [...byRole.values()].map((s) => ({
95
+ role: s.role, agent: s.agent, seals: s.seals,
96
+ amend_rounds: Math.max(0, Math.max(...[...s.perType.values()], 1) - 1),
97
+ cost_usd: Number(s.cost_usd.toFixed(4)),
98
+ models: [...s.models], output_types: [...s.types],
99
+ })),
100
+ seals,
101
+ verdicts,
102
+ failed_verdicts: verdicts.filter((v) => v.pass === false).length,
103
+ departures,
104
+ primers,
105
+ spend: {
106
+ sealed_cost_usd: Number(sealedCost.toFixed(4)),
107
+ chair_spend_rows: spendRows.length,
108
+ gig_rows: gigRows.length,
109
+ // A gig row missing while sealed outputs exist means the gig did not complete — the absence IS
110
+ // the signal (#236), so it is reported rather than defaulted to "complete".
111
+ completed: gigRows.length > 0,
112
+ },
113
+ };
114
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "id": "basic",
3
+ "description": "contract: the census counts a transcript held in the package itself — records, assistant turns, the tool histogram, and the operator's messages with repeats collapsed.",
4
+ "input": { "session-target": { "transcript": "skills/session-census/fixtures/sample.jsonl" } },
5
+ "assertions": [
6
+ { "path": "records", "op": "equals", "value": 6 },
7
+ { "path": "turns.assistant", "op": "equals", "value": 2 },
8
+ { "path": "operator_messages.0.count", "op": "equals", "value": 2 }
9
+ ]
10
+ }
@@ -0,0 +1,6 @@
1
+ {"type": "user", "timestamp": "2026-09-19T00:00:00Z", "message": {"content": "do the thing"}}
2
+ {"type": "assistant", "timestamp": "2026-09-19T00:00:01Z", "message": {"id": "m1", "usage": {"input_tokens": 10, "output_tokens": 5, "cache_read_input_tokens": 100}, "content": [{"type": "tool_use", "name": "Bash", "input": {}}]}}
3
+ {"type": "user", "timestamp": "2026-09-19T00:00:02Z", "message": {"content": [{"type": "tool_result", "content": "ok"}]}}
4
+ {"type": "assistant", "timestamp": "2026-09-19T00:00:03Z", "message": {"id": "m2", "usage": {"input_tokens": 12, "output_tokens": 6}, "content": [{"type": "tool_use", "name": "Bash", "input": {}}]}}
5
+ {"type": "user", "timestamp": "2026-09-19T00:00:04Z", "message": {"content": "do the thing"}}
6
+ {"type": "user", "timestamp": "2026-09-19T00:00:05Z", "message": {"content": "<system-reminder>ignored</system-reminder>"}}
@@ -0,0 +1,25 @@
1
+ {
2
+ "slug": "session-census",
3
+ "version": 1,
4
+ "skill_type": "analysis",
5
+ "permission": { "tier": 1 },
6
+ "determinism_ratio": 1.0,
7
+ "input_type": "session-target",
8
+ "output_type": "session-census",
9
+ "output_schema": {
10
+ "type": "object",
11
+ "properties": {
12
+ "transcript": { "type": "string" },
13
+ "bytes": { "type": "number" },
14
+ "records": { "type": "number" },
15
+ "span": { "type": "object" },
16
+ "turns": { "type": "object" },
17
+ "tools": { "type": "array" },
18
+ "operator_messages": { "type": "array" },
19
+ "interruptions": { "type": "number" },
20
+ "denials": { "type": "array" },
21
+ "errors": { "type": "array" }
22
+ },
23
+ "required": ["transcript", "records", "turns", "tools", "operator_messages"]
24
+ }
25
+ }