@telora/daemon 0.20.89 → 0.20.95
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/build-info.json +2 -2
- package/dist/ci-sensor-loop.d.ts +33 -5
- package/dist/ci-sensor-loop.d.ts.map +1 -1
- package/dist/ci-sensor-loop.js +95 -14
- package/dist/ci-sensor-loop.js.map +1 -1
- package/dist/ci-status-git.d.ts +7 -5
- package/dist/ci-status-git.d.ts.map +1 -1
- package/dist/ci-status-git.js +12 -9
- package/dist/ci-status-git.js.map +1 -1
- package/dist/ci-status.d.ts +21 -6
- package/dist/ci-status.d.ts.map +1 -1
- package/dist/ci-status.js +90 -15
- package/dist/ci-status.js.map +1 -1
- package/dist/cli/connect/agents.d.ts +64 -14
- package/dist/cli/connect/agents.d.ts.map +1 -1
- package/dist/cli/connect/agents.js +102 -19
- package/dist/cli/connect/agents.js.map +1 -1
- package/dist/cli/connect/claude.d.ts +19 -16
- package/dist/cli/connect/claude.d.ts.map +1 -1
- package/dist/cli/connect/claude.js +34 -68
- package/dist/cli/connect/claude.js.map +1 -1
- package/dist/cli/connect/scaffolding.d.ts +3 -2
- package/dist/cli/connect/scaffolding.d.ts.map +1 -1
- package/dist/cli/connect/scaffolding.js +17 -6
- package/dist/cli/connect/scaffolding.js.map +1 -1
- package/dist/cli/connect/seed-retirement.d.ts +39 -0
- package/dist/cli/connect/seed-retirement.d.ts.map +1 -0
- package/dist/cli/connect/seed-retirement.js +95 -0
- package/dist/cli/connect/seed-retirement.js.map +1 -0
- package/dist/cli/connect.d.ts +2 -2
- package/dist/cli/connect.d.ts.map +1 -1
- package/dist/cli/connect.js +8 -2
- package/dist/cli/connect.js.map +1 -1
- package/dist/cli/session-state.d.ts +0 -20
- package/dist/cli/session-state.d.ts.map +1 -1
- package/dist/cli/session-state.js +20 -49
- package/dist/cli/session-state.js.map +1 -1
- package/dist/completion/merge-phase.d.ts +1 -1
- package/dist/completion/merge-phase.d.ts.map +1 -1
- package/dist/completion/merge-phase.js +14 -34
- package/dist/completion/merge-phase.js.map +1 -1
- package/dist/completion/team-lifecycle.d.ts.map +1 -1
- package/dist/completion/team-lifecycle.js +13 -1
- package/dist/completion/team-lifecycle.js.map +1 -1
- package/dist/git/merge.d.ts +16 -0
- package/dist/git/merge.d.ts.map +1 -1
- package/dist/git/merge.js +39 -1
- package/dist/git/merge.js.map +1 -1
- package/dist/product-scaffold.d.ts +8 -6
- package/dist/product-scaffold.d.ts.map +1 -1
- package/dist/product-scaffold.js +14 -10
- package/dist/product-scaffold.js.map +1 -1
- package/dist/queries/cause-key.d.ts +13 -3
- package/dist/queries/cause-key.d.ts.map +1 -1
- package/dist/queries/cause-key.js +14 -4
- package/dist/queries/cause-key.js.map +1 -1
- package/dist/queries/holds.d.ts +11 -2
- package/dist/queries/holds.d.ts.map +1 -1
- package/dist/queries/holds.js +11 -2
- package/dist/queries/holds.js.map +1 -1
- package/dist/templates/agents-md.d.ts +16 -0
- package/dist/templates/agents-md.d.ts.map +1 -1
- package/dist/templates/agents-md.js +26 -0
- package/dist/templates/agents-md.js.map +1 -1
- package/dist/templates/claude-md.d.ts +1 -1
- package/dist/templates/claude-md.d.ts.map +1 -1
- package/dist/templates/claude-md.js +0 -20
- package/dist/templates/claude-md.js.map +1 -1
- package/dist/templates/claude-settings.d.ts +44 -1
- package/dist/templates/claude-settings.d.ts.map +1 -1
- package/dist/templates/claude-settings.js +73 -1
- package/dist/templates/claude-settings.js.map +1 -1
- package/dist/unified-shell-provisioning.d.ts +99 -0
- package/dist/unified-shell-provisioning.d.ts.map +1 -0
- package/dist/unified-shell-provisioning.js +222 -0
- package/dist/unified-shell-provisioning.js.map +1 -0
- package/dist/unified-shell.d.ts +0 -41
- package/dist/unified-shell.d.ts.map +1 -1
- package/dist/unified-shell.js +19 -135
- package/dist/unified-shell.js.map +1 -1
- package/package.json +1 -1
|
@@ -29,7 +29,7 @@ export declare const TELORA_CLAUDE_MD_END = "<!-- END TELORA SEED -->";
|
|
|
29
29
|
* For Codex: the MCP server is registered in `~/.codex/config.toml` (global).
|
|
30
30
|
*/
|
|
31
31
|
export declare const SEED_MCP_REGISTRATION_SENTENCE = "The Telora MCP server is registered in `.mcp.json`.";
|
|
32
|
-
export declare const SEED_BODY = "# Telora workstation context\n\nThis repo is connected to Telora -- a differential control plane for\nsoftware delivery. Intent and reality are paired signals; the meaningful\nwork happens at the difference.\n\n## Before you write any code (read this first)\n\nDEFAULT: on a Telora-connected workstation, a new capability starts as\n**declared intent** before any code. When the user says \"I want to build\nX\", your first move is NOT to scaffold X -- it is to declare it: create\n(or select) a Focus -> delivery -> issue and move an issue to **In\nProgress**. Code is written only after intent is anchored above it.\n\nThis polarity is deliberate and easy to get backwards. Building directly\nin the working tree -- scaffolding, installing dependencies, starting a\ndev server, writing application files -- is the **exception**, taken ONLY\nwhen the user explicitly asks for it. Recognized bypass phrases:\n\"build locally\", \"just write it\", \"skip Telora\", \"don't track this\",\n\"throwaway\". Absent an explicit signal like these, treat any build\nrequest as a request to declare intent in Telora first.\n\nAsking good clarifying questions about stack, scope, or dependencies is\nNOT a substitute for this step -- that is execution-layer scoping, and it\ncomes *after* the capability is declared, not instead of it. Scoping is\nagent work; declaring that a capability matters is the part that must\nland in Telora first.\n\n**Surface the fork; do not silently pick it.** The common failure is\nresolving an ambiguous request toward the path of least resistance --\ne.g. reading \"a web app I run locally on my LAN\" (a deployment target) as\n\"build locally\" (skip Telora). When intent is not already explicit, your\nFIRST response to a build request names the choice rather than assuming\nit: \"I'll scope this in Telora unless you want it built locally -- which?\"\nOne question, once, at the start. Let the user pick; never pick for them\nby starting to type code.\n\n**First action rule.** On a build / new-capability request, your first\ntool call is a Telora planning call (telora_product_focus / _delivery /\n_issue) OR the fork question above -- never Write, Edit, or a code-running\nBash command. If the first move cannot be code, building-before-intent\ncannot happen.\n\nWhy: an artifact with no declared intent above it is reality moving with\nnothing to measure it against -- pure noise to the differential loop. The\nwhole system is built to compute intent-minus-reality; code that skips\nthe intent half defeats the instrument.\n\n## Execution polarity (which path executes this?)\n\nOnce intent is declared, a second polarity governs HOW it executes -- and it\nhas the same default-and-exception shape as the intent polarity above. A\ndeclared focus is handed to the **daemon team + review loop** by default.\nTeam execution IS THE DEFAULT; building it inline yourself in this interactive\nsession is the **explicit, named bypass**, taken ONLY when the user says so.\n\nThree execution forks recur. On each, the left side is the default and the\nright side is the effortful, must-be-named bypass:\n\n- **Daemon team + review vs. inline coding.** Default: hand the focus to the\n daemon team, which executes and runs it through the review gate. Bypass:\n build it inline in this session -- only on an explicit signal.\n- **Tree-anchored delivery vs. unanchored delivery.** Default: anchor each\n delivery to a reality-tree injection. Bypass: an unanchored delivery\n (`allowUnanchored`) -- a deliberate, reason-bearing act, not a silent flag.\n- **Review-gated Done vs. self-marked Done.** Default: work is confirmed Done\n by the review gate. Bypass: marking your own work Done without review.\n\nThe recognized signal that switches execution to inline is an explicit\n\"build it now\" (and the same throwaway phrases that bypass the intent step:\n\"build locally\", \"just write it\", \"skip Telora\", \"don't track this\",\n\"throwaway\"). Absent such a signal, hand off to the team -- do not fill the\nchoice with the lowest-resistance path (typing code yourself).\n\n**Surface the fork; do not silently pick it.** When the execution path is not\nalready explicit, your response NAMES the choice rather than assuming it:\n\"I'll hand this to the daemon team + review unless you want it built inline\nnow -- which?\" One question, once. Let the user pick; never default to inline\nby starting to type code.\n\n## Planning hierarchy\n\n- **Focus** = the context that defines an area of work -- not \"one\n capability.\" All phases of building within that area belong in one\n focus; if a \"focus\" is really just one phase, fold it back in.\n- **Delivery** = a shippable phase or major component of a capability.\n- **Context Group** = optional grouping of related issues that share\n meaningful context (relevant files, architectural notes). A CG earns its\n existence by carrying context, not by being a folder.\n- **Task** = one discrete implementable unit. Bounded files, focused\n session. Multiple \"and\" clauses across different concerns means split.\n\nScope by purpose, not count. The right number of deliveries is however\nmany phases the work naturally has.\n\n## PRD: \"build a working app in one run\"\n\nA **PRD** sits one altitude above Focus (Product -> PRD -> Focus): a\nbounded, verifiable, retire-able milestone carrying a **Prerequisite Tree**\nof `goal` / `obstacle` / `overcome` nodes. Each `overcome` materializes\nas a focus; the daemon progressively arms the **frontier** of foci as\nupstream obstacles clear. This is the entry point a user means by \"build a\nfully working app in one go.\"\n\nIt is NOT big-bang generation: you author the tree once, commit a path,\nand the differential loop walks the frontier to completion -- the execution\nunderneath is still the normal focus -> delivery -> issue + review loop.\n\nThe PRD tools are **lazy-loaded** -- they do not exist until you load the\ndomain. If you don't see `telora_prd` / `telora_prd_tree`, run:\n\n```\ntelora_discover { action: \"load\", domain: \"prd\" }\n```\n\nThen: `telora_prd` create (referencing a Vision) -> `telora_prd_tree`\nauthor nodes (an obstacle's `clearancePredicate` is OPTIONAL and advisory --\nthe frontier advances as upstream obstacles clear via focus-completion, i.e.\neach overcome's focus finishing its deliveries' verify gates, not via a\nper-obstacle predicate) + edges -> commit a pathway -> `materialize_overcome`\neach into a focus -> arm the daemon PRD loop. All authoring is harness+MCP;\nthere is no Telora authoring UI.\n\n## Issue workflow\n\n`To Do` -> `In Progress` -> `In Review` / `Blocked` -> `Done`.\n\nIssue types: **Context Group**, **Task**, **Bug**.\n\nMovement rules:\n\n- An issue MUST be set to `In Progress` before any work begins on it.\n- Never skip `In Progress`. Never move directly from `To Do` to `Done`.\n- Set status with `telora_product_issue` action=update.\n\nDelivery and focus stages advance automatically based on issue\nactivity. Agents never set delivery executionStatus directly.\n\n## MCP tool surface (what's available in this session)\n\nThe Telora MCP server is registered in `.mcp.json`. Core tool families:\n\n- `telora_product` -- list/get/create/update products\n- `telora_product_focus` -- focuses under a product\n- `telora_product_delivery` -- deliveries under a focus\n- `telora_product_issue` -- issues (Context Groups, Tasks, Bugs) under a delivery\n- `telora_agent` -- agent roles, escalation requests\n- `telora_loop_*` -- loop documents, questions, answers\n- `telora_discover` -- on-demand registration of deferred tool domains\n\nResolve the live tool list at runtime via `telora_discover` rather than\nhard-coding a list that drifts.\n\n## Human-vs-agent boundaries\n\n- Humans own **intent** and **completion**.\n - Intent: what capability matters, what changes when. Pre-handoff.\n - Completion: closing the loop on whether a focus is done. Post-handoff.\n- Agents own **scoping** and **execution**.\n - Scoping: decomposing a focus into deliveries, deliveries into\n issues, restructuring mid-flight as the agent learns more.\n - Execution: writing code, running tests, committing, reporting.\n\nDo not ask humans for operational details they expect the agent to figure\nout. Do not silently complete a focus on the human's behalf. Escalate\nwhen stuck via `telora_agent` action=escalate.\n\nWhen communicating with a human, refer to focuses, deliveries, and issues\nby their **title**, never their UUID. UUIDs are for tool calls only and must\nnot be surfaced in chat. MCP tool results carry both, so this is a\ncommunication choice, not a data-availability problem: keep the id in the\ntool call, name the work by its title in the conversation.\n\n## Commit attribution\n\nDeliveries on a focus share one branch, so their commits interleave. Every\ncommit you make for a delivery MUST carry a git trailer naming that delivery:\n\n```\nTelora-Delivery: <deliveryId>\n```\n\n- `<deliveryId>` is the delivery UUID whose work the commit advances (not the\n issue id, not the focus id). E.g.\n `git commit -m \"<subject>\" -m \"Telora-Delivery: <deliveryId>\"`.\n- One delivery per commit; split a change that spans two deliveries.\n- Merge-resolution / housekeeping commits carry no trailer.\n\nThe verify gate partitions the recorded commit set by this trailer to judge each\ndelivery against its OWN work and to prove its evidence is complete. A missing\ntrailer never corrupts a sibling -- at worst this delivery's evidence becomes\nunvouchable and the gate re-queues it instead of rendering a verdict.\n\n## Differential signaling\n\nTelora is asymmetric: it moves reality toward intent, never the reverse.\nAgents do not lower the bar to make signals look better -- they escalate.\nEvery artifact (commit, work summary, gate result) is signal toward the\ndeclared intent; raw activity without intent reduction is noise.\n\nA short corrective comment from the user is high-signal -- treat brief\npushback as the most important input in the session.\n\n## Workflows and policies\n\n- **Workflow**: stage directives shape agent behavior at discrete\n transitions. What context the agent sees (assembly recipes), what tools\n it can use, how it thinks (prompt + model). Live in Telora's\n `workflow_stages.agent_directive` JSONB.\n- **Policy** (organizational, deferred): cross-cutting constraints that\n feed into stage directives.\n\nWhen you cross a stage transition, the daemon may inject context or spawn\na fresh sub-agent per the directive. Don't override that flow without a\nclear reason.\n";
|
|
32
|
+
export declare const SEED_BODY = "# Telora workstation context\n\nThis repo is connected to Telora -- a differential control plane for\nsoftware delivery. Intent and reality are paired signals; the meaningful\nwork happens at the difference.\n\n## Before you write any code (read this first)\n\nDEFAULT: on a Telora-connected workstation, a new capability starts as\n**declared intent** before any code. When the user says \"I want to build\nX\", your first move is NOT to scaffold X -- it is to declare it: create\n(or select) a Focus -> delivery -> issue and move an issue to **In\nProgress**. Code is written only after intent is anchored above it.\n\nThis polarity is deliberate and easy to get backwards. Building directly\nin the working tree -- scaffolding, installing dependencies, starting a\ndev server, writing application files -- is the **exception**, taken ONLY\nwhen the user explicitly asks for it. Recognized bypass phrases:\n\"build locally\", \"just write it\", \"skip Telora\", \"don't track this\",\n\"throwaway\". Absent an explicit signal like these, treat any build\nrequest as a request to declare intent in Telora first.\n\nAsking good clarifying questions about stack, scope, or dependencies is\nNOT a substitute for this step -- that is execution-layer scoping, and it\ncomes *after* the capability is declared, not instead of it. Scoping is\nagent work; declaring that a capability matters is the part that must\nland in Telora first.\n\n**Surface the fork; do not silently pick it.** The common failure is\nresolving an ambiguous request toward the path of least resistance --\ne.g. reading \"a web app I run locally on my LAN\" (a deployment target) as\n\"build locally\" (skip Telora). When intent is not already explicit, your\nFIRST response to a build request names the choice rather than assuming\nit: \"I'll scope this in Telora unless you want it built locally -- which?\"\nOne question, once, at the start. Let the user pick; never pick for them\nby starting to type code.\n\n**First action rule.** On a build / new-capability request, your first\ntool call is a Telora planning call (telora_product_focus / _delivery /\n_issue) OR the fork question above -- never Write, Edit, or a code-running\nBash command. If the first move cannot be code, building-before-intent\ncannot happen.\n\nWhy: an artifact with no declared intent above it is reality moving with\nnothing to measure it against -- pure noise to the differential loop. The\nwhole system is built to compute intent-minus-reality; code that skips\nthe intent half defeats the instrument.\n\n## Execution polarity (which path executes this?)\n\nOnce intent is declared, a second polarity governs HOW it executes -- and it\nhas the same default-and-exception shape as the intent polarity above. A\ndeclared focus is handed to the **daemon team + review loop** by default.\nTeam execution IS THE DEFAULT; building it inline yourself in this interactive\nsession is the **explicit, named bypass**, taken ONLY when the user says so.\n\nThree execution forks recur. On each, the left side is the default and the\nright side is the effortful, must-be-named bypass:\n\n- **Daemon team + review vs. inline coding.** Default: hand the focus to the\n daemon team, which executes and runs it through the review gate. Bypass:\n build it inline in this session -- only on an explicit signal.\n- **Tree-anchored delivery vs. unanchored delivery.** Default: anchor each\n delivery to a reality-tree injection. Bypass: an unanchored delivery\n (`allowUnanchored`) -- a deliberate, reason-bearing act, not a silent flag.\n- **Review-gated Done vs. self-marked Done.** Default: work is confirmed Done\n by the review gate. Bypass: marking your own work Done without review.\n\nThe recognized signal that switches execution to inline is an explicit\n\"build it now\" (and the same throwaway phrases that bypass the intent step:\n\"build locally\", \"just write it\", \"skip Telora\", \"don't track this\",\n\"throwaway\"). Absent such a signal, hand off to the team -- do not fill the\nchoice with the lowest-resistance path (typing code yourself).\n\n**Surface the fork; do not silently pick it.** When the execution path is not\nalready explicit, your response NAMES the choice rather than assuming it:\n\"I'll hand this to the daemon team + review unless you want it built inline\nnow -- which?\" One question, once. Let the user pick; never default to inline\nby starting to type code.\n\n## Planning hierarchy\n\n- **Focus** = the context that defines an area of work -- not \"one\n capability.\" All phases of building within that area belong in one\n focus; if a \"focus\" is really just one phase, fold it back in.\n- **Delivery** = a shippable phase or major component of a capability.\n- **Context Group** = optional grouping of related issues that share\n meaningful context (relevant files, architectural notes). A CG earns its\n existence by carrying context, not by being a folder.\n- **Task** = one discrete implementable unit. Bounded files, focused\n session. Multiple \"and\" clauses across different concerns means split.\n\nScope by purpose, not count. The right number of deliveries is however\nmany phases the work naturally has.\n\n## PRD: \"build a working app in one run\"\n\nA **PRD** sits one altitude above Focus (Product -> PRD -> Focus): a\nbounded, verifiable, retire-able milestone carrying a **Prerequisite Tree**\nof `goal` / `obstacle` / `overcome` nodes. Each `overcome` materializes\nas a focus; the daemon progressively arms the **frontier** of foci as\nupstream obstacles clear. This is the entry point a user means by \"build a\nfully working app in one go.\"\n\nIt is NOT big-bang generation: you author the tree once, commit a path,\nand the differential loop walks the frontier to completion -- the execution\nunderneath is still the normal focus -> delivery -> issue + review loop.\n\nThe PRD tools are **lazy-loaded** -- they do not exist until you load the\ndomain. If you don't see `telora_prd` / `telora_prd_tree`, run:\n\n```\ntelora_discover { action: \"load\", domain: \"prd\" }\n```\n\nThen: `telora_prd` create (referencing a Vision) -> `telora_prd_tree`\nauthor nodes (an obstacle's `clearancePredicate` is OPTIONAL and advisory --\nthe frontier advances as upstream obstacles clear via focus-completion, i.e.\neach overcome's focus finishing its deliveries' verify gates, not via a\nper-obstacle predicate) + edges -> commit a pathway -> `materialize_overcome`\neach into a focus -> arm the daemon PRD loop. All authoring is harness+MCP;\nthere is no Telora authoring UI.\n\n## Issue workflow\n\n`To Do` -> `In Progress` -> `In Review` / `Blocked` -> `Done`.\n\nIssue types: **Context Group**, **Task**, **Bug**.\n\nMovement rules:\n\n- An issue MUST be set to `In Progress` before any work begins on it.\n- Never skip `In Progress`. Never move directly from `To Do` to `Done`.\n- Set status with `telora_product_issue` action=update.\n\nDelivery and focus stages advance automatically based on issue\nactivity. Agents never set delivery executionStatus directly.\n\n## MCP tool surface (what's available in this session)\n\nThe Telora MCP server is registered in `.mcp.json`. Core tool families:\n\n- `telora_product` -- list/get/create/update products\n- `telora_product_focus` -- focuses under a product\n- `telora_product_delivery` -- deliveries under a focus\n- `telora_product_issue` -- issues (Context Groups, Tasks, Bugs) under a delivery\n- `telora_agent` -- agent roles, escalation requests\n- `telora_loop_*` -- loop documents, questions, answers\n- `telora_discover` -- on-demand registration of deferred tool domains\n\nResolve the live tool list at runtime via `telora_discover` rather than\nhard-coding a list that drifts.\n\n## Human-vs-agent boundaries\n\n- Humans own **intent** and **completion**.\n - Intent: what capability matters, what changes when. Pre-handoff.\n - Completion: closing the loop on whether a focus is done. Post-handoff.\n- Agents own **scoping** and **execution**.\n - Scoping: decomposing a focus into deliveries, deliveries into\n issues, restructuring mid-flight as the agent learns more.\n - Execution: writing code, running tests, committing, reporting.\n\nDo not ask humans for operational details they expect the agent to figure\nout. Do not silently complete a focus on the human's behalf. Escalate\nwhen stuck via `telora_agent` action=escalate.\n\nWhen communicating with a human, refer to focuses, deliveries, and issues\nby their **title**, never their UUID. UUIDs are for tool calls only and must\nnot be surfaced in chat. MCP tool results carry both, so this is a\ncommunication choice, not a data-availability problem: keep the id in the\ntool call, name the work by its title in the conversation.\n\n## Differential signaling\n\nTelora is asymmetric: it moves reality toward intent, never the reverse.\nAgents do not lower the bar to make signals look better -- they escalate.\nEvery artifact (commit, work summary, gate result) is signal toward the\ndeclared intent; raw activity without intent reduction is noise.\n\nA short corrective comment from the user is high-signal -- treat brief\npushback as the most important input in the session.\n\n## Workflows and policies\n\n- **Workflow**: stage directives shape agent behavior at discrete\n transitions. What context the agent sees (assembly recipes), what tools\n it can use, how it thinks (prompt + model). Live in Telora's\n `workflow_stages.agent_directive` JSONB.\n- **Policy** (organizational, deferred): cross-cutting constraints that\n feed into stage directives.\n\nWhen you cross a stage transition, the daemon may inject context or spawn\na fresh sub-agent per the directive. Don't override that flow without a\nclear reason.\n";
|
|
33
33
|
/**
|
|
34
34
|
* Render a fresh-repo CLAUDE.md.
|
|
35
35
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-md.d.ts","sourceRoot":"","sources":["../../src/templates/claude-md.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,sBAAsB,+BAA+B,CAAC;AACnE,eAAO,MAAM,oBAAoB,6BAA6B,CAAC;AAE/D;;;;;;GAMG;AACH;;;;;;;GAOG;AACH,eAAO,MAAM,8BAA8B,wDACY,CAAC;AAExD,eAAO,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"claude-md.d.ts","sourceRoot":"","sources":["../../src/templates/claude-md.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,sBAAsB,+BAA+B,CAAC;AACnE,eAAO,MAAM,oBAAoB,6BAA6B,CAAC;AAE/D;;;;;;GAMG;AACH;;;;;;;GAOG;AACH,eAAO,MAAM,8BAA8B,wDACY,CAAC;AAExD,eAAO,MAAM,SAAS,8iTAmMrB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CASjE"}
|
|
@@ -202,26 +202,6 @@ not be surfaced in chat. MCP tool results carry both, so this is a
|
|
|
202
202
|
communication choice, not a data-availability problem: keep the id in the
|
|
203
203
|
tool call, name the work by its title in the conversation.
|
|
204
204
|
|
|
205
|
-
## Commit attribution
|
|
206
|
-
|
|
207
|
-
Deliveries on a focus share one branch, so their commits interleave. Every
|
|
208
|
-
commit you make for a delivery MUST carry a git trailer naming that delivery:
|
|
209
|
-
|
|
210
|
-
\`\`\`
|
|
211
|
-
Telora-Delivery: <deliveryId>
|
|
212
|
-
\`\`\`
|
|
213
|
-
|
|
214
|
-
- \`<deliveryId>\` is the delivery UUID whose work the commit advances (not the
|
|
215
|
-
issue id, not the focus id). E.g.
|
|
216
|
-
\`git commit -m "<subject>" -m "Telora-Delivery: <deliveryId>"\`.
|
|
217
|
-
- One delivery per commit; split a change that spans two deliveries.
|
|
218
|
-
- Merge-resolution / housekeeping commits carry no trailer.
|
|
219
|
-
|
|
220
|
-
The verify gate partitions the recorded commit set by this trailer to judge each
|
|
221
|
-
delivery against its OWN work and to prove its evidence is complete. A missing
|
|
222
|
-
trailer never corrupts a sibling -- at worst this delivery's evidence becomes
|
|
223
|
-
unvouchable and the gate re-queues it instead of rendering a verdict.
|
|
224
|
-
|
|
225
205
|
## Differential signaling
|
|
226
206
|
|
|
227
207
|
Telora is asymmetric: it moves reality toward intent, never the reverse.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-md.js","sourceRoot":"","sources":["../../src/templates/claude-md.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,CAAC,MAAM,sBAAsB,GAAG,4BAA4B,CAAC;AACnE,MAAM,CAAC,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAE/D;;;;;;GAMG;AACH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,8BAA8B,GACzC,qDAAqD,CAAC;AAExD,MAAM,CAAC,MAAM,SAAS,GAAG
|
|
1
|
+
{"version":3,"file":"claude-md.js","sourceRoot":"","sources":["../../src/templates/claude-md.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,CAAC,MAAM,sBAAsB,GAAG,4BAA4B,CAAC;AACnE,MAAM,CAAC,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAE/D;;;;;;GAMG;AACH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,8BAA8B,GACzC,qDAAqD,CAAC;AAExD,MAAM,CAAC,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmMxB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,WAA0B;IACvD,MAAM,WAAW,GAAG,WAAW;QAC7B,CAAC,CAAC,kCAAkC,WAAW,SAAS;QACxD,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,KAAK,GACT,GAAG,sBAAsB,IAAI;QAC7B,GAAG,WAAW,GAAG,SAAS,EAAE;QAC5B,GAAG,oBAAoB,IAAI,CAAC;IAC9B,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -14,6 +14,23 @@
|
|
|
14
14
|
* settings schema): `permissions.allow` is a list of tool patterns. MCP
|
|
15
15
|
* tool patterns follow the form `mcp__<server-name>__<tool-name>`.
|
|
16
16
|
*/
|
|
17
|
+
/** A single Claude Code hook command entry. */
|
|
18
|
+
export interface ClaudeHookCommand {
|
|
19
|
+
type: 'command';
|
|
20
|
+
command: string;
|
|
21
|
+
}
|
|
22
|
+
/** A hook matcher group: a set of commands run for a matched event. */
|
|
23
|
+
export interface ClaudeHookMatcher {
|
|
24
|
+
hooks: ClaudeHookCommand[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The subset of the Claude Code `hooks` map Telora installs. Only `SessionStart`
|
|
28
|
+
* is seeded (it carries the workstation seed via `telora-daemon session-state`);
|
|
29
|
+
* all other hook events are user-owned and left untouched by the merge.
|
|
30
|
+
*/
|
|
31
|
+
export interface TeloraHooks {
|
|
32
|
+
SessionStart?: ClaudeHookMatcher[];
|
|
33
|
+
}
|
|
17
34
|
export interface TeloraSettingsTemplate {
|
|
18
35
|
permissions: {
|
|
19
36
|
allow: string[];
|
|
@@ -26,7 +43,28 @@ export interface TeloraSettingsTemplate {
|
|
|
26
43
|
*/
|
|
27
44
|
deny?: string[];
|
|
28
45
|
};
|
|
46
|
+
/**
|
|
47
|
+
* Seeded hooks. Carries the SessionStart hook that runs `telora-daemon
|
|
48
|
+
* session-state`, which since the seed became workstation context (not a
|
|
49
|
+
* repo file) is the carrier that delivers the Telora workstation seed to the
|
|
50
|
+
* session at open. Present on every writable/read-only seed.
|
|
51
|
+
*/
|
|
52
|
+
hooks?: TeloraHooks;
|
|
29
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* The SessionStart hook command. Resolves the `telora-daemon` binary from the
|
|
56
|
+
* project's local `node_modules/.bin` first (the pinned install), falling back
|
|
57
|
+
* to whatever is on PATH, and no-ops cleanly (`|| true`) when neither is present
|
|
58
|
+
* so a repo without the daemon installed never has session start blocked.
|
|
59
|
+
*
|
|
60
|
+
* `session-state` emits the connection invariants AND the workstation seed to
|
|
61
|
+
* stdout, which the SessionStart hook contract feeds into the session as
|
|
62
|
+
* additionalContext -- so newly shipped Telora directives reach a connected
|
|
63
|
+
* workstation by updating the daemon binary, with no file on disk changing.
|
|
64
|
+
*/
|
|
65
|
+
export declare const TELORA_SESSION_START_HOOK_COMMAND: string;
|
|
66
|
+
/** Build the seeded SessionStart hook group. */
|
|
67
|
+
export declare function buildSessionStartHooks(): TeloraHooks;
|
|
30
68
|
/**
|
|
31
69
|
* Write-shaped tool denials for a read-only audit focus.
|
|
32
70
|
*
|
|
@@ -63,7 +101,12 @@ export declare function buildClaudeSettings({ readOnly }?: {
|
|
|
63
101
|
* - `permissions.deny`: same union semantics. Only written when the seed (or
|
|
64
102
|
* the existing file) carries deny entries -- a writable seed against a
|
|
65
103
|
* deny-free existing file leaves no `deny` key.
|
|
66
|
-
* -
|
|
104
|
+
* - `hooks.SessionStart`: union of the user's matcher groups with the seed's,
|
|
105
|
+
* deduplicated by command string -- a re-merge never appends a second copy of
|
|
106
|
+
* our SessionStart command. All OTHER hook events (PreToolUse, Stop, ...) are
|
|
107
|
+
* left exactly as the user had them.
|
|
108
|
+
* - All other top-level keys: untouched. We only own the permissions list and
|
|
109
|
+
* the SessionStart hook.
|
|
67
110
|
*/
|
|
68
111
|
export declare function mergeClaudeSettings(existing: Record<string, unknown> | null, seed: TeloraSettingsTemplate): Record<string, unknown>;
|
|
69
112
|
//# sourceMappingURL=claude-settings.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-settings.d.ts","sourceRoot":"","sources":["../../src/templates/claude-settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE;QACX,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB;;;;;;WAMG;QACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;KACjB,CAAC;
|
|
1
|
+
{"version":3,"file":"claude-settings.d.ts","sourceRoot":"","sources":["../../src/templates/claude-settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,+CAA+C;AAC/C,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,uEAAuE;AACvE,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,iBAAiB,EAAE,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,iBAAiB,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE;QACX,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB;;;;;;WAMG;QACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;KACjB,CAAC;IACF;;;;;OAKG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iCAAiC,QAGG,CAAC;AAElD,gDAAgD;AAChD,wBAAgB,sBAAsB,IAAI,WAAW,CAMpD;AAqCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAiBhD;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,EAAE,QAAQ,EAAE,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GACxC,sBAAsB,CAQxB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACxC,IAAI,EAAE,sBAAsB,GAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAqCzB"}
|
|
@@ -14,6 +14,28 @@
|
|
|
14
14
|
* settings schema): `permissions.allow` is a list of tool patterns. MCP
|
|
15
15
|
* tool patterns follow the form `mcp__<server-name>__<tool-name>`.
|
|
16
16
|
*/
|
|
17
|
+
/**
|
|
18
|
+
* The SessionStart hook command. Resolves the `telora-daemon` binary from the
|
|
19
|
+
* project's local `node_modules/.bin` first (the pinned install), falling back
|
|
20
|
+
* to whatever is on PATH, and no-ops cleanly (`|| true`) when neither is present
|
|
21
|
+
* so a repo without the daemon installed never has session start blocked.
|
|
22
|
+
*
|
|
23
|
+
* `session-state` emits the connection invariants AND the workstation seed to
|
|
24
|
+
* stdout, which the SessionStart hook contract feeds into the session as
|
|
25
|
+
* additionalContext -- so newly shipped Telora directives reach a connected
|
|
26
|
+
* workstation by updating the daemon binary, with no file on disk changing.
|
|
27
|
+
*/
|
|
28
|
+
export const TELORA_SESSION_START_HOOK_COMMAND = 'bin="${CLAUDE_PROJECT_DIR:-.}/node_modules/.bin/telora-daemon"; ' +
|
|
29
|
+
'[ -x "$bin" ] || bin="$(command -v telora-daemon)"; ' +
|
|
30
|
+
'[ -n "$bin" ] && "$bin" session-state || true';
|
|
31
|
+
/** Build the seeded SessionStart hook group. */
|
|
32
|
+
export function buildSessionStartHooks() {
|
|
33
|
+
return {
|
|
34
|
+
SessionStart: [
|
|
35
|
+
{ hooks: [{ type: 'command', command: TELORA_SESSION_START_HOOK_COMMAND }] },
|
|
36
|
+
],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
17
39
|
/**
|
|
18
40
|
* Routine MCP tool calls expected during a normal Telora session.
|
|
19
41
|
*
|
|
@@ -93,6 +115,7 @@ export function buildClaudeSettings({ readOnly } = {}) {
|
|
|
93
115
|
allow: [...TELORA_MCP_ALLOWLIST],
|
|
94
116
|
...(readOnly ? { deny: buildReadOnlyDenyList() } : {}),
|
|
95
117
|
},
|
|
118
|
+
hooks: buildSessionStartHooks(),
|
|
96
119
|
};
|
|
97
120
|
}
|
|
98
121
|
/**
|
|
@@ -106,7 +129,12 @@ export function buildClaudeSettings({ readOnly } = {}) {
|
|
|
106
129
|
* - `permissions.deny`: same union semantics. Only written when the seed (or
|
|
107
130
|
* the existing file) carries deny entries -- a writable seed against a
|
|
108
131
|
* deny-free existing file leaves no `deny` key.
|
|
109
|
-
* -
|
|
132
|
+
* - `hooks.SessionStart`: union of the user's matcher groups with the seed's,
|
|
133
|
+
* deduplicated by command string -- a re-merge never appends a second copy of
|
|
134
|
+
* our SessionStart command. All OTHER hook events (PreToolUse, Stop, ...) are
|
|
135
|
+
* left exactly as the user had them.
|
|
136
|
+
* - All other top-level keys: untouched. We only own the permissions list and
|
|
137
|
+
* the SessionStart hook.
|
|
110
138
|
*/
|
|
111
139
|
export function mergeClaudeSettings(existing, seed) {
|
|
112
140
|
const out = existing && typeof existing === 'object' ? { ...existing } : {};
|
|
@@ -134,6 +162,50 @@ export function mergeClaudeSettings(existing, seed) {
|
|
|
134
162
|
// against a deny-free existing file must not introduce an empty deny key.
|
|
135
163
|
...(mergedDeny.length > 0 ? { deny: mergedDeny } : {}),
|
|
136
164
|
};
|
|
165
|
+
const mergedHooks = mergeSessionStartHooks(out.hooks, seed.hooks);
|
|
166
|
+
if (mergedHooks)
|
|
167
|
+
out.hooks = mergedHooks;
|
|
137
168
|
return out;
|
|
138
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Merge the seed's SessionStart hook into an existing `hooks` map.
|
|
172
|
+
*
|
|
173
|
+
* - Every existing hook event is preserved verbatim.
|
|
174
|
+
* - The seed's SessionStart matcher groups are appended to any the user already
|
|
175
|
+
* has, skipping a group whose command already appears (so a re-merge is a
|
|
176
|
+
* no-op). Returns null only when there is nothing to write (no seed hooks and
|
|
177
|
+
* no existing hooks), so a settings file that never had hooks stays clean.
|
|
178
|
+
*/
|
|
179
|
+
function mergeSessionStartHooks(existingHooks, seedHooks) {
|
|
180
|
+
const existing = existingHooks && typeof existingHooks === 'object' && !Array.isArray(existingHooks)
|
|
181
|
+
? { ...existingHooks }
|
|
182
|
+
: {};
|
|
183
|
+
const seedGroups = seedHooks?.SessionStart ?? [];
|
|
184
|
+
if (seedGroups.length === 0) {
|
|
185
|
+
return Object.keys(existing).length > 0 ? existing : null;
|
|
186
|
+
}
|
|
187
|
+
const existingGroups = Array.isArray(existing.SessionStart)
|
|
188
|
+
? [...existing.SessionStart]
|
|
189
|
+
: [];
|
|
190
|
+
const commandOf = (group) => {
|
|
191
|
+
if (!group || typeof group !== 'object')
|
|
192
|
+
return [];
|
|
193
|
+
const hooks = group.hooks;
|
|
194
|
+
if (!Array.isArray(hooks))
|
|
195
|
+
return [];
|
|
196
|
+
return hooks
|
|
197
|
+
.map((h) => (h && typeof h === 'object' ? h.command : undefined))
|
|
198
|
+
.filter((c) => typeof c === 'string');
|
|
199
|
+
};
|
|
200
|
+
const present = new Set(existingGroups.flatMap(commandOf));
|
|
201
|
+
for (const group of seedGroups) {
|
|
202
|
+
const cmds = commandOf(group);
|
|
203
|
+
if (cmds.some((c) => present.has(c)))
|
|
204
|
+
continue;
|
|
205
|
+
existingGroups.push(group);
|
|
206
|
+
cmds.forEach((c) => present.add(c));
|
|
207
|
+
}
|
|
208
|
+
existing.SessionStart = existingGroups;
|
|
209
|
+
return existing;
|
|
210
|
+
}
|
|
139
211
|
//# sourceMappingURL=claude-settings.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-settings.js","sourceRoot":"","sources":["../../src/templates/claude-settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"claude-settings.js","sourceRoot":"","sources":["../../src/templates/claude-settings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boot-time per-product provisioning for the unified daemon shell.
|
|
3
|
+
*
|
|
4
|
+
* Every function here answers the same question: "connect seeds this once --
|
|
5
|
+
* what keeps it current on the daemon's update cadence?" Each walks
|
|
6
|
+
* `config.base.products` directly, is idempotent (no write when already
|
|
7
|
+
* current, so an unchanged repo sees no git churn), and is per-product
|
|
8
|
+
* best-effort -- one repo's unreadable or unwritable path must never abort the
|
|
9
|
+
* daemon or the remaining products.
|
|
10
|
+
*
|
|
11
|
+
* `telora-daemon update` is covered by construction: update re-execs the
|
|
12
|
+
* daemon, so an updating workstation necessarily runs this whole pass.
|
|
13
|
+
*
|
|
14
|
+
* Called from `runUnifiedDaemon` (`unified-shell.ts`) in a load-bearing order --
|
|
15
|
+
* see `refreshClaudeSettingsForProducts` for the one ordering constraint that
|
|
16
|
+
* is a correctness requirement rather than a preference.
|
|
17
|
+
*/
|
|
18
|
+
import type { UnifiedConfig } from '@telora/daemon-core';
|
|
19
|
+
/**
|
|
20
|
+
* Refresh `.mcp.json` in each configured product's repo so Claude Code's
|
|
21
|
+
* MCP invocation always points at the daemon's currently-installed
|
|
22
|
+
* `@telora/mcp-products`. Idempotent: writes the same bytes if nothing
|
|
23
|
+
* has changed. All failures are warnings -- a missing or unwritable repo
|
|
24
|
+
* path must not block the daemon.
|
|
25
|
+
*/
|
|
26
|
+
export declare function refreshMcpConfigsForProducts(config: UnifiedConfig): void;
|
|
27
|
+
/**
|
|
28
|
+
* Refresh `.claude/settings.json` in each configured product's repo so the
|
|
29
|
+
* SessionStart seed hook (which carries the Claude workstation seed at session
|
|
30
|
+
* open) reaches EVERY connected repo -- not only newly-connected ones.
|
|
31
|
+
*
|
|
32
|
+
* `.claude/settings.json` is otherwise written at connect time only
|
|
33
|
+
* (writeOrMergeClaudeSettings, sole call site in connect scaffolding). Without
|
|
34
|
+
* this boot-cadence refresh, an already-connected repo would never receive the
|
|
35
|
+
* hook, and once the repo-root CLAUDE.md file carrier is withdrawn that repo
|
|
36
|
+
* would carry NO seed at all -- silently. This is the exact analog of
|
|
37
|
+
* `refreshMcpConfigsForProducts`: "connect seeds it once, this keeps it current
|
|
38
|
+
* on the daemon's update cadence." It walks `config.base.products` directly, so
|
|
39
|
+
* it reaches every product in the local daemon.json regardless of which
|
|
40
|
+
* workstation claims it; `telora-daemon update` re-execs, so an updating
|
|
41
|
+
* workstation necessarily runs this pass.
|
|
42
|
+
*
|
|
43
|
+
* CRITICAL ORDERING (runUnifiedDaemon): this MUST run BEFORE the CLAUDE.md
|
|
44
|
+
* retirement (`scaffoldProductsAtBoot`), so a workstation cannot reach the file
|
|
45
|
+
* withdrawal without having just installed the hook carrier in the same boot.
|
|
46
|
+
*
|
|
47
|
+
* Idempotent (writeOrMergeClaudeSettings no-writes when unchanged) and
|
|
48
|
+
* per-product best-effort: one repo's unwritable settings must not abort the rest.
|
|
49
|
+
*/
|
|
50
|
+
export declare function refreshClaudeSettingsForProducts(config: UnifiedConfig): void;
|
|
51
|
+
/**
|
|
52
|
+
* Boot-time self-heal of every configured product's directory. Routes each
|
|
53
|
+
* product through the single idempotent `scaffoldProductDirectory` -- the exact
|
|
54
|
+
* same scaffolder the SIGHUP hot-reload handler calls for newly-added products
|
|
55
|
+
* -- so there is ONE scaffold implementation shared by both entry points.
|
|
56
|
+
*
|
|
57
|
+
* For each product this (idempotently):
|
|
58
|
+
* - Refreshes the delimited `<!-- BEGIN/END TELORA SEED -->` block in the
|
|
59
|
+
* repo's `CLAUDE.md` to the daemon's installed seed (the analog of
|
|
60
|
+
* `refreshMcpConfigsForProducts`: connect seeds it once, this keeps it
|
|
61
|
+
* current on the daemon's update cadence -- no write when already current,
|
|
62
|
+
* so an unchanged repo sees no git churn). productName is null to stay
|
|
63
|
+
* byte-identical with the connect-seeded block.
|
|
64
|
+
* - git-inits the directory when it has no repo (init, .gitignore, initial
|
|
65
|
+
* commit, integration branch) so the focus engine can create branches and
|
|
66
|
+
* worktrees. Skipped when a repo already exists (never clobbers).
|
|
67
|
+
*
|
|
68
|
+
* `telora-daemon update` is covered by construction: update re-execs the
|
|
69
|
+
* daemon, so this boot path runs again on the new version.
|
|
70
|
+
*
|
|
71
|
+
* All failures are per-product warnings (handled inside the scaffolder): one
|
|
72
|
+
* repo's unreadable/locked directory must not abort the daemon or the others.
|
|
73
|
+
*/
|
|
74
|
+
export declare function scaffoldProductsAtBoot(config: UnifiedConfig): void;
|
|
75
|
+
/**
|
|
76
|
+
* Boot-time self-heal for the Codex AGENTS.md seed carriers, on the daemon's
|
|
77
|
+
* update cadence. There are three destinations, all off the repo root and each
|
|
78
|
+
* refresh-only (a destination that does not already exist is skipped, so boot
|
|
79
|
+
* never spawns a carrier a workstation did not opt into):
|
|
80
|
+
*
|
|
81
|
+
* 1. The workstation-shared operator seed `~/.codex/AGENTS.md` (header-less) --
|
|
82
|
+
* read by an interactive operator and by daemon-spawned HOSTED Codex agents.
|
|
83
|
+
* 2. Each product's ISOLATED CODEX_HOME `~/.telora/codex/<productId>/AGENTS.md`
|
|
84
|
+
* (per-product header) -- read by daemon-spawned LOCAL-MODEL Codex agents.
|
|
85
|
+
* Refreshed only where the isolated home already exists (i.e. was
|
|
86
|
+
* provisioned for a local-model product); a hosted product has none and is
|
|
87
|
+
* skipped.
|
|
88
|
+
* 3. Repo-root `<repo>/AGENTS.md` for the IDE harnesses (Cursor / VS Code) that
|
|
89
|
+
* read it natively -- refresh-only, and the safe writer refuses to touch a
|
|
90
|
+
* repo-TRACKED file. Boot does NOT retire repo-root AGENTS.md: it cannot
|
|
91
|
+
* tell a legacy-Codex file apart from a live IDE one, and deleting the
|
|
92
|
+
* latter would strip a harness still using it. Repo-root retirement is done
|
|
93
|
+
* at connect / `harness add codex`, where the harness is known.
|
|
94
|
+
*
|
|
95
|
+
* Per-destination warnings on failure; one repo's unreadable AGENTS.md must not
|
|
96
|
+
* abort the rest.
|
|
97
|
+
*/
|
|
98
|
+
export declare function refreshAgentsMdForProducts(config: UnifiedConfig): void;
|
|
99
|
+
//# sourceMappingURL=unified-shell-provisioning.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unified-shell-provisioning.d.ts","sourceRoot":"","sources":["../src/unified-shell-provisioning.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AA6BzD;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CA2BxE;AAMD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAgB5E;AAMD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAclE;AAMD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAiDtE"}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boot-time per-product provisioning for the unified daemon shell.
|
|
3
|
+
*
|
|
4
|
+
* Every function here answers the same question: "connect seeds this once --
|
|
5
|
+
* what keeps it current on the daemon's update cadence?" Each walks
|
|
6
|
+
* `config.base.products` directly, is idempotent (no write when already
|
|
7
|
+
* current, so an unchanged repo sees no git churn), and is per-product
|
|
8
|
+
* best-effort -- one repo's unreadable or unwritable path must never abort the
|
|
9
|
+
* daemon or the remaining products.
|
|
10
|
+
*
|
|
11
|
+
* `telora-daemon update` is covered by construction: update re-execs the
|
|
12
|
+
* daemon, so an updating workstation necessarily runs this whole pass.
|
|
13
|
+
*
|
|
14
|
+
* Called from `runUnifiedDaemon` (`unified-shell.ts`) in a load-bearing order --
|
|
15
|
+
* see `refreshClaudeSettingsForProducts` for the one ordering constraint that
|
|
16
|
+
* is a correctness requirement rather than a preference.
|
|
17
|
+
*/
|
|
18
|
+
import { existsSync } from 'node:fs';
|
|
19
|
+
import { resolve } from 'node:path';
|
|
20
|
+
import { resolveMcpServerPath, writeMcpConfigFile } from './mcp-resolution.js';
|
|
21
|
+
import { writeOrMergeAgentsMd, writeOrMergeGlobalAgentsMd, writeProductCodexAgentsMd, writeOrMergeClaudeSettings, globalAgentsMdPath, } from './cli/connect.js';
|
|
22
|
+
import { resolveProductCodexHome } from './cli/codex-provision.js';
|
|
23
|
+
import { scaffoldProductDirectory } from './product-scaffold.js';
|
|
24
|
+
import { resolveIntegrationBranch } from './unified-shell-config.js';
|
|
25
|
+
import { createLogger } from './log.js';
|
|
26
|
+
const log = createLogger({ module: 'telemetry' });
|
|
27
|
+
/** Standard stdout/stderr/fetch io bundle the connect writers take. */
|
|
28
|
+
function bootIo() {
|
|
29
|
+
return {
|
|
30
|
+
out: (msg) => process.stdout.write(msg),
|
|
31
|
+
err: (msg) => process.stderr.write(msg),
|
|
32
|
+
fetch: globalThis.fetch,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// .mcp.json refresh
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
/**
|
|
39
|
+
* Refresh `.mcp.json` in each configured product's repo so Claude Code's
|
|
40
|
+
* MCP invocation always points at the daemon's currently-installed
|
|
41
|
+
* `@telora/mcp-products`. Idempotent: writes the same bytes if nothing
|
|
42
|
+
* has changed. All failures are warnings -- a missing or unwritable repo
|
|
43
|
+
* path must not block the daemon.
|
|
44
|
+
*/
|
|
45
|
+
export function refreshMcpConfigsForProducts(config) {
|
|
46
|
+
const products = config.base.products ?? [];
|
|
47
|
+
if (products.length === 0)
|
|
48
|
+
return;
|
|
49
|
+
let mcpServerPath;
|
|
50
|
+
try {
|
|
51
|
+
mcpServerPath = resolveMcpServerPath();
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
log.warn(`[mcp-refresh] Cannot resolve @telora/mcp-products: ${err instanceof Error ? err.message : String(err)}`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
for (const product of products) {
|
|
58
|
+
if (!product.repoPath)
|
|
59
|
+
continue;
|
|
60
|
+
try {
|
|
61
|
+
writeMcpConfigFile(product.repoPath, {
|
|
62
|
+
mcpServerPath,
|
|
63
|
+
profile: 'human',
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
log.warn(`[mcp-refresh] Failed for ${product.repoPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
// .claude/settings.json refresh (SessionStart seed-hook migration)
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
/**
|
|
75
|
+
* Refresh `.claude/settings.json` in each configured product's repo so the
|
|
76
|
+
* SessionStart seed hook (which carries the Claude workstation seed at session
|
|
77
|
+
* open) reaches EVERY connected repo -- not only newly-connected ones.
|
|
78
|
+
*
|
|
79
|
+
* `.claude/settings.json` is otherwise written at connect time only
|
|
80
|
+
* (writeOrMergeClaudeSettings, sole call site in connect scaffolding). Without
|
|
81
|
+
* this boot-cadence refresh, an already-connected repo would never receive the
|
|
82
|
+
* hook, and once the repo-root CLAUDE.md file carrier is withdrawn that repo
|
|
83
|
+
* would carry NO seed at all -- silently. This is the exact analog of
|
|
84
|
+
* `refreshMcpConfigsForProducts`: "connect seeds it once, this keeps it current
|
|
85
|
+
* on the daemon's update cadence." It walks `config.base.products` directly, so
|
|
86
|
+
* it reaches every product in the local daemon.json regardless of which
|
|
87
|
+
* workstation claims it; `telora-daemon update` re-execs, so an updating
|
|
88
|
+
* workstation necessarily runs this pass.
|
|
89
|
+
*
|
|
90
|
+
* CRITICAL ORDERING (runUnifiedDaemon): this MUST run BEFORE the CLAUDE.md
|
|
91
|
+
* retirement (`scaffoldProductsAtBoot`), so a workstation cannot reach the file
|
|
92
|
+
* withdrawal without having just installed the hook carrier in the same boot.
|
|
93
|
+
*
|
|
94
|
+
* Idempotent (writeOrMergeClaudeSettings no-writes when unchanged) and
|
|
95
|
+
* per-product best-effort: one repo's unwritable settings must not abort the rest.
|
|
96
|
+
*/
|
|
97
|
+
export function refreshClaudeSettingsForProducts(config) {
|
|
98
|
+
const products = config.base.products ?? [];
|
|
99
|
+
if (products.length === 0)
|
|
100
|
+
return;
|
|
101
|
+
const io = bootIo();
|
|
102
|
+
for (const product of products) {
|
|
103
|
+
if (!product.repoPath)
|
|
104
|
+
continue;
|
|
105
|
+
try {
|
|
106
|
+
writeOrMergeClaudeSettings(product.repoPath, io);
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
log.warn(`[settings-refresh] Failed for ${product.repoPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
// Product directory self-heal (CLAUDE.md seed + git-init)
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
/**
|
|
117
|
+
* Boot-time self-heal of every configured product's directory. Routes each
|
|
118
|
+
* product through the single idempotent `scaffoldProductDirectory` -- the exact
|
|
119
|
+
* same scaffolder the SIGHUP hot-reload handler calls for newly-added products
|
|
120
|
+
* -- so there is ONE scaffold implementation shared by both entry points.
|
|
121
|
+
*
|
|
122
|
+
* For each product this (idempotently):
|
|
123
|
+
* - Refreshes the delimited `<!-- BEGIN/END TELORA SEED -->` block in the
|
|
124
|
+
* repo's `CLAUDE.md` to the daemon's installed seed (the analog of
|
|
125
|
+
* `refreshMcpConfigsForProducts`: connect seeds it once, this keeps it
|
|
126
|
+
* current on the daemon's update cadence -- no write when already current,
|
|
127
|
+
* so an unchanged repo sees no git churn). productName is null to stay
|
|
128
|
+
* byte-identical with the connect-seeded block.
|
|
129
|
+
* - git-inits the directory when it has no repo (init, .gitignore, initial
|
|
130
|
+
* commit, integration branch) so the focus engine can create branches and
|
|
131
|
+
* worktrees. Skipped when a repo already exists (never clobbers).
|
|
132
|
+
*
|
|
133
|
+
* `telora-daemon update` is covered by construction: update re-execs the
|
|
134
|
+
* daemon, so this boot path runs again on the new version.
|
|
135
|
+
*
|
|
136
|
+
* All failures are per-product warnings (handled inside the scaffolder): one
|
|
137
|
+
* repo's unreadable/locked directory must not abort the daemon or the others.
|
|
138
|
+
*/
|
|
139
|
+
export function scaffoldProductsAtBoot(config) {
|
|
140
|
+
const products = config.base.products ?? [];
|
|
141
|
+
if (products.length === 0)
|
|
142
|
+
return;
|
|
143
|
+
// Resolve the integration branch the same way buildFocusConfig does
|
|
144
|
+
// (env override -> focus section field -> default), without building the
|
|
145
|
+
// full focus config here.
|
|
146
|
+
const integrationBranch = resolveIntegrationBranch(config.focus.fields);
|
|
147
|
+
const io = bootIo();
|
|
148
|
+
for (const product of products) {
|
|
149
|
+
scaffoldProductDirectory(product, { integrationBranch }, io);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
// AGENTS.md (Codex seed carriers) refresh
|
|
154
|
+
// ---------------------------------------------------------------------------
|
|
155
|
+
/**
|
|
156
|
+
* Boot-time self-heal for the Codex AGENTS.md seed carriers, on the daemon's
|
|
157
|
+
* update cadence. There are three destinations, all off the repo root and each
|
|
158
|
+
* refresh-only (a destination that does not already exist is skipped, so boot
|
|
159
|
+
* never spawns a carrier a workstation did not opt into):
|
|
160
|
+
*
|
|
161
|
+
* 1. The workstation-shared operator seed `~/.codex/AGENTS.md` (header-less) --
|
|
162
|
+
* read by an interactive operator and by daemon-spawned HOSTED Codex agents.
|
|
163
|
+
* 2. Each product's ISOLATED CODEX_HOME `~/.telora/codex/<productId>/AGENTS.md`
|
|
164
|
+
* (per-product header) -- read by daemon-spawned LOCAL-MODEL Codex agents.
|
|
165
|
+
* Refreshed only where the isolated home already exists (i.e. was
|
|
166
|
+
* provisioned for a local-model product); a hosted product has none and is
|
|
167
|
+
* skipped.
|
|
168
|
+
* 3. Repo-root `<repo>/AGENTS.md` for the IDE harnesses (Cursor / VS Code) that
|
|
169
|
+
* read it natively -- refresh-only, and the safe writer refuses to touch a
|
|
170
|
+
* repo-TRACKED file. Boot does NOT retire repo-root AGENTS.md: it cannot
|
|
171
|
+
* tell a legacy-Codex file apart from a live IDE one, and deleting the
|
|
172
|
+
* latter would strip a harness still using it. Repo-root retirement is done
|
|
173
|
+
* at connect / `harness add codex`, where the harness is known.
|
|
174
|
+
*
|
|
175
|
+
* Per-destination warnings on failure; one repo's unreadable AGENTS.md must not
|
|
176
|
+
* abort the rest.
|
|
177
|
+
*/
|
|
178
|
+
export function refreshAgentsMdForProducts(config) {
|
|
179
|
+
const products = config.base.products ?? [];
|
|
180
|
+
if (products.length === 0)
|
|
181
|
+
return;
|
|
182
|
+
const teloraUrl = config.base.teloraUrl;
|
|
183
|
+
const organizationId = config.base.organizationId;
|
|
184
|
+
if (!teloraUrl || !organizationId)
|
|
185
|
+
return;
|
|
186
|
+
const io = bootIo();
|
|
187
|
+
// 1. Refresh the workstation-shared operator seed, if this workstation has one.
|
|
188
|
+
if (existsSync(globalAgentsMdPath())) {
|
|
189
|
+
try {
|
|
190
|
+
writeOrMergeGlobalAgentsMd(io);
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
log.warn(`[agents-md-refresh] Global ~/.codex/AGENTS.md refresh failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
for (const product of products) {
|
|
197
|
+
if (!product.id)
|
|
198
|
+
continue;
|
|
199
|
+
const inv = { productName: null, teloraUrl, organizationId, productId: product.id };
|
|
200
|
+
// 2. Refresh the per-product isolated-home seed, only where the isolated
|
|
201
|
+
// home already exists (provisioned for a local-model product).
|
|
202
|
+
if (existsSync(resolveProductCodexHome(product.id))) {
|
|
203
|
+
try {
|
|
204
|
+
writeProductCodexAgentsMd(inv, io);
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
log.warn(`[agents-md-refresh] Isolated-home AGENTS.md refresh failed for ${product.id}: ${err instanceof Error ? err.message : String(err)}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// 3. Refresh (never create) repo-root AGENTS.md for IDE harnesses; the safe
|
|
211
|
+
// writer refuses to touch a repo-tracked file.
|
|
212
|
+
if (product.repoPath && existsSync(resolve(product.repoPath, 'AGENTS.md'))) {
|
|
213
|
+
try {
|
|
214
|
+
writeOrMergeAgentsMd(product.repoPath, inv, io);
|
|
215
|
+
}
|
|
216
|
+
catch (err) {
|
|
217
|
+
log.warn(`[agents-md-refresh] Failed for ${product.repoPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=unified-shell-provisioning.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unified-shell-provisioning.js","sourceRoot":"","sources":["../src/unified-shell-provisioning.ts"],"names":[],"mappings":"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"}
|