@iowarp/clio-coder 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/CHANGELOG.md +407 -0
  2. package/CODE_OF_CONDUCT.md +21 -0
  3. package/CONTRIBUTING.md +224 -0
  4. package/LICENSE +202 -0
  5. package/NOTICE +9 -0
  6. package/README.md +798 -0
  7. package/SECURITY.md +72 -0
  8. package/assets/clio-coder-logo-128.webp +0 -0
  9. package/damage-control-rules.yaml +419 -0
  10. package/dist/acp-UMLFVA3F.js +92 -0
  11. package/dist/agents-Q4MYPMUW.js +91 -0
  12. package/dist/auth-O6HYIJ6J.js +521 -0
  13. package/dist/chunk-262G75JS.js +35 -0
  14. package/dist/chunk-26BZQOAD.js +1281 -0
  15. package/dist/chunk-2J63S4SF.js +508 -0
  16. package/dist/chunk-3DANZDGR.js +717 -0
  17. package/dist/chunk-4UQA7NCT.js +29 -0
  18. package/dist/chunk-527KG6XR.js +497 -0
  19. package/dist/chunk-5LDRNKX2.js +1063 -0
  20. package/dist/chunk-5N2FG33Q.js +25 -0
  21. package/dist/chunk-67MTHP2E.js +135 -0
  22. package/dist/chunk-6CWDTGUC.js +20 -0
  23. package/dist/chunk-7BHLZB3A.js +2115 -0
  24. package/dist/chunk-7RBKDI66.js +348 -0
  25. package/dist/chunk-AMFR5YA3.js +541 -0
  26. package/dist/chunk-BBUH4VAA.js +1224 -0
  27. package/dist/chunk-BYEU76JP.js +899 -0
  28. package/dist/chunk-CLJ5HLUD.js +458 -0
  29. package/dist/chunk-D5YD55AR.js +116 -0
  30. package/dist/chunk-DXQNI4PC.js +61 -0
  31. package/dist/chunk-E3NYWENM.js +1004 -0
  32. package/dist/chunk-GNGDQYDU.js +34688 -0
  33. package/dist/chunk-GOTUR54M.js +9 -0
  34. package/dist/chunk-HBU5MTAM.js +41 -0
  35. package/dist/chunk-HMYNFFY4.js +28 -0
  36. package/dist/chunk-JPOWPFCU.js +1010 -0
  37. package/dist/chunk-JWHCJDCI.js +1215 -0
  38. package/dist/chunk-KBR4MZZR.js +41 -0
  39. package/dist/chunk-KKKPTZLM.js +93 -0
  40. package/dist/chunk-ME6DNWIU.js +66 -0
  41. package/dist/chunk-NI4DEJMC.js +88 -0
  42. package/dist/chunk-O4EJEDHO.js +659 -0
  43. package/dist/chunk-PIDUD6M2.js +31 -0
  44. package/dist/chunk-PS4PFJQP.js +29459 -0
  45. package/dist/chunk-QV47YRF4.js +48 -0
  46. package/dist/chunk-RQDWMVRB.js +279 -0
  47. package/dist/chunk-TFSSEXL6.js +136 -0
  48. package/dist/chunk-TKHQ4DGZ.js +8290 -0
  49. package/dist/chunk-TPOCL34A.js +2876 -0
  50. package/dist/chunk-UGYAX5YI.js +565 -0
  51. package/dist/chunk-UHTSULZS.js +461 -0
  52. package/dist/chunk-UU3R62TT.js +128 -0
  53. package/dist/chunk-UWIJNAOB.js +3906 -0
  54. package/dist/chunk-VOO7NYPP.js +914 -0
  55. package/dist/chunk-VPAWTYLY.js +117 -0
  56. package/dist/chunk-WD6AJM35.js +1216 -0
  57. package/dist/chunk-X3BR7HWV.js +115 -0
  58. package/dist/chunk-X3NE4WVW.js +120 -0
  59. package/dist/chunk-XNISANGE.js +1395 -0
  60. package/dist/chunk-XV4ZJ6ZM.js +3177 -0
  61. package/dist/cli/index.js +236 -0
  62. package/dist/clio-KIQ5SNDS.js +53 -0
  63. package/dist/components-JVHMUBEB.js +653 -0
  64. package/dist/config-ZFCDBMDC.js +372 -0
  65. package/dist/configure-G4E3A2PG.js +27 -0
  66. package/dist/context-CDXTP2MP.js +293 -0
  67. package/dist/context-E3KIFVXI.js +185 -0
  68. package/dist/context-clear-3F4PLXOS.js +102 -0
  69. package/dist/context-index-Q7YSYTR3.js +106 -0
  70. package/dist/docs-YIETIWZI.js +280 -0
  71. package/dist/doctor-M5HJJZOL.js +61 -0
  72. package/dist/domains/agents/builtins/architect.md +33 -0
  73. package/dist/domains/agents/builtins/coder.md +31 -0
  74. package/dist/domains/agents/builtins/context-bootstrap.md +38 -0
  75. package/dist/domains/agents/builtins/debugger.md +30 -0
  76. package/dist/domains/agents/builtins/documenter.md +31 -0
  77. package/dist/domains/agents/builtins/git-master.md +30 -0
  78. package/dist/domains/agents/builtins/provenance.md +30 -0
  79. package/dist/domains/agents/builtins/researcher.md +71 -0
  80. package/dist/domains/agents/builtins/scout.md +42 -0
  81. package/dist/domains/agents/builtins/tester.md +31 -0
  82. package/dist/domains/agents/builtins/verifier.md +30 -0
  83. package/dist/domains/agents/builtins/wiki-writer.md +41 -0
  84. package/dist/eval-B3KZZESM.js +2674 -0
  85. package/dist/evidence-V67CHM35.js +233 -0
  86. package/dist/evolve-YDZSUQYA.js +518 -0
  87. package/dist/extensions-SRG7XCAH.js +207 -0
  88. package/dist/fleet-CA2CRTVG.js +760 -0
  89. package/dist/fleet-preflight-CLIAX7YR.js +21 -0
  90. package/dist/init-2OZDJE2D.js +227 -0
  91. package/dist/memory-3PIQQAKX.js +207 -0
  92. package/dist/models-DY35XI7Y.js +237 -0
  93. package/dist/paths-5OMXW7Z4.js +57 -0
  94. package/dist/preload-KZVHET2B.js +11 -0
  95. package/dist/reset-PIFYNOS3.js +216 -0
  96. package/dist/run-3VSPP24F.js +735 -0
  97. package/dist/share-D36RQCXM.js +241 -0
  98. package/dist/skills-F2MRLELY.js +445 -0
  99. package/dist/skills-eval-E2ZTW4PL.js +932 -0
  100. package/dist/targets-DZMEZAH4.js +977 -0
  101. package/dist/trace-7NYCUI2J.js +250 -0
  102. package/dist/uninstall-AD3JWHBB.js +322 -0
  103. package/dist/upgrade-WYYBKGDY.js +301 -0
  104. package/dist/usage-ULIDAGFF.js +755 -0
  105. package/dist/version-ROZ6CZKH.js +16 -0
  106. package/dist/wiki-generate-PKFIX6OB.js +377 -0
  107. package/dist/worker/entry.js +1739 -0
  108. package/docs/README.md +93 -0
  109. package/docs/acp.md +120 -0
  110. package/docs/alcf-provider.md +72 -0
  111. package/docs/architecture.md +172 -0
  112. package/docs/artifact-versions.md +54 -0
  113. package/docs/built-in-agents.md +265 -0
  114. package/docs/capacity-and-scheduling.md +97 -0
  115. package/docs/commands-and-modes.md +554 -0
  116. package/docs/config-knobs-audit.md +115 -0
  117. package/docs/configuration-and-targets.md +812 -0
  118. package/docs/context-engine.md +236 -0
  119. package/docs/dispatch-architecture-rationale.md +126 -0
  120. package/docs/documentation-coverage.md +46 -0
  121. package/docs/documentation-guide.md +166 -0
  122. package/docs/environment-variables.md +105 -0
  123. package/docs/eval-runner.md +205 -0
  124. package/docs/evals-internal.md +298 -0
  125. package/docs/evidence-and-memory.md +243 -0
  126. package/docs/evolution.md +143 -0
  127. package/docs/exit-codes-and-output.md +74 -0
  128. package/docs/extensions-and-sharing.md +306 -0
  129. package/docs/fleet-demo-runbook.md +179 -0
  130. package/docs/fleet-dispatch.md +591 -0
  131. package/docs/glossary.md +75 -0
  132. package/docs/html/agents_blueprint.html +936 -0
  133. package/docs/html/alcf_blueprint.html +324 -0
  134. package/docs/html/architecture_blueprint.html +850 -0
  135. package/docs/html/commands_blueprint.html +794 -0
  136. package/docs/html/config_knobs_audit_blueprint.html +178 -0
  137. package/docs/html/configuration_blueprint.html +1080 -0
  138. package/docs/html/context_blueprint.html +603 -0
  139. package/docs/html/documentation_blueprint.html +832 -0
  140. package/docs/html/environment_blueprint.html +404 -0
  141. package/docs/html/eval_blueprint.html +743 -0
  142. package/docs/html/evals_internal_blueprint.html +190 -0
  143. package/docs/html/evolution_blueprint.html +674 -0
  144. package/docs/html/extensions_blueprint.html +2065 -0
  145. package/docs/html/fleet_dispatch_blueprint.html +286 -0
  146. package/docs/html/index.html +919 -0
  147. package/docs/html/lifecycle_blueprint.html +723 -0
  148. package/docs/html/memory_blueprint.html +699 -0
  149. package/docs/html/middleware_blueprint.html +664 -0
  150. package/docs/html/models_blueprint.html +2366 -0
  151. package/docs/html/observability_blueprint.html +683 -0
  152. package/docs/html/provider_adapter_blueprint.html +245 -0
  153. package/docs/html/safety_blueprint.html +1386 -0
  154. package/docs/html/shared.css +571 -0
  155. package/docs/html/shared.js +143 -0
  156. package/docs/html/skills_blueprint.html +671 -0
  157. package/docs/html/soak_blueprint.html +182 -0
  158. package/docs/html/tool_usage_blueprint.html +350 -0
  159. package/docs/html/tools_blueprint.html +2249 -0
  160. package/docs/html/trace_blueprint.html +235 -0
  161. package/docs/html/tui_design_blueprint.html +314 -0
  162. package/docs/html/validation_blueprint.html +961 -0
  163. package/docs/html/worker_dispatch_blueprint.html +231 -0
  164. package/docs/installation-and-lifecycle.md +308 -0
  165. package/docs/middleware-and-components.md +148 -0
  166. package/docs/model-catalog.md +189 -0
  167. package/docs/observability.md +233 -0
  168. package/docs/proactive-memory.md +452 -0
  169. package/docs/prompt-envelope-and-tools.md +142 -0
  170. package/docs/provider-adapter-cookbook.md +148 -0
  171. package/docs/release-cut-checklist.md +138 -0
  172. package/docs/safety-model.md +357 -0
  173. package/docs/scientific-validation.md +105 -0
  174. package/docs/session-lifecycle.md +156 -0
  175. package/docs/skills-marketplace.md +46 -0
  176. package/docs/tool-usage.md +527 -0
  177. package/docs/trace-store.md +132 -0
  178. package/docs/troubleshooting.md +33 -0
  179. package/docs/tui-design.md +239 -0
  180. package/docs/worker-dispatch-mechanics.md +242 -0
  181. package/package.json +132 -0
  182. package/skills/README.md +408 -0
  183. package/skills/git/commit-crafting/SKILL.md +79 -0
  184. package/skills/git/commit-crafting/evals.md +92 -0
  185. package/skills/git/create-pr/SKILL.md +116 -0
  186. package/skills/git/create-pr/evals.md +114 -0
  187. package/skills/git/investigate-issue/SKILL.md +139 -0
  188. package/skills/git/investigate-issue/evals.md +94 -0
  189. package/skills/git/resolve-merge-conflicts/SKILL.md +96 -0
  190. package/skills/git/resolve-merge-conflicts/evals.md +58 -0
  191. package/skills/git/review-changes/SKILL.md +103 -0
  192. package/skills/git/review-changes/evals.md +85 -0
  193. package/skills/git/worktree-create/SKILL.md +92 -0
  194. package/skills/git/worktree-create/evals.md +97 -0
  195. package/skills/git/worktree-create/references/worktree-setup.md +66 -0
  196. package/skills/git/worktree-merge/SKILL.md +95 -0
  197. package/skills/git/worktree-merge/evals.md +114 -0
  198. package/skills/skill-marketplace.json +261 -0
  199. package/skills/workflow/cut-it/SKILL.md +86 -0
  200. package/skills/workflow/cut-it/evals.md +42 -0
  201. package/src/domains/agents/builtins/architect.md +33 -0
  202. package/src/domains/agents/builtins/coder.md +31 -0
  203. package/src/domains/agents/builtins/context-bootstrap.md +38 -0
  204. package/src/domains/agents/builtins/debugger.md +30 -0
  205. package/src/domains/agents/builtins/documenter.md +31 -0
  206. package/src/domains/agents/builtins/git-master.md +30 -0
  207. package/src/domains/agents/builtins/provenance.md +30 -0
  208. package/src/domains/agents/builtins/researcher.md +71 -0
  209. package/src/domains/agents/builtins/scout.md +42 -0
  210. package/src/domains/agents/builtins/tester.md +31 -0
  211. package/src/domains/agents/builtins/verifier.md +30 -0
  212. package/src/domains/agents/builtins/wiki-writer.md +41 -0
  213. package/src/domains/agents/fleets/build-review.md +34 -0
  214. package/src/domains/agents/fleets/build-test.md +35 -0
  215. package/src/domains/agents/fleets/sdlc.md +86 -0
  216. package/src/domains/prompts/fragments/identity/clio-worker.md +11 -0
  217. package/src/domains/prompts/fragments/identity/clio.md +26 -0
  218. package/src/domains/prompts/fragments/operating/contract.md +64 -0
  219. package/src/domains/prompts/fragments/safety/auto-edit.md +14 -0
  220. package/src/domains/prompts/fragments/safety/full-auto.md +14 -0
  221. package/src/domains/prompts/fragments/safety/read-only.md +13 -0
  222. package/src/domains/prompts/fragments/safety/suggest.md +13 -0
  223. package/src/domains/prompts/fragments/wiki/page.md +75 -0
  224. package/src/domains/prompts/fragments/wiki/plan.md +48 -0
  225. package/src/domains/providers/models/cloud-models/alcf.yaml +40 -0
  226. package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +993 -0
