@eir-labs/coltrane 0.4.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/LICENSE +201 -0
- package/README.md +85 -0
- package/agents/anticipation-mapper.json +34 -0
- package/agents/claim-amender.json +34 -0
- package/agents/claim-architect.json +34 -0
- package/agents/claim-rewriter.json +32 -0
- package/agents/delivery-finalizer.json +40 -0
- package/agents/diamond-cutter.json +33 -0
- package/agents/disclosure-analyst.json +26 -0
- package/agents/domain-explorer.json +37 -0
- package/agents/e2e-runner.json +34 -0
- package/agents/e2e-suite-judge.json +26 -0
- package/agents/event-clusterer.json +29 -0
- package/agents/novelty-searcher.json +40 -0
- package/agents/patent-browser-scout.json +49 -0
- package/agents/patent-examiner.json +36 -0
- package/agents/phase_agents/claim-rewriter.md +44 -0
- package/agents/phase_agents/delivery-finalizer.md +30 -0
- package/agents/phase_agents/diamond-cutter.md +47 -0
- package/agents/phase_agents/domain-explorer.md +27 -0
- package/agents/phase_agents/novelty-searcher.md +50 -0
- package/agents/phase_agents/problem-definer.md +32 -0
- package/agents/phase_agents/solution-developer.md +26 -0
- package/agents/phase_agents/verdict-judger.md +70 -0
- package/agents/players/audience-modeler.md +40 -0
- package/agents/players/chain-audit-keeper.md +41 -0
- package/agents/players/illumination-reviewer.md +42 -0
- package/agents/players/methodology-cadence-keeper.md +42 -0
- package/agents/players/substrate-edge-keeper.md +45 -0
- package/agents/prior-art-scout.json +45 -0
- package/agents/problem-definer.json +35 -0
- package/agents/seeds/steve_seed_a.json +12 -0
- package/agents/seeds/steve_seed_b.json +12 -0
- package/agents/seeds/steve_seed_c.json +12 -0
- package/agents/seeds/steve_seed_d.json +12 -0
- package/agents/sensor.json +22 -0
- package/agents/solution-developer.json +35 -0
- package/agents/source-walker.json +38 -0
- package/agents/spec-drafter.json +31 -0
- package/agents/sub_thread_soft_judge.json +26 -0
- package/agents/sub_thread_trace_sensor.json +22 -0
- package/agents/summarizer.json +25 -0
- package/agents/synthesis-writer.json +29 -0
- package/agents/triage-judge.json +39 -0
- package/agents/user_flow_judge.json +26 -0
- package/agents/user_flow_sensor.json +22 -0
- package/agents/verdict-judger.json +39 -0
- package/core_types/artifact.json +17 -0
- package/core_types/interpretation.json +16 -0
- package/core_types/judgment.json +16 -0
- package/core_types/plan.json +16 -0
- package/core_types/signal.json +16 -0
- package/core_types/verdict.json +27 -0
- package/dist/src/access_grant.d.ts +46 -0
- package/dist/src/access_grant.js +76 -0
- package/dist/src/access_grant.js.map +1 -0
- package/dist/src/acoustics.d.ts +9 -0
- package/dist/src/acoustics.js +65 -0
- package/dist/src/acoustics.js.map +1 -0
- package/dist/src/agent_profile.d.ts +36 -0
- package/dist/src/agent_profile.js +57 -0
- package/dist/src/agent_profile.js.map +1 -0
- package/dist/src/bifrost_invoker.d.ts +33 -0
- package/dist/src/bifrost_invoker.js +85 -0
- package/dist/src/bifrost_invoker.js.map +1 -0
- package/dist/src/canonical_core_types.d.ts +2 -0
- package/dist/src/canonical_core_types.js +111 -0
- package/dist/src/canonical_core_types.js.map +1 -0
- package/dist/src/canonical_form.d.ts +55 -0
- package/dist/src/canonical_form.js +93 -0
- package/dist/src/canonical_form.js.map +1 -0
- package/dist/src/charter.d.ts +37 -0
- package/dist/src/charter.js +86 -0
- package/dist/src/charter.js.map +1 -0
- package/dist/src/circle_of_fifths.d.ts +27 -0
- package/dist/src/circle_of_fifths.js +78 -0
- package/dist/src/circle_of_fifths.js.map +1 -0
- package/dist/src/claude_invoker.d.ts +102 -0
- package/dist/src/claude_invoker.js +760 -0
- package/dist/src/claude_invoker.js.map +1 -0
- package/dist/src/coltrane_profile.d.ts +87 -0
- package/dist/src/coltrane_profile.js +132 -0
- package/dist/src/coltrane_profile.js.map +1 -0
- package/dist/src/composition.d.ts +57 -0
- package/dist/src/composition.js +447 -0
- package/dist/src/composition.js.map +1 -0
- package/dist/src/core_types.d.ts +6 -0
- package/dist/src/core_types.js +25 -0
- package/dist/src/core_types.js.map +1 -0
- package/dist/src/document_factory.d.ts +89 -0
- package/dist/src/document_factory.js +176 -0
- package/dist/src/document_factory.js.map +1 -0
- package/dist/src/genome_schema.d.ts +512 -0
- package/dist/src/genome_schema.js +168 -0
- package/dist/src/genome_schema.js.map +1 -0
- package/dist/src/genome_writer.d.ts +67 -0
- package/dist/src/genome_writer.js +179 -0
- package/dist/src/genome_writer.js.map +1 -0
- package/dist/src/gig_song.d.ts +29 -0
- package/dist/src/gig_song.js +56 -0
- package/dist/src/gig_song.js.map +1 -0
- package/dist/src/gig_tracker.d.ts +54 -0
- package/dist/src/gig_tracker.js +109 -0
- package/dist/src/gig_tracker.js.map +1 -0
- package/dist/src/harmonic_validation.d.ts +11 -0
- package/dist/src/harmonic_validation.js +35 -0
- package/dist/src/harmonic_validation.js.map +1 -0
- package/dist/src/hooks.d.ts +27 -0
- package/dist/src/hooks.js +2 -0
- package/dist/src/hooks.js.map +1 -0
- package/dist/src/index.d.ts +36 -0
- package/dist/src/index.js +37 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/jsong.d.ts +47 -0
- package/dist/src/jsong.js +130 -0
- package/dist/src/jsong.js.map +1 -0
- package/dist/src/judges/user_flow_judge.d.ts +89 -0
- package/dist/src/judges/user_flow_judge.js +200 -0
- package/dist/src/judges/user_flow_judge.js.map +1 -0
- package/dist/src/learner.d.ts +37 -0
- package/dist/src/learner.js +30 -0
- package/dist/src/learner.js.map +1 -0
- package/dist/src/ledger.d.ts +225 -0
- package/dist/src/ledger.js +306 -0
- package/dist/src/ledger.js.map +1 -0
- package/dist/src/loader.d.ts +87 -0
- package/dist/src/loader.js +504 -0
- package/dist/src/loader.js.map +1 -0
- package/dist/src/mcp.d.ts +23 -0
- package/dist/src/mcp.js +125 -0
- package/dist/src/mcp.js.map +1 -0
- package/dist/src/modulation_path.d.ts +42 -0
- package/dist/src/modulation_path.js +60 -0
- package/dist/src/modulation_path.js.map +1 -0
- package/dist/src/output_validation.d.ts +19 -0
- package/dist/src/output_validation.js +51 -0
- package/dist/src/output_validation.js.map +1 -0
- package/dist/src/outputs.d.ts +125 -0
- package/dist/src/outputs.js +452 -0
- package/dist/src/outputs.js.map +1 -0
- package/dist/src/overtones.d.ts +42 -0
- package/dist/src/overtones.js +98 -0
- package/dist/src/overtones.js.map +1 -0
- package/dist/src/player_to_claude_code.d.ts +17 -0
- package/dist/src/player_to_claude_code.js +141 -0
- package/dist/src/player_to_claude_code.js.map +1 -0
- package/dist/src/playwright_cage.d.ts +28 -0
- package/dist/src/playwright_cage.js +47 -0
- package/dist/src/playwright_cage.js.map +1 -0
- package/dist/src/polyphony.d.ts +46 -0
- package/dist/src/polyphony.js +91 -0
- package/dist/src/polyphony.js.map +1 -0
- package/dist/src/portfolio.d.ts +52 -0
- package/dist/src/portfolio.js +186 -0
- package/dist/src/portfolio.js.map +1 -0
- package/dist/src/pricing.d.ts +23 -0
- package/dist/src/pricing.js +16 -0
- package/dist/src/pricing.js.map +1 -0
- package/dist/src/registry.d.ts +46 -0
- package/dist/src/registry.js +199 -0
- package/dist/src/registry.js.map +1 -0
- package/dist/src/runtime.d.ts +304 -0
- package/dist/src/runtime.js +1099 -0
- package/dist/src/runtime.js.map +1 -0
- package/dist/src/server.d.ts +88 -0
- package/dist/src/server.js +1692 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/server_entry.d.ts +2 -0
- package/dist/src/server_entry.js +40 -0
- package/dist/src/server_entry.js.map +1 -0
- package/dist/src/server_relay.d.ts +82 -0
- package/dist/src/server_relay.js +341 -0
- package/dist/src/server_relay.js.map +1 -0
- package/dist/src/simulate.d.ts +60 -0
- package/dist/src/simulate.js +72 -0
- package/dist/src/simulate.js.map +1 -0
- package/dist/src/skill_runner.mjs +34 -0
- package/dist/src/skill_subprocess.d.ts +65 -0
- package/dist/src/skill_subprocess.js +132 -0
- package/dist/src/skill_subprocess.js.map +1 -0
- package/dist/src/skills.d.ts +85 -0
- package/dist/src/skills.js +258 -0
- package/dist/src/skills.js.map +1 -0
- package/dist/src/subthread_recorder.d.ts +68 -0
- package/dist/src/subthread_recorder.js +166 -0
- package/dist/src/subthread_recorder.js.map +1 -0
- package/dist/src/tensor_read.d.ts +38 -0
- package/dist/src/tensor_read.js +60 -0
- package/dist/src/tensor_read.js.map +1 -0
- package/dist/src/test_honest_broker.d.ts +34 -0
- package/dist/src/test_honest_broker.js +155 -0
- package/dist/src/test_honest_broker.js.map +1 -0
- package/dist/src/test_topology.d.ts +22 -0
- package/dist/src/test_topology.js +137 -0
- package/dist/src/test_topology.js.map +1 -0
- package/dist/src/tones.d.ts +20 -0
- package/dist/src/tones.js +81 -0
- package/dist/src/tones.js.map +1 -0
- package/dist/src/tool_providers.d.ts +45 -0
- package/dist/src/tool_providers.js +104 -0
- package/dist/src/tool_providers.js.map +1 -0
- package/dist/src/type_versioning.d.ts +23 -0
- package/dist/src/type_versioning.js +31 -0
- package/dist/src/type_versioning.js.map +1 -0
- package/dist/src/version.d.ts +28 -0
- package/dist/src/version.js +86 -0
- package/dist/src/version.js.map +1 -0
- package/domain_types/claim-draft.json +34 -0
- package/domain_types/coverage-report.json +31 -0
- package/domain_types/draft-agent-profile.json +31 -0
- package/domain_types/draft-domain-type.json +28 -0
- package/domain_types/draft-standard.json +46 -0
- package/domain_types/e2e-observation.json +32 -0
- package/domain_types/e2e-report.json +30 -0
- package/domain_types/e2e-target.json +26 -0
- package/domain_types/e2e-verdict.json +26 -0
- package/domain_types/examine-round-record.json +40 -0
- package/domain_types/examiner-rejection.json +28 -0
- package/domain_types/failure-modes.json +31 -0
- package/domain_types/invention-analysis.json +34 -0
- package/domain_types/invention-spec.json +34 -0
- package/domain_types/novelty-analysis.json +28 -0
- package/domain_types/novelty-verdict.json +35 -0
- package/domain_types/parsed-conversation-trace.json +38 -0
- package/domain_types/pattern-extraction.json +62 -0
- package/domain_types/prior-art-hit.json +50 -0
- package/domain_types/project-charter.json +71 -0
- package/domain_types/provisional-draft.json +34 -0
- package/domain_types/raw-note.json +19 -0
- package/domain_types/repo-survey.json +28 -0
- package/domain_types/seeding-verdict.json +70 -0
- package/domain_types/soft-verdict.json +55 -0
- package/domain_types/summary.json +19 -0
- package/domain_types/triage-verdict.json +59 -0
- package/domain_types/user-flow-transcript.json +43 -0
- package/domain_types/user-flow-verdict.json +60 -0
- package/domain_types/verdict-record.json +39 -0
- package/package.json +82 -0
- package/skills/citation-verify/fixtures/basic.json +14 -0
- package/skills/citation-verify/meta.json +10 -0
- package/skills/citation-verify/skill.mjs +26 -0
- package/skills/claim-element-decompose/fixtures/basic.json +11 -0
- package/skills/claim-element-decompose/meta.json +10 -0
- package/skills/claim-element-decompose/skill.mjs +14 -0
- package/skills/diamond-cutting-discipline/fixtures/basic.json +13 -0
- package/skills/diamond-cutting-discipline/meta.json +19 -0
- package/skills/diamond-cutting-discipline/skill.md +46 -0
- package/skills/element-mapping-matrix/fixtures/basic.json +13 -0
- package/skills/element-mapping-matrix/meta.json +10 -0
- package/skills/element-mapping-matrix/skill.mjs +20 -0
- package/skills/number-adder/fixtures/basic.json +9 -0
- package/skills/number-adder/meta.json +10 -0
- package/skills/number-adder/skill.mjs +12 -0
- package/skills/patent-fetch/fixtures/parse.json +18 -0
- package/skills/patent-fetch/meta.json +11 -0
- package/skills/patent-fetch/skill.mjs +34 -0
- package/skills/query-expand/fixtures/basic.json +14 -0
- package/skills/query-expand/meta.json +10 -0
- package/skills/query-expand/skill.mjs +29 -0
- package/skills/run-vitest-band/fixtures/basic.json +9 -0
- package/skills/run-vitest-band/meta.json +18 -0
- package/skills/run-vitest-band/skill.mjs +22 -0
- package/skills/statutory-checklist/fixtures/basic.json +16 -0
- package/skills/statutory-checklist/meta.json +10 -0
- package/skills/statutory-checklist/skill.mjs +25 -0
- package/skills/summarize-tight/fixtures/basic.json +13 -0
- package/skills/summarize-tight/meta.json +20 -0
- package/skills/summarize-tight/skill.md +1 -0
- package/skills/verdict-gate/fixtures/basic.json +9 -0
- package/skills/verdict-gate/meta.json +10 -0
- package/skills/verdict-gate/skill.mjs +82 -0
- package/standards/e2e-suite-v0.json +44 -0
- package/standards/patent-triage-v0.json +98 -0
- package/standards/patent-triage-v1.json +84 -0
- package/standards/seed-from-local-repos-v0.json +115 -0
- package/standards/sub_thread_invocation.json +50 -0
- package/standards/summarize.json +40 -0
- package/standards/synthesis-walk-v0.json +108 -0
- package/standards/user_flow_correctness.json +57 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// player → claude-code agent compile.
|
|
2
|
+
//
|
|
3
|
+
// A Player is a public-facing role-definition that wraps an existing
|
|
4
|
+
// coltrane agent_profile. This module parses a Player from a markdown file
|
|
5
|
+
// with YAML frontmatter and emits a Claude Code agent .md file with the
|
|
6
|
+
// required frontmatter fields (name, description, tools, model) and the
|
|
7
|
+
// player's charter as the body, prefixed with an orientation line.
|
|
8
|
+
//
|
|
9
|
+
// The compile is pure: a parsed Player in, a string out. The CLI script
|
|
10
|
+
// (scripts/compile_players.ts) handles the file I/O.
|
|
11
|
+
//
|
|
12
|
+
// Tool name mapping: coltrane MCP tool slugs (e.g. "agent_define") become
|
|
13
|
+
// claude-code MCP refs (e.g. "mcp__coltrane__agent_define") in the
|
|
14
|
+
// compiled agent's `tools` frontmatter field. The MCP server name in the
|
|
15
|
+
// downstream consumer's .mcp.json must be "coltrane" for the refs to bind.
|
|
16
|
+
const MCP_SERVER_NAME = "coltrane";
|
|
17
|
+
function mapToolToClaudeRef(coltraneSlug) {
|
|
18
|
+
return `mcp__${MCP_SERVER_NAME}__${coltraneSlug}`;
|
|
19
|
+
}
|
|
20
|
+
/** Parse a player .md file body (frontmatter + body) into a Player record.
|
|
21
|
+
* Throws if required fields are missing or the frontmatter delimiters are
|
|
22
|
+
* malformed. Minimal YAML — we only support the exact shape we ship. */
|
|
23
|
+
export function parsePlayer(fileContents) {
|
|
24
|
+
const m = fileContents.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
|
|
25
|
+
if (!m)
|
|
26
|
+
throw new Error("player file missing YAML frontmatter");
|
|
27
|
+
const fm = m[1] ?? "";
|
|
28
|
+
const lines = fm.split(/\r?\n/);
|
|
29
|
+
const fields = {};
|
|
30
|
+
const lists = {};
|
|
31
|
+
let currentList = null;
|
|
32
|
+
let currentBlockKey = null;
|
|
33
|
+
let currentBlockLines = [];
|
|
34
|
+
let currentBlockIndent = 0;
|
|
35
|
+
const flushBlock = () => {
|
|
36
|
+
if (currentBlockKey) {
|
|
37
|
+
fields[currentBlockKey] = currentBlockLines.join("\n").replace(/\s+$/, "");
|
|
38
|
+
currentBlockKey = null;
|
|
39
|
+
currentBlockLines = [];
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
for (const raw of lines) {
|
|
43
|
+
if (currentBlockKey !== null) {
|
|
44
|
+
// inside a |-block; consume indented lines, end on dedent or new key
|
|
45
|
+
const indentMatch = raw.match(/^(\s*)(.*)$/);
|
|
46
|
+
const indent = indentMatch ? (indentMatch[1] ?? "").length : 0;
|
|
47
|
+
const rest = indentMatch ? (indentMatch[2] ?? "") : "";
|
|
48
|
+
if (raw.trim() === "") {
|
|
49
|
+
currentBlockLines.push("");
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (indent >= currentBlockIndent) {
|
|
53
|
+
currentBlockLines.push(raw.slice(currentBlockIndent));
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
// dedent — close block, fall through to normal parsing
|
|
57
|
+
flushBlock();
|
|
58
|
+
// and reprocess this line below
|
|
59
|
+
// (so do NOT continue; fall into the parse below)
|
|
60
|
+
// however we already consumed raw; just re-handle synthetically
|
|
61
|
+
if (rest === "")
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const line = raw;
|
|
65
|
+
const blockMatch = line.match(/^([a-z_]+):\s*\|\s*$/);
|
|
66
|
+
if (blockMatch) {
|
|
67
|
+
currentList = null;
|
|
68
|
+
currentBlockKey = blockMatch[1] ?? null;
|
|
69
|
+
currentBlockLines = [];
|
|
70
|
+
// detect indent from next non-empty line
|
|
71
|
+
currentBlockIndent = 2;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const listStart = line.match(/^([a-z_]+):\s*$/);
|
|
75
|
+
if (listStart) {
|
|
76
|
+
currentList = listStart[1] ?? null;
|
|
77
|
+
if (currentList)
|
|
78
|
+
lists[currentList] = [];
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (currentList) {
|
|
82
|
+
const item = line.match(/^\s+-\s+(.+)$/);
|
|
83
|
+
if (item) {
|
|
84
|
+
const v = (item[1] ?? "").trim();
|
|
85
|
+
lists[currentList]?.push(v);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
currentList = null;
|
|
89
|
+
}
|
|
90
|
+
const kv = line.match(/^([a-z_]+):\s*(.*)$/);
|
|
91
|
+
if (kv) {
|
|
92
|
+
const key = kv[1] ?? "";
|
|
93
|
+
const value = (kv[2] ?? "").trim();
|
|
94
|
+
fields[key] = value;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
flushBlock();
|
|
98
|
+
const required = ["slug", "display_name", "description", "agent_profile_ref", "lane", "charter"];
|
|
99
|
+
for (const r of required) {
|
|
100
|
+
if (!(r in fields) || !fields[r]) {
|
|
101
|
+
throw new Error(`player frontmatter missing required field: ${r}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const toolsAllowlist = lists["tools_allowlist"] ?? [];
|
|
105
|
+
if (toolsAllowlist.length === 0) {
|
|
106
|
+
throw new Error("player frontmatter must list at least one tool in tools_allowlist");
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
slug: fields["slug"],
|
|
110
|
+
display_name: fields["display_name"],
|
|
111
|
+
description: fields["description"],
|
|
112
|
+
agent_profile_ref: fields["agent_profile_ref"],
|
|
113
|
+
lane: fields["lane"],
|
|
114
|
+
tools_allowlist: toolsAllowlist,
|
|
115
|
+
charter: fields["charter"],
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/** Compile a Player into a Claude Code agent .md string.
|
|
119
|
+
* Output shape: YAML frontmatter (name, description, tools, model) + a body
|
|
120
|
+
* with the orientation line and the player's charter. */
|
|
121
|
+
export function compilePlayerToClaudeAgent(player) {
|
|
122
|
+
const name = `coltrane-${player.slug}`;
|
|
123
|
+
const tools = player.tools_allowlist.map(mapToolToClaudeRef).join(", ");
|
|
124
|
+
const toolsList = player.tools_allowlist.map((t) => `- ${mapToolToClaudeRef(t)}`).join("\n");
|
|
125
|
+
const orientation = `You are operating as a coltrane player in the ${player.lane} lane. ` +
|
|
126
|
+
`Your role is: ${player.description} ` +
|
|
127
|
+
`You have access to the following coltrane MCP tools and only these tools:\n\n${toolsList}\n\n` +
|
|
128
|
+
`Use these tools to fulfill the user's request. Do not attempt to use tools outside this allowlist.`;
|
|
129
|
+
const frontmatter = [
|
|
130
|
+
"---",
|
|
131
|
+
`name: ${name}`,
|
|
132
|
+
`description: ${player.description}`,
|
|
133
|
+
`tools: ${tools}`,
|
|
134
|
+
`model: sonnet`,
|
|
135
|
+
`lane: ${player.lane}`,
|
|
136
|
+
`agent_profile_ref: ${player.agent_profile_ref}`,
|
|
137
|
+
"---",
|
|
138
|
+
].join("\n");
|
|
139
|
+
return `${frontmatter}\n\n${orientation}\n\n${player.charter}\n`;
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=player_to_claude_code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"player_to_claude_code.js","sourceRoot":"","sources":["../../src/player_to_claude_code.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface PlaywrightCageOptions {
|
|
2
|
+
/** The nav allowlist — host/origin patterns the browser may reach. Deny-by-default: an empty
|
|
3
|
+
* list means the agent may browse nothing (a browser grant without origins is inert). */
|
|
4
|
+
allowedOrigins: readonly string[];
|
|
5
|
+
/** Origins to explicitly block even if otherwise allowed. */
|
|
6
|
+
blockedOrigins?: readonly string[];
|
|
7
|
+
/** Where Playwright writes its saved session (provenance). Omit to skip session capture. */
|
|
8
|
+
traceDir?: string;
|
|
9
|
+
/** Ephemeral in-memory profile (no persistence). Default true. */
|
|
10
|
+
isolated?: boolean;
|
|
11
|
+
/** Run headless. Default true. */
|
|
12
|
+
headless?: boolean;
|
|
13
|
+
/** Override the package spec (tests/pinning). Default "@playwright/mcp@latest". */
|
|
14
|
+
packageSpec?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface McpServerConfig {
|
|
17
|
+
command: string;
|
|
18
|
+
args: string[];
|
|
19
|
+
}
|
|
20
|
+
/** Build the @playwright/mcp server config for a caged browser. The allowlist + isolation +
|
|
21
|
+
* trace flags are enforced by the server itself, so the cage holds even though the browser runs
|
|
22
|
+
* out-of-process. Deny-by-default: origins not on `allowedOrigins` are refused at navigation. */
|
|
23
|
+
export declare function buildPlaywrightCage(opts: PlaywrightCageOptions): McpServerConfig;
|
|
24
|
+
export type { BrowserGrant } from "./genome_schema.js";
|
|
25
|
+
import type { BrowserGrant } from "./genome_schema.js";
|
|
26
|
+
/** Resolve an agent's declared browser grant into a caged playwright server config (server slug →
|
|
27
|
+
* config). Returns null when the agent declares no browser grant (no caged browser is wired). */
|
|
28
|
+
export declare function playwrightServerFor(grant: BrowserGrant | undefined): McpServerConfig | null;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// The caged browser — coltrane's deny-by-default wrapper over @playwright/mcp. Raw browser
|
|
2
|
+
// automation is powerful and dangerous: an agent with a browser can reach anywhere, persist
|
|
3
|
+
// state, and exfiltrate. This cage hardens it into a safe, declared capability:
|
|
4
|
+
// - nav allowlist (--allowed-origins): the browser can ONLY reach the origins the agent
|
|
5
|
+
// declares — deny-by-default. An off-list navigation is refused by the server itself, not
|
|
6
|
+
// merely discouraged in the prompt.
|
|
7
|
+
// - ephemeral (--isolated): the profile is in-memory, disposed at session end — no cookie
|
|
8
|
+
// or storage bleed across gigs.
|
|
9
|
+
// - headless (--headless): no UI, no human-session hijack.
|
|
10
|
+
// - provenance (--save-session + --output-dir): the MCP session (every navigation + tool
|
|
11
|
+
// call) is written to disk, so "the browser actually went to ppubs.uspto.gov" is an artifact.
|
|
12
|
+
// An agent grants browser tools (mcp__playwright__*) AND declares its allowed origins; coltrane
|
|
13
|
+
// builds the server config from that declaration, so each agent's browser is scoped to exactly
|
|
14
|
+
// what it asked for. Ships default with the repo — the deny-by-default browser is the substrate.
|
|
15
|
+
/** Build the @playwright/mcp server config for a caged browser. The allowlist + isolation +
|
|
16
|
+
* trace flags are enforced by the server itself, so the cage holds even though the browser runs
|
|
17
|
+
* out-of-process. Deny-by-default: origins not on `allowedOrigins` are refused at navigation. */
|
|
18
|
+
export function buildPlaywrightCage(opts) {
|
|
19
|
+
const args = ["-y", opts.packageSpec ?? "@playwright/mcp@latest"];
|
|
20
|
+
if (opts.headless !== false)
|
|
21
|
+
args.push("--headless");
|
|
22
|
+
if (opts.isolated !== false)
|
|
23
|
+
args.push("--isolated");
|
|
24
|
+
// --allowed-origins is the deny-by-default boundary: only these origins load. Always pass it
|
|
25
|
+
// (even empty) so a misconfigured grant fails closed (browses nothing) rather than open.
|
|
26
|
+
args.push("--allowed-origins", opts.allowedOrigins.join(";"));
|
|
27
|
+
if (opts.blockedOrigins && opts.blockedOrigins.length > 0) {
|
|
28
|
+
args.push("--blocked-origins", opts.blockedOrigins.join(";"));
|
|
29
|
+
}
|
|
30
|
+
if (opts.traceDir)
|
|
31
|
+
args.push("--save-session", "--output-dir", opts.traceDir);
|
|
32
|
+
return { command: "npx", args };
|
|
33
|
+
}
|
|
34
|
+
/** Resolve an agent's declared browser grant into a caged playwright server config (server slug →
|
|
35
|
+
* config). Returns null when the agent declares no browser grant (no caged browser is wired). */
|
|
36
|
+
export function playwrightServerFor(grant) {
|
|
37
|
+
if (!grant || !Array.isArray(grant.allowed_origins))
|
|
38
|
+
return null;
|
|
39
|
+
return buildPlaywrightCage({
|
|
40
|
+
allowedOrigins: grant.allowed_origins,
|
|
41
|
+
...(grant.blocked_origins ? { blockedOrigins: grant.blocked_origins } : {}),
|
|
42
|
+
...(grant.trace_dir ? { traceDir: grant.trace_dir } : {}),
|
|
43
|
+
...(grant.isolated !== undefined ? { isolated: grant.isolated } : {}),
|
|
44
|
+
...(grant.headless !== undefined ? { headless: grant.headless } : {}),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=playwright_cage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright_cage.js","sourceRoot":"","sources":["../../src/playwright_cage.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,4FAA4F;AAC5F,gFAAgF;AAChF,2FAA2F;AAC3F,8FAA8F;AAC9F,wCAAwC;AACxC,iGAAiG;AACjG,oCAAoC;AACpC,mEAAmE;AACnE,+FAA+F;AAC/F,kGAAkG;AAClG,gGAAgG;AAChG,+FAA+F;AAC/F,iGAAiG;AAuBjG;;kGAEkG;AAClG,MAAM,UAAU,mBAAmB,CAAC,IAA2B;IAC7D,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,IAAI,wBAAwB,CAAC,CAAC;IAClE,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK;QAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACrD,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK;QAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACrD,6FAA6F;IAC7F,yFAAyF;IACzF,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9D,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1D,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ;QAAE,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,cAAc,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9E,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAClC,CAAC;AASD;kGACkG;AAClG,MAAM,UAAU,mBAAmB,CAAC,KAA+B;IACjE,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC;QAAE,OAAO,IAAI,CAAC;IACjE,OAAO,mBAAmB,CAAC;QACzB,cAAc,EAAE,KAAK,CAAC,eAAe;QACrC,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtE,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type Key } from "./circle_of_fifths.js";
|
|
2
|
+
import type { ModulationPath } from "./modulation_path.js";
|
|
3
|
+
export interface Voice {
|
|
4
|
+
agent_slug: string;
|
|
5
|
+
path: ModulationPath;
|
|
6
|
+
}
|
|
7
|
+
export interface ChordAtPhase {
|
|
8
|
+
phase: string;
|
|
9
|
+
voices: ReadonlyMap<string, Key>;
|
|
10
|
+
pairwise: ReadonlyArray<{
|
|
11
|
+
voice_a: string;
|
|
12
|
+
voice_b: string;
|
|
13
|
+
distance: number;
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
export interface Polyphony {
|
|
17
|
+
voices: readonly Voice[];
|
|
18
|
+
chords: readonly ChordAtPhase[];
|
|
19
|
+
}
|
|
20
|
+
export declare class PolyphonyError extends Error {
|
|
21
|
+
}
|
|
22
|
+
export declare function composeVoices(voices: readonly Voice[]): Polyphony;
|
|
23
|
+
/**
|
|
24
|
+
* Number of voices sounding at a given phase. Feature, not verdict.
|
|
25
|
+
*/
|
|
26
|
+
export declare function voiceCountAtPhase(poly: Polyphony, phase: string): number;
|
|
27
|
+
/**
|
|
28
|
+
* Tonic-density: the n-tonic shape of the chord at a given phase.
|
|
29
|
+
* monotonic (1 voice) · bitonic (2) · tritonic (3) · pentatonic (5) · polyphonic (≥6).
|
|
30
|
+
* Names match Eugene's morning spec.
|
|
31
|
+
*/
|
|
32
|
+
export type TonicDensity = "silence" | "monotonic" | "bitonic" | "tritonic" | "tetratonic" | "pentatonic" | "hexatonic" | "polyphonic";
|
|
33
|
+
export declare function tonicDensity(poly: Polyphony, phase: string): TonicDensity;
|
|
34
|
+
/**
|
|
35
|
+
* Per-phase tonic-density profile across the whole polyphonic structure.
|
|
36
|
+
* Returned as an array of (phase, density) — feature data for a tensor channel.
|
|
37
|
+
*/
|
|
38
|
+
export declare function densityProfile(poly: Polyphony): ReadonlyArray<{
|
|
39
|
+
phase: string;
|
|
40
|
+
density: TonicDensity;
|
|
41
|
+
}>;
|
|
42
|
+
/**
|
|
43
|
+
* Maximum pairwise distance at a given phase. Surfaces "how dissonant" the
|
|
44
|
+
* chord is in circle-of-fifths terms. A NUMBER (0..6), not a pass/fail.
|
|
45
|
+
*/
|
|
46
|
+
export declare function maxDissonanceAtPhase(poly: Polyphony, phase: string): number;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// Multi-voice composition: when multiple agents play together in the sim, they
|
|
2
|
+
// form polyphony. Each agent emits its own modulation_path (its voice). This
|
|
3
|
+
// module composes N voices into a polyphonic read WITHOUT collapsing them into
|
|
4
|
+
// one melodic line — voice independence is preserved; cross-voice coupling is
|
|
5
|
+
// surfaced as feature-data, never as a single verdict.
|
|
6
|
+
import { circleOfFifthsDistance, } from "./circle_of_fifths.js";
|
|
7
|
+
export class PolyphonyError extends Error {
|
|
8
|
+
}
|
|
9
|
+
export function composeVoices(voices) {
|
|
10
|
+
if (voices.length === 0) {
|
|
11
|
+
throw new PolyphonyError("polyphony requires at least one voice");
|
|
12
|
+
}
|
|
13
|
+
// Collect every phase name that any voice visits.
|
|
14
|
+
const phaseOrder = [];
|
|
15
|
+
const seen = new Set();
|
|
16
|
+
for (const v of voices) {
|
|
17
|
+
for (const step of v.path.steps) {
|
|
18
|
+
if (!seen.has(step.phase)) {
|
|
19
|
+
seen.add(step.phase);
|
|
20
|
+
phaseOrder.push(step.phase);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// For each phase, gather which voices are playing + their pairwise distances.
|
|
25
|
+
const chords = phaseOrder.map((phase) => {
|
|
26
|
+
const voicesAtPhase = new Map();
|
|
27
|
+
for (const v of voices) {
|
|
28
|
+
const step = v.path.steps.find((s) => s.phase === phase);
|
|
29
|
+
if (step)
|
|
30
|
+
voicesAtPhase.set(v.agent_slug, step.key);
|
|
31
|
+
}
|
|
32
|
+
const slugs = [...voicesAtPhase.keys()];
|
|
33
|
+
const pairwise = [];
|
|
34
|
+
for (let i = 0; i < slugs.length; i++) {
|
|
35
|
+
for (let j = i + 1; j < slugs.length; j++) {
|
|
36
|
+
const a = slugs[i];
|
|
37
|
+
const b = slugs[j];
|
|
38
|
+
pairwise.push({
|
|
39
|
+
voice_a: a,
|
|
40
|
+
voice_b: b,
|
|
41
|
+
distance: circleOfFifthsDistance(voicesAtPhase.get(a), voicesAtPhase.get(b)),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return { phase, voices: voicesAtPhase, pairwise };
|
|
46
|
+
});
|
|
47
|
+
return { voices, chords };
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Number of voices sounding at a given phase. Feature, not verdict.
|
|
51
|
+
*/
|
|
52
|
+
export function voiceCountAtPhase(poly, phase) {
|
|
53
|
+
const chord = poly.chords.find((c) => c.phase === phase);
|
|
54
|
+
return chord ? chord.voices.size : 0;
|
|
55
|
+
}
|
|
56
|
+
export function tonicDensity(poly, phase) {
|
|
57
|
+
const n = voiceCountAtPhase(poly, phase);
|
|
58
|
+
if (n === 0)
|
|
59
|
+
return "silence";
|
|
60
|
+
if (n === 1)
|
|
61
|
+
return "monotonic";
|
|
62
|
+
if (n === 2)
|
|
63
|
+
return "bitonic";
|
|
64
|
+
if (n === 3)
|
|
65
|
+
return "tritonic";
|
|
66
|
+
if (n === 4)
|
|
67
|
+
return "tetratonic";
|
|
68
|
+
if (n === 5)
|
|
69
|
+
return "pentatonic";
|
|
70
|
+
if (n === 6)
|
|
71
|
+
return "hexatonic";
|
|
72
|
+
return "polyphonic";
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Per-phase tonic-density profile across the whole polyphonic structure.
|
|
76
|
+
* Returned as an array of (phase, density) — feature data for a tensor channel.
|
|
77
|
+
*/
|
|
78
|
+
export function densityProfile(poly) {
|
|
79
|
+
return poly.chords.map((c) => ({ phase: c.phase, density: tonicDensity(poly, c.phase) }));
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Maximum pairwise distance at a given phase. Surfaces "how dissonant" the
|
|
83
|
+
* chord is in circle-of-fifths terms. A NUMBER (0..6), not a pass/fail.
|
|
84
|
+
*/
|
|
85
|
+
export function maxDissonanceAtPhase(poly, phase) {
|
|
86
|
+
const chord = poly.chords.find((c) => c.phase === phase);
|
|
87
|
+
if (!chord || chord.pairwise.length === 0)
|
|
88
|
+
return 0;
|
|
89
|
+
return Math.max(...chord.pairwise.map((p) => p.distance));
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=polyphony.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polyphony.js","sourceRoot":"","sources":["../../src/polyphony.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export interface PortfolioEntry {
|
|
2
|
+
genome_slug: string;
|
|
3
|
+
current_phase: string;
|
|
4
|
+
current_standard_slug: string | null;
|
|
5
|
+
last_touched_utc: string;
|
|
6
|
+
sealed_state_hash: string | null;
|
|
7
|
+
next_natural_action: string;
|
|
8
|
+
parked_at_utc: string | null;
|
|
9
|
+
}
|
|
10
|
+
export declare class SealMismatchError extends Error {
|
|
11
|
+
readonly recorded_hash: string;
|
|
12
|
+
readonly recomputed_hash: string;
|
|
13
|
+
readonly genome_slug: string;
|
|
14
|
+
constructor(genome_slug: string, recorded_hash: string, recomputed_hash: string);
|
|
15
|
+
}
|
|
16
|
+
export declare class PortfolioNotFoundError extends Error {
|
|
17
|
+
readonly genome_slug: string;
|
|
18
|
+
constructor(genome_slug: string);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Lists the portfolio as latest-per-slug. Resume rows override prior park rows
|
|
22
|
+
* for the same slug; park rows override prior resume rows. Order of appearance
|
|
23
|
+
* in the JSONL is the order of truth (append-only).
|
|
24
|
+
*/
|
|
25
|
+
export declare function listPortfolio(genomes_root?: string): PortfolioEntry[];
|
|
26
|
+
/**
|
|
27
|
+
* SHA-seals the current state, marks the project as parked, appends a park row.
|
|
28
|
+
* Returns the parked entry (sealed_state_hash populated, parked_at_utc populated).
|
|
29
|
+
*/
|
|
30
|
+
export declare function parkGenome(genome_slug: string, current_state: object, opts?: {
|
|
31
|
+
current_phase?: string;
|
|
32
|
+
current_standard_slug?: string | null;
|
|
33
|
+
genomes_root?: string;
|
|
34
|
+
}): PortfolioEntry;
|
|
35
|
+
/**
|
|
36
|
+
* Verifies the seal of the most recent park-row for the slug, restores the state,
|
|
37
|
+
* appends a resume row, and returns both.
|
|
38
|
+
*
|
|
39
|
+
* Throws PortfolioNotFoundError if the slug has no park row.
|
|
40
|
+
* Throws SealMismatchError if the recorded state's recomputed hash != recorded hash.
|
|
41
|
+
*/
|
|
42
|
+
export declare function resumeGenome(genome_slug: string, opts?: {
|
|
43
|
+
genomes_root?: string;
|
|
44
|
+
}): {
|
|
45
|
+
entry: PortfolioEntry;
|
|
46
|
+
restored_state: object;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Computes a text description of where the user would naturally pick up.
|
|
50
|
+
* Pure function over an entry; deterministic.
|
|
51
|
+
*/
|
|
52
|
+
export declare function suggestNextAction(entry: PortfolioEntry): string;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
// portfolio.ts — sprint-portfolio primitive.
|
|
2
|
+
//
|
|
3
|
+
// Models a portfolio of in-flight projects, each at its own phase. Append-only
|
|
4
|
+
// .coltrane/portfolio.jsonl is the durable surface; each park/resume appends
|
|
5
|
+
// a row; listPortfolio reduces to latest-per-slug.
|
|
6
|
+
//
|
|
7
|
+
// Storage path resolution (in order):
|
|
8
|
+
// 1. explicit `genomes_root` arg → <root>/.coltrane/portfolio.jsonl
|
|
9
|
+
// 2. process.env.COLTRANE_PORTFOLIO_ROOT → <env>/.coltrane/portfolio.jsonl
|
|
10
|
+
// 3. process.cwd() → <cwd>/.coltrane/portfolio.jsonl
|
|
11
|
+
//
|
|
12
|
+
// Seal: sha256 over canonical-form JSON of the parked state. Same content → same hash.
|
|
13
|
+
import { existsSync, mkdirSync, readFileSync, appendFileSync } from "node:fs";
|
|
14
|
+
import { join, dirname } from "node:path";
|
|
15
|
+
import { canonJson, sha256Hex } from "./canonical_form.js";
|
|
16
|
+
export class SealMismatchError extends Error {
|
|
17
|
+
recorded_hash;
|
|
18
|
+
recomputed_hash;
|
|
19
|
+
genome_slug;
|
|
20
|
+
constructor(genome_slug, recorded_hash, recomputed_hash) {
|
|
21
|
+
super(`seal mismatch for ${genome_slug}: recorded=${recorded_hash} recomputed=${recomputed_hash}`);
|
|
22
|
+
this.name = "SealMismatchError";
|
|
23
|
+
this.genome_slug = genome_slug;
|
|
24
|
+
this.recorded_hash = recorded_hash;
|
|
25
|
+
this.recomputed_hash = recomputed_hash;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export class PortfolioNotFoundError extends Error {
|
|
29
|
+
genome_slug;
|
|
30
|
+
constructor(genome_slug) {
|
|
31
|
+
super(`no portfolio entry for genome_slug=${genome_slug}`);
|
|
32
|
+
this.name = "PortfolioNotFoundError";
|
|
33
|
+
this.genome_slug = genome_slug;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function resolvePortfolioPath(genomes_root) {
|
|
37
|
+
const root = genomes_root ??
|
|
38
|
+
process.env.COLTRANE_PORTFOLIO_ROOT ??
|
|
39
|
+
process.cwd();
|
|
40
|
+
return join(root, ".coltrane", "portfolio.jsonl");
|
|
41
|
+
}
|
|
42
|
+
function ensureParentDir(path) {
|
|
43
|
+
const parent = dirname(path);
|
|
44
|
+
if (!existsSync(parent)) {
|
|
45
|
+
mkdirSync(parent, { recursive: true });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function readAllRows(path) {
|
|
49
|
+
if (!existsSync(path))
|
|
50
|
+
return [];
|
|
51
|
+
const raw = readFileSync(path, "utf-8");
|
|
52
|
+
const rows = [];
|
|
53
|
+
for (const line of raw.split("\n")) {
|
|
54
|
+
const t = line.trim();
|
|
55
|
+
if (!t)
|
|
56
|
+
continue;
|
|
57
|
+
try {
|
|
58
|
+
rows.push(JSON.parse(t));
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// skip malformed lines; honest log-tail tolerance
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return rows;
|
|
65
|
+
}
|
|
66
|
+
function appendRow(path, row) {
|
|
67
|
+
ensureParentDir(path);
|
|
68
|
+
appendFileSync(path, JSON.stringify(row) + "\n");
|
|
69
|
+
}
|
|
70
|
+
function nowUtc() {
|
|
71
|
+
return new Date().toISOString();
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Lists the portfolio as latest-per-slug. Resume rows override prior park rows
|
|
75
|
+
* for the same slug; park rows override prior resume rows. Order of appearance
|
|
76
|
+
* in the JSONL is the order of truth (append-only).
|
|
77
|
+
*/
|
|
78
|
+
export function listPortfolio(genomes_root) {
|
|
79
|
+
const path = resolvePortfolioPath(genomes_root);
|
|
80
|
+
const rows = readAllRows(path);
|
|
81
|
+
const latest = new Map();
|
|
82
|
+
for (const row of rows) {
|
|
83
|
+
if (!row.entry || typeof row.entry.genome_slug !== "string")
|
|
84
|
+
continue;
|
|
85
|
+
latest.set(row.entry.genome_slug, row.entry);
|
|
86
|
+
}
|
|
87
|
+
return Array.from(latest.values()).sort((a, b) => a.genome_slug < b.genome_slug ? -1 : a.genome_slug > b.genome_slug ? 1 : 0);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* SHA-seals the current state, marks the project as parked, appends a park row.
|
|
91
|
+
* Returns the parked entry (sealed_state_hash populated, parked_at_utc populated).
|
|
92
|
+
*/
|
|
93
|
+
export function parkGenome(genome_slug, current_state, opts = {}) {
|
|
94
|
+
const path = resolvePortfolioPath(opts.genomes_root);
|
|
95
|
+
const sealed_state_hash = sha256Hex(canonJson(current_state));
|
|
96
|
+
const now = nowUtc();
|
|
97
|
+
// pull prior phase/standard if not supplied
|
|
98
|
+
const prior = listPortfolio(opts.genomes_root).find((e) => e.genome_slug === genome_slug);
|
|
99
|
+
const current_phase = opts.current_phase ?? prior?.current_phase ?? "voice";
|
|
100
|
+
const current_standard_slug = opts.current_standard_slug !== undefined
|
|
101
|
+
? opts.current_standard_slug
|
|
102
|
+
: (prior?.current_standard_slug ?? null);
|
|
103
|
+
const entry = {
|
|
104
|
+
genome_slug,
|
|
105
|
+
current_phase,
|
|
106
|
+
current_standard_slug,
|
|
107
|
+
last_touched_utc: now,
|
|
108
|
+
sealed_state_hash,
|
|
109
|
+
next_natural_action: "",
|
|
110
|
+
parked_at_utc: now,
|
|
111
|
+
};
|
|
112
|
+
entry.next_natural_action = suggestNextAction(entry);
|
|
113
|
+
appendRow(path, { event: "park", entry, state: current_state });
|
|
114
|
+
return entry;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Verifies the seal of the most recent park-row for the slug, restores the state,
|
|
118
|
+
* appends a resume row, and returns both.
|
|
119
|
+
*
|
|
120
|
+
* Throws PortfolioNotFoundError if the slug has no park row.
|
|
121
|
+
* Throws SealMismatchError if the recorded state's recomputed hash != recorded hash.
|
|
122
|
+
*/
|
|
123
|
+
export function resumeGenome(genome_slug, opts = {}) {
|
|
124
|
+
const path = resolvePortfolioPath(opts.genomes_root);
|
|
125
|
+
const rows = readAllRows(path);
|
|
126
|
+
// find most recent park row for this slug
|
|
127
|
+
let parkRow = null;
|
|
128
|
+
for (let i = rows.length - 1; i >= 0; i--) {
|
|
129
|
+
const row = rows[i];
|
|
130
|
+
if (row !== undefined &&
|
|
131
|
+
row.event === "park" &&
|
|
132
|
+
row.entry &&
|
|
133
|
+
row.entry.genome_slug === genome_slug) {
|
|
134
|
+
parkRow = row;
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (parkRow === null) {
|
|
139
|
+
throw new PortfolioNotFoundError(genome_slug);
|
|
140
|
+
}
|
|
141
|
+
const recorded_hash = parkRow.entry.sealed_state_hash;
|
|
142
|
+
const restored_state = (parkRow.state ?? {});
|
|
143
|
+
const recomputed_hash = sha256Hex(canonJson(restored_state));
|
|
144
|
+
if (recorded_hash === null) {
|
|
145
|
+
// null-sealed park: restore but warn — caller can opt into hard-gate
|
|
146
|
+
}
|
|
147
|
+
else if (recorded_hash !== recomputed_hash) {
|
|
148
|
+
throw new SealMismatchError(genome_slug, recorded_hash, recomputed_hash);
|
|
149
|
+
}
|
|
150
|
+
const now = nowUtc();
|
|
151
|
+
const resumedEntry = {
|
|
152
|
+
genome_slug,
|
|
153
|
+
current_phase: parkRow.entry.current_phase,
|
|
154
|
+
current_standard_slug: parkRow.entry.current_standard_slug,
|
|
155
|
+
last_touched_utc: now,
|
|
156
|
+
sealed_state_hash: null, // resume clears the parked-seal — project is live again
|
|
157
|
+
next_natural_action: "",
|
|
158
|
+
parked_at_utc: null,
|
|
159
|
+
};
|
|
160
|
+
resumedEntry.next_natural_action = suggestNextAction(resumedEntry);
|
|
161
|
+
appendRow(path, { event: "resume", entry: resumedEntry });
|
|
162
|
+
return { entry: resumedEntry, restored_state };
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Computes a text description of where the user would naturally pick up.
|
|
166
|
+
* Pure function over an entry; deterministic.
|
|
167
|
+
*/
|
|
168
|
+
export function suggestNextAction(entry) {
|
|
169
|
+
const phase = entry.current_phase;
|
|
170
|
+
const standard = entry.current_standard_slug ?? "no-standard";
|
|
171
|
+
const parked = entry.parked_at_utc !== null;
|
|
172
|
+
const verbByPhase = {
|
|
173
|
+
voice: "Voice the in-flight thought",
|
|
174
|
+
spin: "Spin up the project genome",
|
|
175
|
+
discover: "Diverge — survey the problem space",
|
|
176
|
+
define: "Converge — name the falsifiable",
|
|
177
|
+
develop: "Generate the files under the sealed charter",
|
|
178
|
+
deliver: "Ripen the verdict",
|
|
179
|
+
"context-switch": "Switch to a different project slug",
|
|
180
|
+
"return-later": "Restore from the sealed park entry",
|
|
181
|
+
};
|
|
182
|
+
const verb = verbByPhase[phase] ?? `Continue at phase=${phase}`;
|
|
183
|
+
const status = parked ? "parked" : "current";
|
|
184
|
+
return `[${status}] ${verb} (standard=${standard})`;
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=portfolio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portfolio.js","sourceRoot":"","sources":["../../src/portfolio.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const DEPTH_MULTIPLIER: {
|
|
2
|
+
readonly skim: 0.5;
|
|
3
|
+
readonly quick: 0.75;
|
|
4
|
+
readonly standard: 1;
|
|
5
|
+
readonly deep: 2;
|
|
6
|
+
};
|
|
7
|
+
export declare const MODEL_MULTIPLIER: {
|
|
8
|
+
readonly economy: 0.5;
|
|
9
|
+
readonly standard: 1;
|
|
10
|
+
readonly premium: 2;
|
|
11
|
+
};
|
|
12
|
+
export type Depth = keyof typeof DEPTH_MULTIPLIER;
|
|
13
|
+
export type ModelTier = keyof typeof MODEL_MULTIPLIER;
|
|
14
|
+
export declare const DEPTHS: readonly Depth[];
|
|
15
|
+
export declare function isDepth(v: unknown): v is Depth;
|
|
16
|
+
export interface CreditInput {
|
|
17
|
+
base_cost: number;
|
|
18
|
+
depth: Depth;
|
|
19
|
+
model_tier: ModelTier;
|
|
20
|
+
agents: number;
|
|
21
|
+
external_tool_calls: number;
|
|
22
|
+
}
|
|
23
|
+
export declare function computeCredits(input: CreditInput): number;
|