@telora/daemon 0.20.89 → 0.20.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/build-info.json +2 -2
  2. package/dist/audit-prompt.d.ts.map +1 -1
  3. package/dist/audit-prompt.js +6 -1
  4. package/dist/audit-prompt.js.map +1 -1
  5. package/dist/ci-sensor-loop.d.ts +33 -5
  6. package/dist/ci-sensor-loop.d.ts.map +1 -1
  7. package/dist/ci-sensor-loop.js +95 -14
  8. package/dist/ci-sensor-loop.js.map +1 -1
  9. package/dist/ci-status-git.d.ts +7 -5
  10. package/dist/ci-status-git.d.ts.map +1 -1
  11. package/dist/ci-status-git.js +12 -9
  12. package/dist/ci-status-git.js.map +1 -1
  13. package/dist/ci-status.d.ts +21 -6
  14. package/dist/ci-status.d.ts.map +1 -1
  15. package/dist/ci-status.js +90 -15
  16. package/dist/ci-status.js.map +1 -1
  17. package/dist/cli/connect/agents.d.ts +64 -14
  18. package/dist/cli/connect/agents.d.ts.map +1 -1
  19. package/dist/cli/connect/agents.js +102 -19
  20. package/dist/cli/connect/agents.js.map +1 -1
  21. package/dist/cli/connect/claude.d.ts +19 -16
  22. package/dist/cli/connect/claude.d.ts.map +1 -1
  23. package/dist/cli/connect/claude.js +34 -68
  24. package/dist/cli/connect/claude.js.map +1 -1
  25. package/dist/cli/connect/scaffolding.d.ts +3 -2
  26. package/dist/cli/connect/scaffolding.d.ts.map +1 -1
  27. package/dist/cli/connect/scaffolding.js +17 -6
  28. package/dist/cli/connect/scaffolding.js.map +1 -1
  29. package/dist/cli/connect/seed-retirement.d.ts +39 -0
  30. package/dist/cli/connect/seed-retirement.d.ts.map +1 -0
  31. package/dist/cli/connect/seed-retirement.js +95 -0
  32. package/dist/cli/connect/seed-retirement.js.map +1 -0
  33. package/dist/cli/connect.d.ts +2 -2
  34. package/dist/cli/connect.d.ts.map +1 -1
  35. package/dist/cli/connect.js +8 -2
  36. package/dist/cli/connect.js.map +1 -1
  37. package/dist/cli/session-state.d.ts +0 -20
  38. package/dist/cli/session-state.d.ts.map +1 -1
  39. package/dist/cli/session-state.js +20 -49
  40. package/dist/cli/session-state.js.map +1 -1
  41. package/dist/completion/merge-phase.d.ts +1 -1
  42. package/dist/completion/merge-phase.d.ts.map +1 -1
  43. package/dist/completion/merge-phase.js +14 -34
  44. package/dist/completion/merge-phase.js.map +1 -1
  45. package/dist/completion/team-lifecycle.d.ts.map +1 -1
  46. package/dist/completion/team-lifecycle.js +13 -1
  47. package/dist/completion/team-lifecycle.js.map +1 -1
  48. package/dist/git/merge.d.ts +16 -0
  49. package/dist/git/merge.d.ts.map +1 -1
  50. package/dist/git/merge.js +39 -1
  51. package/dist/git/merge.js.map +1 -1
  52. package/dist/product-scaffold.d.ts +8 -6
  53. package/dist/product-scaffold.d.ts.map +1 -1
  54. package/dist/product-scaffold.js +14 -10
  55. package/dist/product-scaffold.js.map +1 -1
  56. package/dist/queries/cause-key.d.ts +13 -3
  57. package/dist/queries/cause-key.d.ts.map +1 -1
  58. package/dist/queries/cause-key.js +14 -4
  59. package/dist/queries/cause-key.js.map +1 -1
  60. package/dist/queries/holds.d.ts +11 -2
  61. package/dist/queries/holds.d.ts.map +1 -1
  62. package/dist/queries/holds.js +11 -2
  63. package/dist/queries/holds.js.map +1 -1
  64. package/dist/templates/agents-md.d.ts +16 -0
  65. package/dist/templates/agents-md.d.ts.map +1 -1
  66. package/dist/templates/agents-md.js +26 -0
  67. package/dist/templates/agents-md.js.map +1 -1
  68. package/dist/templates/claude-md.d.ts +1 -1
  69. package/dist/templates/claude-md.d.ts.map +1 -1
  70. package/dist/templates/claude-md.js +0 -20
  71. package/dist/templates/claude-md.js.map +1 -1
  72. package/dist/templates/claude-settings.d.ts +44 -1
  73. package/dist/templates/claude-settings.d.ts.map +1 -1
  74. package/dist/templates/claude-settings.js +73 -1
  75. package/dist/templates/claude-settings.js.map +1 -1
  76. package/dist/unified-shell-provisioning.d.ts +99 -0
  77. package/dist/unified-shell-provisioning.d.ts.map +1 -0
  78. package/dist/unified-shell-provisioning.js +222 -0
  79. package/dist/unified-shell-provisioning.js.map +1 -0
  80. package/dist/unified-shell.d.ts +0 -41
  81. package/dist/unified-shell.d.ts.map +1 -1
  82. package/dist/unified-shell.js +19 -135
  83. package/dist/unified-shell.js.map +1 -1
  84. package/package.json +2 -2
@@ -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,y4UAuNrB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CASjE"}
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuNxB,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"}
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
- * - All other top-level keys: untouched. We only own the permissions list.
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;CACH;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,CAOxB;AAED;;;;;;;;;;;;GAYG;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,CAkCzB"}
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
- * - All other top-level keys: untouched. We only own the permissions list.
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":"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"}
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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"}