@@ -0,0 +1,717 @@
1
+ import {
2
+ loadOperatorProfile,
3
+ loadProjectRules,
4
+ renderOperatorProfile,
5
+ selectActiveRules
6
+ } from "./chunk-UWIJNAOB.js";
7
+ import {
8
+ compile,
9
+ compileWorker,
10
+ sha256
11
+ } from "./chunk-GNGDQYDU.js";
12
+ import {
13
+ isUserVisibleAgent
14
+ } from "./chunk-WD6AJM35.js";
15
+ import {
16
+ classifyProjectPreload
17
+ } from "./chunk-KBR4MZZR.js";
18
+ import {
19
+ BusChannels
20
+ } from "./chunk-D5YD55AR.js";
21
+ import {
22
+ resolvePackageRoot
23
+ } from "./chunk-DXQNI4PC.js";
24
+
25
+ // src/domains/prompts/extension.ts
26
+ import { isAbsolute, relative } from "node:path";
27
+
28
+ // src/core/clio-repo.ts
29
+ import { existsSync, readFileSync, statSync } from "node:fs";
30
+ import path from "node:path";
31
+ var CLIO_PACKAGE_NAME = "@iowarp/clio-coder";
32
+ var SOURCE_MARKERS = [
33
+ "src/entry/orchestrator.ts",
34
+ "src/worker/entry.ts",
35
+ "src/domains/prompts/fragments/identity/clio.md"
36
+ ];
37
+ function isFile(filePath) {
38
+ try {
39
+ return statSync(filePath).isFile();
40
+ } catch {
41
+ return false;
42
+ }
43
+ }
44
+ function readPackageJson(root) {
45
+ try {
46
+ const raw = readFileSync(path.join(root, "package.json"), "utf8");
47
+ const parsed = JSON.parse(raw);
48
+ return parsed && typeof parsed === "object" ? parsed : null;
49
+ } catch {
50
+ return null;
51
+ }
52
+ }
53
+ function repositoryMatches(value) {
54
+ if (typeof value === "string") return value.includes("iowarp/clio-coder");
55
+ if (!value || typeof value !== "object") return false;
56
+ const url = value.url;
57
+ return typeof url === "string" && url.includes("iowarp/clio-coder");
58
+ }
59
+ function hasGitMarker(root) {
60
+ return existsSync(path.join(root, ".git"));
61
+ }
62
+ function hasSourceMarkers(root) {
63
+ return SOURCE_MARKERS.every((marker) => isFile(path.join(root, marker)));
64
+ }
65
+ function isClioCoderRepoRoot(root) {
66
+ const pkg = readPackageJson(root);
67
+ if (pkg?.name !== CLIO_PACKAGE_NAME) return false;
68
+ if (!repositoryMatches(pkg.repository)) return false;
69
+ if (!hasGitMarker(root)) return false;
70
+ return hasSourceMarkers(root);
71
+ }
72
+ function detectClioCoderRepo(cwd = process.cwd()) {
73
+ let current = path.resolve(cwd);
74
+ for (; ; ) {
75
+ if (isClioCoderRepoRoot(current)) {
76
+ return { isClioCoderRepo: true, repoRoot: current };
77
+ }
78
+ if (hasGitMarker(current)) break;
79
+ const parent = path.dirname(current);
80
+ if (parent === current) break;
81
+ current = parent;
82
+ }
83
+ return { isClioCoderRepo: false, repoRoot: null };
84
+ }
85
+
86
+ // src/domains/agents/catalog.ts
87
+ var DEFAULT_DISPATCH_AGENT_ID = "coder";
88
+ var FLEET_PROMPT_PURPOSE_MAX_CHARS = 64;
89
+ var FLEET_DELEGATION_RULE = "Delegate when the task has two or more independent file-scoped subtasks, or any broad exploration. You keep synthesis and validation; a single narrow change stays with you.";
90
+ var FLEET_HANDOFF_RULE = "A file you assigned to a worker is not yours to edit while its dispatch is pending or after it succeeds; if you already changed it, say so in your report.";
91
+ var FLEET_REFUSAL_DISCLOSURE = "When admission refuses a dispatch, report the refusal and the reason it gave; never substitute another agent without saying why.";
92
+ var FLEET_ANTI_CHURN_RULE = "A dispatch with the same target files and the same goal as one you already ran is a repeat however differently you word it: read that run's receipt, or run the check yourself, instead of dispatching again.";
93
+ var FLEET_SPECIALIST_ROUTING = "Pick by job: receipts, diffs, or telemetry -> provenance; external docs -> researcher; broad recon -> scout; tests -> tester; gates or review -> verifier.";
94
+ function fleetPromptPurpose(description) {
95
+ const trimmed = description.trim().replace(/\s+/gu, " ");
96
+ if (trimmed.length === 0) return "";
97
+ const stop = trimmed.indexOf(". ");
98
+ const sentence = stop > 0 ? trimmed.slice(0, stop) : trimmed.replace(/\.$/u, "");
99
+ if (sentence.length <= FLEET_PROMPT_PURPOSE_MAX_CHARS) return sentence;
100
+ const cut = sentence.lastIndexOf(" ", FLEET_PROMPT_PURPOSE_MAX_CHARS);
101
+ return `${sentence.slice(0, cut > 0 ? cut : FLEET_PROMPT_PURPOSE_MAX_CHARS).trimEnd()}...`;
102
+ }
103
+ function fleetPromptLine(spec) {
104
+ const budget = spec.budget ? `${spec.budget.toolCalls} calls` : "default budget";
105
+ const purpose = fleetPromptPurpose(spec.description);
106
+ return `- ${spec.id} (${spec.capabilityClass}, ${budget})${purpose.length > 0 ? `: ${purpose}` : ""}`;
107
+ }
108
+ function renderFleetPromptSection(input) {
109
+ const specs = input.slice().sort((a, b) => {
110
+ const category = a.category.localeCompare(b.category);
111
+ return category === 0 ? a.id.localeCompare(b.id) : category;
112
+ });
113
+ const publicSpecs = specs.filter(isUserVisibleAgent);
114
+ const shadowSpecs = specs.filter((spec) => spec.audience === "shadow");
115
+ if (publicSpecs.length === 0 && shadowSpecs.length === 0) return "";
116
+ const lines = [
117
+ "# Fleet",
118
+ FLEET_DELEGATION_RULE,
119
+ FLEET_HANDOFF_RULE,
120
+ FLEET_ANTI_CHURN_RULE,
121
+ FLEET_REFUSAL_DISCLOSURE,
122
+ `Workers you reach with \`dispatch\`, by \`agent\` id (default ${DEFAULT_DISPATCH_AGENT_ID}). Capability class is what a worker may do: a read-only worker cannot edit.`,
123
+ FLEET_SPECIALIST_ROUTING
124
+ ];
125
+ if (publicSpecs.length > 0) {
126
+ lines.push("", "Operator-facing:", ...publicSpecs.map(fleetPromptLine));
127
+ }
128
+ if (shadowSpecs.length > 0) {
129
+ lines.push("", "Internal specialists, dispatch-only:", ...shadowSpecs.map(fleetPromptLine));
130
+ }
131
+ return lines.join("\n");
132
+ }
133
+ function renderAgentCatalogSectionsFromSpecs(input) {
134
+ const specs = input.slice().sort((a, b) => {
135
+ const category = a.category.localeCompare(b.category);
136
+ return category === 0 ? a.id.localeCompare(b.id) : category;
137
+ });
138
+ const publicSpecs = specs.filter(isUserVisibleAgent);
139
+ const shadowSpecs = specs.filter((spec) => spec.audience === "shadow");
140
+ const lines = [
141
+ "Clio manages a small fleet of coding agents. Recipes are Markdown files; normalized specs carry audience, category, capability, tools, skills, latency, and worker-budget hints.",
142
+ "Use the `dispatch` tool to invoke one by `agent_id` when delegation helps.",
143
+ `Default dispatch agent: ${DEFAULT_DISPATCH_AGENT_ID}.`,
144
+ "User-facing agents are base/custom. Shadow agents are internal helpers for context, research, and provenance; do not recommend them as normal `/run` choices.",
145
+ "Prefer fast read-only agents for orientation, verification agents for gates, and workspace-edit agents only for bounded coding tasks.",
146
+ "When a task matches a skill named on an agent line (skills=...), prefer the recipe that binds it; its worker is told to load bound skills for the run.",
147
+ `After a dispatch succeeds, synthesize from the sealed receipt; the worker's prose is an advisory claim until its verification state is verified. Spot-check delegated claims before repeating them: re-read any cited file:line location, and re-run or inspect the named validation before repeating a "tests pass" claim.`,
148
+ FLEET_ANTI_CHURN_RULE
149
+ ];
150
+ if (publicSpecs.length > 0) {
151
+ lines.push("", "User-facing agents:");
152
+ for (const spec of publicSpecs) {
153
+ const description = spec.description.trim();
154
+ const suffix = description.length > 0 ? ` - ${description}` : "";
155
+ lines.push(formatSpecLine(spec, suffix));
156
+ }
157
+ }
158
+ if (shadowSpecs.length > 0) {
159
+ lines.push("", "Shadow agents for internal orchestration:");
160
+ for (const spec of shadowSpecs) {
161
+ const description = spec.description.trim();
162
+ const suffix = description.length > 0 ? ` - ${description}` : "";
163
+ lines.push(formatSpecLine(spec, suffix));
164
+ }
165
+ }
166
+ return { stable: lines.join("\n"), volatile: "" };
167
+ }
168
+ function formatSpecLine(spec, suffix) {
169
+ const tags = spec.tags.length > 0 ? `, tags=${spec.tags.join("/")}` : "";
170
+ const skills = spec.skills.length > 0 ? `, skills=${spec.skills.join("/")}` : "";
171
+ const budget = spec.budget ? `, budget=${spec.budget.toolCalls}/${spec.budget.readReserve}/${spec.budget.synthesis ? "synthesize" : "stop"}` : ", budget=operator-default";
172
+ return `- ${spec.name} [${spec.id}] (${spec.audience}, ${spec.category}, ${spec.capabilityClass}, ${spec.latencyClass}, ${spec.source}${tags}${skills}${budget})${suffix}`;
173
+ }
174
+
175
+ // src/domains/prompts/fragment-loader.ts
176
+ import { readdirSync, readFileSync as readFileSync2 } from "node:fs";
177
+ import path2 from "node:path";
178
+ import yaml from "yaml";
179
+ var frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
180
+ var fragmentIdRegex = /^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/;
181
+ function defaultRootDir() {
182
+ return path2.join(resolvePackageRoot(), "src", "domains", "prompts", "fragments");
183
+ }
184
+ function walk(root) {
185
+ const out = [];
186
+ let entries;
187
+ try {
188
+ entries = readdirSync(root, { withFileTypes: true });
189
+ } catch {
190
+ return out;
191
+ }
192
+ for (const entry of entries) {
193
+ const full = path2.join(root, entry.name);
194
+ if (entry.isDirectory()) {
195
+ if (entry.name === "wiki") continue;
196
+ out.push(...walk(full));
197
+ continue;
198
+ }
199
+ if (entry.isFile() && entry.name.endsWith(".md")) {
200
+ out.push(full);
201
+ }
202
+ }
203
+ return out.sort((left, right) => left.localeCompare(right));
204
+ }
205
+ function parseFragment(filePath, rootDir) {
206
+ const raw = readFileSync2(filePath, "utf8");
207
+ const rawRel = path2.relative(rootDir, filePath);
208
+ const relPath = rawRel.split(path2.sep).join("/");
209
+ const match = raw.match(frontmatterRegex);
210
+ if (!match) {
211
+ throw new Error(`fragment-loader: ${relPath}: missing or malformed YAML frontmatter`);
212
+ }
213
+ const frontmatterText = match[1] ?? "";
214
+ const body = match[2] ?? "";
215
+ let parsed;
216
+ try {
217
+ parsed = yaml.parse(frontmatterText);
218
+ } catch (err) {
219
+ const reason = err instanceof Error ? err.message : String(err);
220
+ throw new Error(`fragment-loader: ${relPath}: invalid YAML frontmatter (${reason})`);
221
+ }
222
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
223
+ throw new Error(`fragment-loader: ${relPath}: frontmatter must be a YAML object`);
224
+ }
225
+ const fm = parsed;
226
+ const id = fm.id;
227
+ if (typeof id !== "string" || !fragmentIdRegex.test(id)) {
228
+ throw new Error(`fragment-loader: ${relPath}: frontmatter.id must be a dot-separated namespace`);
229
+ }
230
+ const version = fm.version;
231
+ if (version !== 1) {
232
+ throw new Error(`fragment-loader: ${relPath}: frontmatter.version must be 1`);
233
+ }
234
+ const description = fm.description;
235
+ if (typeof description !== "string" || description.trim() === "") {
236
+ throw new Error(`fragment-loader: ${relPath}: frontmatter.description must be a non-empty string`);
237
+ }
238
+ const dynamicRaw = fm.dynamic;
239
+ if (dynamicRaw !== void 0 && typeof dynamicRaw !== "boolean") {
240
+ throw new Error(`fragment-loader: ${relPath}: frontmatter.dynamic must be a boolean when present`);
241
+ }
242
+ return {
243
+ path: filePath,
244
+ relPath,
245
+ id,
246
+ version,
247
+ description,
248
+ dynamic: dynamicRaw === true,
249
+ body,
250
+ contentHash: sha256(raw)
251
+ };
252
+ }
253
+ function loadFragments(options) {
254
+ const rootDir = typeof options === "string" ? options : options?.rootDir;
255
+ const resolvedRoot = rootDir ? path2.resolve(rootDir) : defaultRootDir();
256
+ const files = walk(resolvedRoot);
257
+ const byId = /* @__PURE__ */ new Map();
258
+ for (const file of files) {
259
+ const fragment = parseFragment(file, resolvedRoot);
260
+ const existing = byId.get(fragment.id);
261
+ if (existing) {
262
+ throw new Error(
263
+ `fragment-loader: duplicate fragment id "${fragment.id}" in ${existing.relPath} and ${fragment.relPath}`
264
+ );
265
+ }
266
+ byId.set(fragment.id, fragment);
267
+ }
268
+ return { byId, rootDir: resolvedRoot };
269
+ }
270
+
271
+ // src/domains/prompts/extension.ts
272
+ var CLIO_REPO_AWARENESS_ID = "context.clio-repo-awareness";
273
+ var WORKSPACE_ROOT_ID = "context.workspace-root";
274
+ function createPromptsBundle(context, options = {}) {
275
+ let table = null;
276
+ const suppressContextFiles = options.noContextFiles === true;
277
+ function config() {
278
+ return context.getContract("config");
279
+ }
280
+ function contextDomain() {
281
+ return context.getContract("context");
282
+ }
283
+ function agentsDomain() {
284
+ return context.getContract("agents");
285
+ }
286
+ function fleetRoster() {
287
+ const specs = agentsDomain()?.listSpecs() ?? [];
288
+ return specs.length > 0 ? renderFleetPromptSection(specs) : "";
289
+ }
290
+ function reload() {
291
+ try {
292
+ table = loadFragments();
293
+ } catch (err) {
294
+ const msg = err instanceof Error ? err.message : String(err);
295
+ process.stderr.write(`[clio:prompts] reload failed: ${msg}
296
+ `);
297
+ }
298
+ }
299
+ function diffTouchesFragments(paths) {
300
+ for (const p of paths) {
301
+ if (p.includes("prompt") || p.includes("fragment")) return true;
302
+ }
303
+ return false;
304
+ }
305
+ const contract = {
306
+ async compileSessionPrompt(input) {
307
+ if (!table) throw new Error("prompts domain not started");
308
+ if (table.byId.size === 0) {
309
+ throw new Error("prompts: no fragments loaded, check startup logs");
310
+ }
311
+ const configContract = config();
312
+ const settings = configContract?.get();
313
+ const safety = input.autonomy ?? settings?.autonomy ?? "auto-edit";
314
+ const cwd = input.cwd ?? process.cwd();
315
+ let contextFiles = "";
316
+ let projectPreload = null;
317
+ if (!suppressContextFiles) {
318
+ const projectContext = contextDomain()?.renderPromptContext(cwd);
319
+ contextFiles = projectContext ? selectProjectContext(projectContext, input.sessionInputs.providerSupportsTools ?? null) : "";
320
+ if (projectContext) {
321
+ projectPreload = classifyProjectPreload({
322
+ hasClioMd: projectContext.clioMd !== null,
323
+ text: projectContext.text
324
+ });
325
+ }
326
+ for (const warning of projectContext?.warnings ?? []) process.stderr.write(`${warning}
327
+ `);
328
+ }
329
+ const roster = fleetRoster();
330
+ const sessionInputs = {
331
+ ...input.sessionInputs,
332
+ ...contextFiles.length > 0 ? { contextFiles } : {},
333
+ ...roster.length > 0 ? { fleetRoster: roster } : {}
334
+ };
335
+ const compiled = compile(table, {
336
+ identity: "identity.clio",
337
+ operatingContract: "operating.contract",
338
+ safety: `safety.${safety}`,
339
+ sessionInputs,
340
+ additionalFragments: [
341
+ ...workspaceRootFragment(cwd),
342
+ ...clioRepoAwarenessFragments(cwd),
343
+ ...customizationFragments(cwd, input.workingContextPaths ?? [])
344
+ ]
345
+ });
346
+ return { ...compiled, projectPreload };
347
+ },
348
+ async compileWorkerPrompt(input) {
349
+ if (!table) throw new Error("prompts domain not started");
350
+ if (table.byId.size === 0) {
351
+ throw new Error("prompts: no fragments loaded, check startup logs");
352
+ }
353
+ return compileWorker(table, input);
354
+ },
355
+ reload
356
+ };
357
+ let unsubscribeHotReload = null;
358
+ const extension = {
359
+ async start() {
360
+ try {
361
+ table = loadFragments();
362
+ } catch (err) {
363
+ const msg = err instanceof Error ? err.message : String(err);
364
+ process.stderr.write(`[clio:prompts] initial load failed: ${msg}
365
+ `);
366
+ table = { byId: /* @__PURE__ */ new Map(), rootDir: "" };
367
+ }
368
+ unsubscribeHotReload = context.bus.on(BusChannels.ConfigHotReload, (payload) => {
369
+ const diff = payload?.diff;
370
+ const paths = diff?.hotReload ?? [];
371
+ if (!diffTouchesFragments(paths)) return;
372
+ reload();
373
+ });
374
+ },
375
+ async stop() {
376
+ unsubscribeHotReload?.();
377
+ unsubscribeHotReload = null;
378
+ }
379
+ };
380
+ return { extension, contract };
381
+ }
382
+ function customizationFragments(cwd, workingContextPaths) {
383
+ const fragments = [];
384
+ try {
385
+ const loaded = loadProjectRules(cwd);
386
+ const active = selectActiveRules(loaded.rules, normalizeWorkingContextPaths(cwd, workingContextPaths));
387
+ if (active.length > 0) {
388
+ const body = ["# Project rules", ...active.map((rule) => rule.body)].join("\n\n");
389
+ fragments.push({
390
+ id: "context.project-rules",
391
+ relPath: "inline/project-rules",
392
+ body,
393
+ contentHash: sha256(body),
394
+ dynamic: true
395
+ });
396
+ }
397
+ } catch {
398
+ }
399
+ try {
400
+ const profile = loadOperatorProfile(cwd);
401
+ const rendered = renderOperatorProfile(profile.profile);
402
+ if (rendered.text.length > 0) {
403
+ fragments.push({
404
+ id: "context.operator-profile",
405
+ relPath: "inline/operator-profile",
406
+ body: rendered.text,
407
+ contentHash: sha256(rendered.text),
408
+ dynamic: true
409
+ });
410
+ }
411
+ } catch {
412
+ }
413
+ return fragments;
414
+ }
415
+ function normalizeWorkingContextPaths(cwd, paths) {
416
+ const normalized = /* @__PURE__ */ new Set();
417
+ for (const filePath of paths) {
418
+ const rel = isAbsolute(filePath) ? relative(cwd, filePath) : filePath;
419
+ if (!rel || rel.startsWith("..") || isAbsolute(rel)) continue;
420
+ normalized.add(rel.replace(/\\/g, "/"));
421
+ }
422
+ return [...normalized].sort();
423
+ }
424
+ function workspaceRootFragment(cwd) {
425
+ const body = [
426
+ "# Workspace",
427
+ `Absolute workspace root: ${cwd}`,
428
+ "Relative paths resolve here. Do not invent a root such as /workspace or /repo, and do not pass a working directory unless the command must run in a subdirectory of this root."
429
+ ].join("\n");
430
+ return [
431
+ {
432
+ id: WORKSPACE_ROOT_ID,
433
+ relPath: "inline/workspace-root",
434
+ body,
435
+ contentHash: sha256(body),
436
+ dynamic: true
437
+ }
438
+ ];
439
+ }
440
+ function clioRepoAwarenessFragments(cwd) {
441
+ const awareness = detectClioCoderRepo(cwd);
442
+ if (!awareness.isClioCoderRepo || !awareness.repoRoot) return [];
443
+ const body = [
444
+ "# Clio Source Tree",
445
+ "This workspace is Clio Coder's own source tree.",
446
+ "When running inside this repo, Clio can modify her own TUI, skills, agents, tools, prompts, context/bootstrap, and harness as ordinary local source work when the user asks.",
447
+ "Shared contribution/publishing/push/PR/release requires explicit user intent and normal Git/GitHub etiquette. Do not imply autonomous publishing."
448
+ ].join("\n");
449
+ return [
450
+ {
451
+ id: CLIO_REPO_AWARENESS_ID,
452
+ relPath: "inline/clio-repo-awareness",
453
+ body,
454
+ contentHash: sha256(body),
455
+ dynamic: true
456
+ }
457
+ ];
458
+ }
459
+ function projectTypeFromPromptContext(text) {
460
+ const match = /<project-type>([^<]+)<\/project-type>/.exec(text);
461
+ const value = match?.[1]?.trim();
462
+ return value && value !== "unknown" ? value : null;
463
+ }
464
+ function hasCodewiki(text) {
465
+ return text.includes("<codewiki>");
466
+ }
467
+ function wikiAvailabilityFromPromptContext(text) {
468
+ const match = /<wiki>([^<]+)<\/wiki>/.exec(text);
469
+ const value = match?.[1]?.trim();
470
+ return value && value.length > 0 ? value : null;
471
+ }
472
+ function renderProjectSynopsis(context, providerSupportsTools) {
473
+ const projectType = projectTypeFromPromptContext(context.text);
474
+ const wiki = wikiAvailabilityFromPromptContext(context.text);
475
+ const lines = ["<project-synopsis>"];
476
+ if (projectType) lines.push(`Language: ${projectType}`);
477
+ if (context.clioMd) {
478
+ lines.push(`Project: ${context.clioMd.projectName}`);
479
+ lines.push(
480
+ "CLIO-CODER.md: available; compact synopsis only because the handbook is too large for automatic preload."
481
+ );
482
+ }
483
+ if (hasCodewiki(context.text)) lines.push("Codewiki: available via code_nav.");
484
+ if (wiki) lines.push(`Wiki: ${wiki}`);
485
+ if (providerSupportsTools === false) {
486
+ lines.push("Tools: unavailable for this target; use this synopsis only as fallback context.");
487
+ } else {
488
+ lines.push('Retrieve exact repository facts with context(scope="workspace"), code_nav, grep, and read.');
489
+ }
490
+ lines.push("</project-synopsis>");
491
+ return lines.join("\n");
492
+ }
493
+ function selectProjectContext(context, providerSupportsTools) {
494
+ const preload = classifyProjectPreload({ hasClioMd: context.clioMd !== null, text: context.text });
495
+ if (preload.mode === "none") return "";
496
+ if (preload.mode === "full") return context.text.trim();
497
+ return renderProjectSynopsis(context, providerSupportsTools);
498
+ }
499
+
500
+ // src/domains/prompts/manifest.ts
501
+ var PromptsManifest = {
502
+ name: "prompts",
503
+ // agents: the compiled session prompt carries the fleet roster, so the
504
+ // recipe registry must be loaded before the first compile.
505
+ dependsOn: ["config", "context", "resources", "agents"]
506
+ };
507
+
508
+ // src/domains/prompts/index.ts
509
+ function createPromptsDomainModule(options = {}) {
510
+ return {
511
+ manifest: options.noContextFiles === true ? {
512
+ ...PromptsManifest,
513
+ dependsOn: PromptsManifest.dependsOn.filter((name) => name !== "context")
514
+ } : PromptsManifest,
515
+ createExtension: (context) => createPromptsBundle(context, options)
516
+ };
517
+ }
518
+
519
+ // src/domains/scheduling/budget.ts
520
+ function createBudgetState(initialCeilingUsd) {
521
+ if (initialCeilingUsd < 0) throw new Error(`budget: ceiling must be >= 0 (got ${initialCeilingUsd})`);
522
+ let ceiling = initialCeilingUsd;
523
+ return {
524
+ get ceilingUsd() {
525
+ return ceiling;
526
+ },
527
+ checkCeiling(currentUsd) {
528
+ if (currentUsd > ceiling) return "over";
529
+ if (currentUsd === ceiling) return "at";
530
+ return "under";
531
+ },
532
+ raise(newCeilingUsd) {
533
+ if (newCeilingUsd < ceiling) {
534
+ throw new Error(`budget.raise: new ceiling ${newCeilingUsd} below current ${ceiling}`);
535
+ }
536
+ ceiling = newCeilingUsd;
537
+ }
538
+ };
539
+ }
540
+
541
+ // src/domains/scheduling/cluster.ts
542
+ var LOCAL_NODE_ID = "local";
543
+ var NODE_DEATH_FAILURE_THRESHOLD = 2;
544
+ function freshState() {
545
+ return { state: "online", stateReason: null, consecutiveFailures: 0, lastSeenMs: null };
546
+ }
547
+ function createFleetRegistry(getNodes, options) {
548
+ const now = options?.now ?? (() => Date.now());
549
+ const runtime = /* @__PURE__ */ new Map();
550
+ let activeWorkers = options?.activeWorkers;
551
+ function stateFor(id) {
552
+ let state = runtime.get(id);
553
+ if (!state) {
554
+ state = freshState();
555
+ runtime.set(id, state);
556
+ }
557
+ return state;
558
+ }
559
+ function snapshotFor(id, config) {
560
+ const state = stateFor(id);
561
+ if (config === null) {
562
+ return {
563
+ id: LOCAL_NODE_ID,
564
+ host: "localhost",
565
+ kind: "local",
566
+ state: state.state,
567
+ stateReason: state.stateReason,
568
+ activeWorkers: activeWorkers?.(LOCAL_NODE_ID) ?? 0,
569
+ maxWorkers: options?.localMaxWorkers?.() ?? Number.POSITIVE_INFINITY,
570
+ labels: [],
571
+ lastSeenAt: state.lastSeenMs !== null ? new Date(state.lastSeenMs).toISOString() : null
572
+ };
573
+ }
574
+ return {
575
+ id: config.id,
576
+ host: config.host,
577
+ kind: "ssh",
578
+ state: state.state,
579
+ stateReason: state.stateReason,
580
+ activeWorkers: activeWorkers?.(id) ?? 0,
581
+ maxWorkers: config.maxWorkers,
582
+ labels: [...config.labels ?? []],
583
+ lastSeenAt: state.lastSeenMs !== null ? new Date(state.lastSeenMs).toISOString() : null
584
+ };
585
+ }
586
+ function findConfig(id) {
587
+ return getNodes().find((node) => node.id === id) ?? null;
588
+ }
589
+ return {
590
+ hasRemoteNodes() {
591
+ return getNodes().length > 0;
592
+ },
593
+ list() {
594
+ return [snapshotFor(LOCAL_NODE_ID, null), ...getNodes().map((node) => snapshotFor(node.id, node))];
595
+ },
596
+ get(id) {
597
+ if (id === LOCAL_NODE_ID) return snapshotFor(LOCAL_NODE_ID, null);
598
+ const config = findConfig(id);
599
+ return config ? snapshotFor(id, config) : null;
600
+ },
601
+ config(id) {
602
+ return id === LOCAL_NODE_ID ? null : findConfig(id);
603
+ },
604
+ seen(id) {
605
+ stateFor(id).lastSeenMs = now();
606
+ },
607
+ recordChannelFailure(id, reason) {
608
+ const state = stateFor(id);
609
+ state.consecutiveFailures += 1;
610
+ if (state.state === "online" && state.consecutiveFailures >= NODE_DEATH_FAILURE_THRESHOLD) {
611
+ state.state = "offline";
612
+ state.stateReason = `classified dead after ${state.consecutiveFailures} consecutive channel failures (${reason})`;
613
+ }
614
+ return state.state;
615
+ },
616
+ bindActiveWorkers(source) {
617
+ activeWorkers = source;
618
+ },
619
+ recordChannelSuccess(id) {
620
+ const state = stateFor(id);
621
+ state.consecutiveFailures = 0;
622
+ state.lastSeenMs = now();
623
+ if (state.state === "offline") {
624
+ state.state = "online";
625
+ state.stateReason = null;
626
+ }
627
+ }
628
+ };
629
+ }
630
+
631
+ // src/domains/scheduling/extension.ts
632
+ var DEFAULT_MAX_WORKERS = 4;
633
+ function resolveMaxWorkers(concurrency) {
634
+ if (concurrency === "auto") return DEFAULT_MAX_WORKERS;
635
+ return Math.max(1, concurrency);
636
+ }
637
+ function createSchedulingBundle(context) {
638
+ const maybeConfig = context.getContract("config");
639
+ if (!maybeConfig) throw new Error("scheduling domain requires 'config' contract");
640
+ const config = maybeConfig;
641
+ const observability = context.getContract("observability");
642
+ const settings = config.get();
643
+ let budget = createBudgetState(settings.budget.sessionCeilingUsd);
644
+ const fleet = createFleetRegistry(() => config.get().fleet?.nodes ?? [], {
645
+ localMaxWorkers: () => resolveMaxWorkers(config.get().budget.concurrency)
646
+ });
647
+ const unsubscribes = [];
648
+ function syncBudget() {
649
+ const nextCeiling = config.get().budget.sessionCeilingUsd;
650
+ if (nextCeiling === budget.ceilingUsd) return;
651
+ budget = createBudgetState(nextCeiling);
652
+ }
653
+ function evaluate() {
654
+ syncBudget();
655
+ const currentUsd = observability?.sessionCost() ?? 0;
656
+ return { verdict: budget.checkCeiling(currentUsd), currentUsd };
657
+ }
658
+ const extension = {
659
+ async start() {
660
+ unsubscribes.push(
661
+ context.bus.on(BusChannels.DispatchEnqueued, () => {
662
+ const { verdict, currentUsd } = evaluate();
663
+ if (verdict !== "under") {
664
+ context.bus.emit(BusChannels.BudgetAlert, {
665
+ level: verdict,
666
+ currentUsd,
667
+ ceilingUsd: budget.ceilingUsd
668
+ });
669
+ }
670
+ })
671
+ );
672
+ },
673
+ async stop() {
674
+ for (const off of unsubscribes) off();
675
+ unsubscribes.length = 0;
676
+ }
677
+ };
678
+ const contract = {
679
+ ceilingUsd: () => {
680
+ syncBudget();
681
+ return budget.ceilingUsd;
682
+ },
683
+ checkCeiling: (current) => {
684
+ syncBudget();
685
+ return budget.checkCeiling(current);
686
+ },
687
+ raiseCeiling: (next) => {
688
+ budget = createBudgetState(next);
689
+ },
690
+ preflight: () => {
691
+ const { verdict, currentUsd } = evaluate();
692
+ return { verdict, currentUsd, ceilingUsd: budget.ceilingUsd };
693
+ },
694
+ maxWorkers: () => resolveMaxWorkers(config.get().budget.concurrency),
695
+ fleet
696
+ };
697
+ return { extension, contract };
698
+ }
699
+
700
+ // src/domains/scheduling/manifest.ts
701
+ var SchedulingManifest = {
702
+ name: "scheduling",
703
+ dependsOn: ["config", "observability"]
704
+ };
705
+
706
+ // src/domains/scheduling/index.ts
707
+ var SchedulingDomainModule = {
708
+ manifest: SchedulingManifest,
709
+ createExtension: createSchedulingBundle
710
+ };
711
+
712
+ export {
713
+ renderAgentCatalogSectionsFromSpecs,
714
+ createPromptsDomainModule,
715
+ SchedulingDomainModule
716
+ };
717
+ //# sourceMappingURL=chunk-3DANZDGR.js.map