@krapht/ork 1.0.0-alpha.1 → 1.0.0-alpha.11

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 (43) hide show
  1. package/README.md +3 -4
  2. package/dist/{__build_info__-D9lSlMFy.mjs → __build_info__-CIchF6nr.mjs} +2 -2
  3. package/dist/bin.mjs +1479 -600
  4. package/dist/chips-BA7SrrH5.mjs +43 -0
  5. package/dist/{clean-CA_Oi2Wl.mjs → clean-Di-KT7Mf.mjs} +5 -2
  6. package/dist/{completion-DBGfL-gN.mjs → completion-C5D0sEs5.mjs} +23 -16
  7. package/dist/context-BaNshWr9.mjs +695 -0
  8. package/dist/{decide-CoIJh34e.mjs → decide-B6PnKeqo.mjs} +3 -3
  9. package/dist/{find-rBBk7Jui.mjs → find-BicBbGMg.mjs} +1 -1
  10. package/dist/format-lWhN-jYR.mjs +286 -0
  11. package/dist/{in-a-run-DdAakpRR.mjs → in-a-run-CgkVouyG.mjs} +1 -1
  12. package/dist/{limits-BPM9wUlV.mjs → limits-jZQp9ZJC.mjs} +1 -1
  13. package/dist/{list-Bv5Lxu7z.mjs → list-CEaJ07jd.mjs} +11 -4
  14. package/dist/{mcp-DM30MFBw.mjs → mcp-DYgVA9f5.mjs} +6 -6
  15. package/dist/output-CM95njYt.mjs +421 -0
  16. package/dist/{pause-C7lJkSma.mjs → pause-D6PuSlNl.mjs} +4 -4
  17. package/dist/{relay-BipJYszF.mjs → relay-DNx7be9k.mjs} +2 -2
  18. package/dist/{remove-BDs9isB6.mjs → remove-CpMb4NDl.mjs} +14 -7
  19. package/dist/{report-DK4LGqwF.mjs → report-CEN8VoUb.mjs} +31 -20
  20. package/dist/{send-nbkjf3sc.mjs → send-CLs_fyg7.mjs} +3 -3
  21. package/dist/{src-BxUJPGa5.mjs → src-9iGkjnsy.mjs} +487 -341
  22. package/dist/{src-B0TT7DBi.mjs → src-B6KvTm7B.mjs} +106 -90
  23. package/dist/src-BnZgZGrf.mjs +2697 -0
  24. package/dist/{src-hrj2h0IZ.mjs → src-D6_xjm-x.mjs} +6719 -3389
  25. package/dist/ui/THIRD_PARTY_LICENSES.txt +594 -0
  26. package/dist/ui/assets/app-CxURph7a.js +75 -0
  27. package/dist/ui/assets/app-QoHVi-mb.css +1 -0
  28. package/dist/ui/assets/{index-CPx74lFf.js → index-By_8KKG6.js} +3 -3
  29. package/dist/ui/assets/theme-CdXvqTQ6.js +1 -0
  30. package/dist/ui/index.html +2 -2
  31. package/dist/{ui-B98FSboa.mjs → ui-CIci4UBW.mjs} +4 -4
  32. package/dist/{usage-EW7DI6Z7.mjs → usage-GceBGMjU.mjs} +43 -32
  33. package/dist/{watch-BAkSGaOp.mjs → watch-BmoybMQg.mjs} +28 -16
  34. package/dist/{workflows-vsEohqa7.mjs → workflows-DZvW3i1e.mjs} +4 -3
  35. package/dist/{worktrees-Ahj9rdWK.mjs → worktrees-Be51E2rB.mjs} +84 -24
  36. package/package.json +2 -4
  37. package/dist/context-6x3kXREO.mjs +0 -274
  38. package/dist/format-zMmhqyLE.mjs +0 -427
  39. package/dist/output-TV_j7Ni0.mjs +0 -950
  40. package/dist/src-B9v0lDc6.mjs +0 -1204
  41. package/dist/ui/assets/app-BNT0SuIz.css +0 -1
  42. package/dist/ui/assets/app-CmkynZyW.js +0 -67
  43. package/dist/ui/assets/theme-3xH5jxKs.js +0 -1
@@ -1,274 +0,0 @@
1
- import { C as workflowTextHash, Ct as walkChecks, On as LESSON_CAP_TOKENS, S as readProjectTriggers, St as checkWorkflowText, Tn as workflowDirOf, bn as placeFiles, lt as explainSession, wt as walkSummary, xn as placeFor } from "./src-hrj2h0IZ.mjs";
2
- import { a as write, i as style, r as plain } from "./output-TV_j7Ni0.mjs";
3
- import { c as registeredProjects, i as refusedBuiltin, o as workflowArg, r as findWorkflowFiles, s as projectAt } from "./workflows-vsEohqa7.mjs";
4
- import path from "node:path";
5
- import { readFileSync } from "node:fs";
6
- import { defineCommand } from "citty";
7
- // src/commands/walk-report.ts
8
- /**
9
- * @file How `ork validate` shows a walk (RFC-009): one line on what it tried,
10
- * and with `--paths`, each way a run can end. A gate's answer that ends the
11
- * run shows here as an ending, not as a problem.
12
- */
13
- const walkLine = (walk) => walk === void 0 ? [] : [style("dim", walkSummary(walk))];
14
- const endingLine = ({ status, notRun, paths }) => {
15
- const ways = `${String(paths)} ${paths === 1 ? "way" : "ways"}`;
16
- const word = status === "succeeded" ? style("green", status) : style("red", status);
17
- const rest = notRun.length === 0 ? "every node ran" : `didn't run: ${notRun.map((id) => plain(id)).join(", ")}`;
18
- return ` ${word} ${style("dim", `(${ways})`)} ${rest}`;
19
- };
20
- const endingLines = (ending) => [endingLine(ending), ...ending.choices.map((choice) => style("dim", ` ${plain(choice)}`))];
21
- /** Each ending, the ones that succeeded first, with one way to get there. */
22
- const pathLines = (walk) => {
23
- const endings = walk?.endings ?? [];
24
- return [...endings.filter(({ status }) => status === "succeeded"), ...endings.filter(({ status }) => status !== "succeeded")].flatMap((ending) => endingLines(ending));
25
- };
26
- // src/commands/validate.ts
27
- /**
28
- * @file `ork validate`: loads, parses and compiles workflow files with the
29
- * project's rules (`.ork/project.yaml`) and the agents they name, checks
30
- * their skill and context references, and reports diagnostics compiler-style,
31
- * with file, line and column. `loadWorkflow` is shared with `ork run`.
32
- */
33
- const hasErrors = (diagnostics) => diagnostics.some((d) => d.severity === "error");
34
- /**
35
- * Parses and compiles one workflow file, with the agents the user and its
36
- * project offer. `home` is the user's `~` (tests pass a folder); `registered`
37
- * the projects a caller's store has, else those of the store in `home`.
38
- */
39
- const loadWorkflow = (file, cwd, home, registered = registeredProjects(home)) => {
40
- const absolute = path.resolve(cwd, file);
41
- const place = placeFor(path.dirname(absolute), registered);
42
- const where = {
43
- place,
44
- workflowDir: workflowDirOf(place, absolute)
45
- };
46
- let text;
47
- try {
48
- text = readFileSync(path.resolve(cwd, file), "utf8");
49
- } catch (error) {
50
- return {
51
- report: {
52
- file,
53
- diagnostics: [{
54
- severity: "error",
55
- code: "file.read",
56
- message: error instanceof Error && "code" in error && error.code === "ENOENT" ? "file not found" : "cannot read file",
57
- path: []
58
- }]
59
- },
60
- workflow: null,
61
- graph: null,
62
- ...where
63
- };
64
- }
65
- const { diagnostics, workflow, graph, summary, locate } = checkWorkflowText(text, {
66
- ...where,
67
- registered,
68
- home
69
- });
70
- return {
71
- report: {
72
- file,
73
- diagnostics,
74
- ...summary === void 0 ? {} : { summary }
75
- },
76
- workflow,
77
- graph,
78
- textHash: workflowTextHash(text),
79
- ...locate === void 0 ? {} : { locate },
80
- ...where
81
- };
82
- };
83
- const validateFile = (file, cwd) => loadWorkflow(file, cwd).report;
84
- /**
85
- * Walks what loaded, with its findings on its report. `ork validate` and `ork
86
- * run` do this; the rest of what loads a workflow doesn't pay for a walk.
87
- */
88
- const walkLoaded = async (loaded) => {
89
- const { diagnostics, walk } = await walkChecks({
90
- diagnostics: loaded.report.diagnostics,
91
- graph: loaded.graph,
92
- ...loaded.locate === void 0 ? {} : { locate: loaded.locate }
93
- });
94
- return {
95
- ...loaded,
96
- report: {
97
- ...loaded.report,
98
- diagnostics,
99
- ...walk === void 0 ? {} : { walk }
100
- }
101
- };
102
- };
103
- const plural = (count, word) => `${count} ${word}${count === 1 ? "" : "s"}`;
104
- const diagnosticLine = (file, d) => {
105
- const where = d.line === void 0 ? file : `${file}:${d.line}:${d.column ?? 1}`;
106
- const severity = d.severity === "error" ? style(["red", "bold"], "error") : style(["yellow", "bold"], "warning");
107
- return `${style("dim", where)} ${severity} ${d.message} ${style("dim", `(${d.code})`)}`;
108
- };
109
- /** The warnings alone, for a run that goes ahead despite them. */
110
- const warningLines = (report) => report.diagnostics.filter((d) => d.severity === "warning").map((d) => diagnosticLine(report.file, d));
111
- /** Human-readable report, one line per diagnostic, compiler style. */
112
- const formatReport = (report) => {
113
- const lines = report.diagnostics.map((d) => diagnosticLine(report.file, d));
114
- const errors = report.diagnostics.filter((d) => d.severity === "error").length;
115
- const warnings = report.diagnostics.length - errors;
116
- if (report.summary === void 0 && errors === 0) lines.push(`${style("green", "✓")} ${report.file}${warnings === 0 ? "" : style("dim", ` (${plural(warnings, "warning")})`)}`);
117
- else if (report.summary !== void 0 && errors === 0) {
118
- const { nodes, edges, entries } = report.summary;
119
- const extra = warnings > 0 ? `, ${plural(warnings, "warning")}` : "";
120
- lines.push(`${style("green", "✓")} ${report.file} ${style("dim", `(${plural(nodes, "node")}, ${plural(edges, "edge")}, starts at ${entries.join(", ")}${extra})`)}`);
121
- } else lines.push(`${style("red", "✗")} ${report.file} ${style("dim", `(${plural(errors, "error")}, ${plural(warnings, "warning")})`)}`);
122
- return [...lines, ...walkLine(report.walk)];
123
- };
124
- const validate = defineCommand({
125
- meta: {
126
- name: "validate",
127
- description: "Check workflow files: schema, ownership tree, edges, loops and references, and walk every way through them"
128
- },
129
- args: {
130
- files: {
131
- type: "positional",
132
- description: "Workflow files or names in .ork/workflows/ (default: every workflow there, and the project's triggers)",
133
- required: false
134
- },
135
- json: {
136
- type: "boolean",
137
- description: "Print the reports as JSON",
138
- default: false
139
- },
140
- paths: {
141
- type: "boolean",
142
- description: "List each way a run can end, and the choices that lead there",
143
- default: false
144
- }
145
- },
146
- run: async ({ args }) => {
147
- const cwd = process.cwd();
148
- if (refusedBuiltin(args._, cwd)) return;
149
- const files = findWorkflowFiles(args._, cwd, placeFiles(projectAt(cwd)).workflows);
150
- if (files.length === 0) {
151
- write("No workflow files found. Run `ork init`, or pass a path.");
152
- process.exitCode = 1;
153
- return;
154
- }
155
- const place = projectAt(cwd);
156
- const triggers = args._.length === 0 ? readProjectTriggers(place, void 0, registeredProjects()) : void 0;
157
- const walked = [];
158
- for (const file of files) {
159
- const { report } = await walkLoaded(loadWorkflow(file, cwd));
160
- walked.push(report);
161
- }
162
- const reports = [...walked, ...triggers?.present === true ? [{
163
- file: path.relative(cwd, triggers.file),
164
- diagnostics: [...triggers.diagnostics, ...triggers.triggers.flatMap((item) => item.diagnostics)]
165
- }] : []];
166
- if (args.json) write(JSON.stringify(reports, void 0, 2));
167
- else for (const report of reports) {
168
- for (const line of formatReport(report)) write(line);
169
- if (args.paths) for (const line of pathLines(report.walk)) write(line);
170
- }
171
- if (reports.some((r) => hasErrors(r.diagnostics))) process.exitCode = 1;
172
- }
173
- });
174
- // src/commands/context.ts
175
- /**
176
- * @file `ork context explain <wf> <node>`: what one node's session would load,
177
- * layer by layer, as core's `explainSession` plans it without writing
178
- * anything (one of Ork's own `ork:` workflows is written into the project's
179
- * run folder first, as `ork run` does): its project instructions, every skill
180
- * with the layer it came from and whether it is live, shadowed or switched
181
- * off, its context files, its practices, and estimated tokens.
182
- */
183
- /** Loads a workflow file and plans one node's session in it, in place. */
184
- const explainNode = (file, nodeId, cwd, home) => {
185
- const { report, workflow, graph, place, workflowDir } = loadWorkflow(file, cwd, home);
186
- if (workflow === null) return {
187
- ok: false,
188
- lines: formatReport(report)
189
- };
190
- const result = explainSession(workflow, graph, nodeId, {
191
- root: place.root,
192
- orkDir: place.dir,
193
- workflowDir,
194
- ...home === void 0 ? {} : { home }
195
- });
196
- return result.ok ? result : {
197
- ok: false,
198
- lines: [result.error]
199
- };
200
- };
201
- const approx = (count) => style("dim", `≈${count.toLocaleString("en")} tokens`);
202
- const formatExplanation = (e) => {
203
- const width = Math.max(8, ...e.skills.map((s) => s.name.length));
204
- const sourceWidth = Math.max(0, ...e.skills.map((s) => s.source.length));
205
- const lines = [
206
- `${style("bold", e.node)} ${style("dim", `(${e.type}) in ${e.workflow}`)}${e.template === void 0 ? "" : style("dim", `, planned as ${e.template}, the node it was spawned from`)}`,
207
- "",
208
- ...e.agent === void 0 ? [] : [`${style("bold", "Agent")} ${e.agent.name} ${style("dim", `(${e.agent.where})`)} ${approx(e.agent.tokens)}`],
209
- `${style("bold", "Instructions")} ${e.instructions}`,
210
- "",
211
- style("bold", "Skills")
212
- ];
213
- if (e.skills.length === 0) lines.push(style("dim", " none"));
214
- for (const s of e.skills) {
215
- const mark = s.state === "live" ? style("green", "✓") : style("dim", "−");
216
- const state = s.why === void 0 ? approx(s.tokens).replace("tokens", "tokens when used") : style("yellow", `off: ${s.why}`);
217
- lines.push(` ${mark} ${s.name.padEnd(width)} ${s.layer.padEnd(8)} ${style("dim", s.source.padEnd(sourceWidth))} ${state}`);
218
- }
219
- lines.push("", style("bold", "Context files"));
220
- if (e.files.length === 0) lines.push(style("dim", " none"));
221
- for (const f of e.files) {
222
- const cut = f.cutFrom === void 0 ? "" : ` ${style("yellow", `cut at the ${LESSON_CAP_TOKENS.toLocaleString("en")}-token cap; the whole file is ${approx(f.cutFrom)}`)}`;
223
- lines.push(` ${f.layer.padEnd(8)} ${f.name} ${approx(f.tokens)}${cut}`);
224
- }
225
- lines.push("", style("bold", "Practices"));
226
- for (const p of e.practices) lines.push(` ${p.name.padEnd(8)} ${approx(p.tokens)}`);
227
- for (const name of e.skippedPractices) lines.push(` ${name.padEnd(8)} ${style("dim", "the project's own skill wins")}`);
228
- if (e.practices.length === 0 && e.skippedPractices.length === 0) lines.push(style("dim", " off"));
229
- lines.push("", `Appended to Claude Code's system prompt: ${approx(e.appendedTokens)}`);
230
- return lines;
231
- };
232
- const explain = defineCommand({
233
- meta: {
234
- name: "explain",
235
- description: "Show what one node's session loads, layer by layer"
236
- },
237
- args: {
238
- workflow: {
239
- type: "positional",
240
- description: "A workflow file, the name of one in the project's workflows (.ork/workflows/), or one of Ork's own (ork:feedback-apply)",
241
- required: true
242
- },
243
- node: {
244
- type: "positional",
245
- description: "Node id",
246
- required: true
247
- },
248
- json: {
249
- type: "boolean",
250
- description: "Print JSON",
251
- default: false
252
- }
253
- },
254
- run: ({ args }) => {
255
- const cwd = process.cwd();
256
- if (refusedBuiltin([args.workflow], cwd)) return;
257
- const result = explainNode(workflowArg(args.workflow, cwd).file, args.node, cwd);
258
- if (!result.ok) {
259
- for (const line of result.lines) process.stderr.write(`${line}\n`);
260
- process.exitCode = 1;
261
- return;
262
- }
263
- if (args.json) write(JSON.stringify(result.explanation, void 0, 2));
264
- else for (const line of formatExplanation(result.explanation)) write(line);
265
- }
266
- });
267
- const context = defineCommand({
268
- meta: {
269
- name: "context",
270
- description: "Inspect the context Ork compiles for each node"
271
- },
272
- subCommands: { explain }
273
- });
274
- export { validate as a, warningLines as c, loadWorkflow as i, explainNode as n, validateFile as o, formatReport as r, walkLoaded as s, context as t };