@krapht/ork 1.0.0-alpha.2 → 1.0.0-alpha.21

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 (75) hide show
  1. package/README.md +12 -7
  2. package/dist/__build_info__-0wqQ-rtf.mjs +180 -0
  3. package/dist/apply-Mb0fNpCX.mjs +17 -0
  4. package/dist/argument-error-CihH46Le.mjs +27 -0
  5. package/dist/attach-C0-YyNoY.mjs +92 -0
  6. package/dist/attach-CAKNqnUK.mjs +1259 -0
  7. package/dist/bin.mjs +1885 -1609
  8. package/dist/brief-C2hew8cS.mjs +116 -0
  9. package/dist/{decide-CGyx9rv7.mjs → builtin-files-YYAnbZGD.mjs} +3 -51
  10. package/dist/chips-CP_pgKlj.mjs +48 -0
  11. package/dist/command-tree-CEkzWNy6.mjs +63 -0
  12. package/dist/{completion-CSU5vkEt.mjs → completion-K4rAVsrf.mjs} +200 -30
  13. package/dist/context-B-fjPJky.mjs +106 -0
  14. package/dist/context-DMK0U1w0.mjs +160 -0
  15. package/dist/detached-q0AYG0Bs.mjs +39 -0
  16. package/dist/extra-arguments-BxQMXARO.mjs +13 -0
  17. package/dist/{find-D6Gj1sxg.mjs → find-Ct5CNl1J.mjs} +2 -2
  18. package/dist/flags-C90N4J1i.mjs +145 -0
  19. package/dist/follow-ups-D3HPyNYM.mjs +568 -0
  20. package/dist/format-CiPhQqbX.mjs +260 -0
  21. package/dist/{help-groups-BwYoAWsh.mjs → help-groups-BQvcKQ9H.mjs} +49 -78
  22. package/dist/in-a-run-D_wg4iJi.mjs +27 -0
  23. package/dist/install-Hji6LIei.mjs +259 -0
  24. package/dist/{limits-B1-DYc3d.mjs → limits-BD6RZRCS.mjs} +2 -2
  25. package/dist/{mcp-DE_EmyVm.mjs → mcp-CpbDmBLG.mjs} +6 -6
  26. package/dist/once-J8Qn5fTG.mjs +112 -0
  27. package/dist/orphan-guard-BFKg8VSd.mjs +58 -0
  28. package/dist/output-DXZbnFt_.mjs +458 -0
  29. package/dist/outputs-text-CNTJ7Qq_.mjs +19 -0
  30. package/dist/{pause-CL6N_Xrj.mjs → pause-Cl4ZYA35.mjs} +7 -4
  31. package/dist/print-DzugGZQB.mjs +19 -0
  32. package/dist/project-records-CtkmlsHN.mjs +233 -0
  33. package/dist/refusals-DQQX3AIb.mjs +116 -0
  34. package/dist/{relay-0SD0erwf.mjs → relay-CiP77vga.mjs} +2 -2
  35. package/dist/run-CtuNY3mE.mjs +234 -0
  36. package/dist/send-DRYGks8K.mjs +104 -0
  37. package/dist/short-flags-DkJLWVqh.mjs +1 -0
  38. package/dist/short-flags-Qf21as0E.mjs +83 -0
  39. package/dist/src-BMFQKHz4.mjs +3122 -0
  40. package/dist/{src-BbyEoMn4.mjs → src-BrFfDKux.mjs} +800 -235
  41. package/dist/{src-Dujmvv4s.mjs → src-BuF9Lbow.mjs} +12580 -5505
  42. package/dist/{src-DOcK8Jfp.mjs → src-k0A_QpST.mjs} +1024 -590
  43. package/dist/store-rTgRu8xy.mjs +25 -0
  44. package/dist/ui/THIRD_PARTY_LICENSES.txt +612 -0
  45. package/dist/ui/assets/app-BYxpKJRh.css +1 -0
  46. package/dist/ui/assets/app-SEFEJLkF.js +112 -0
  47. package/dist/ui/assets/{index-9dFha9Qn.js → index-Cb6Voq_W.js} +3 -3
  48. package/dist/ui/assets/theme-CdXvqTQ6.js +1 -0
  49. package/dist/ui/index.html +2 -2
  50. package/dist/{ui-CTmO2Xzu.mjs → ui-C2f37TSb.mjs} +57 -25
  51. package/dist/usage-BuvGcQSk.mjs +256 -0
  52. package/dist/validate-ObP5lt29.mjs +1 -0
  53. package/dist/validate-_HjACtk9.mjs +632 -0
  54. package/dist/verdict-B592j1W3.mjs +84 -0
  55. package/dist/{watch-CtbgDAcz.mjs → watch-DV3ixCYj.mjs} +45 -17
  56. package/dist/{workflows-D1_WVukk.mjs → workflows-QLjBhGNS.mjs} +30 -5
  57. package/dist/worktrees-D3ubG_Qw.mjs +302 -0
  58. package/dist/yolo-BSH1E_kE.mjs +33 -0
  59. package/package.json +10 -8
  60. package/dist/__build_info__-fy6L1Mrd.mjs +0 -615
  61. package/dist/clean-DaHjs__2.mjs +0 -88
  62. package/dist/context-DT8MfEIR.mjs +0 -274
  63. package/dist/format-Dnfv8zMT.mjs +0 -427
  64. package/dist/in-a-run-pLAZeNys.mjs +0 -22
  65. package/dist/list-BrH8KRSJ.mjs +0 -110
  66. package/dist/output-BLQWD6MJ.mjs +0 -950
  67. package/dist/remove-BeGdqroy.mjs +0 -194
  68. package/dist/report-DK4LGqwF.mjs +0 -129
  69. package/dist/send-C8tunWhv.mjs +0 -163
  70. package/dist/src-CCUKRX51.mjs +0 -1204
  71. package/dist/ui/assets/app-BNT0SuIz.css +0 -1
  72. package/dist/ui/assets/app-T7wVAhgx.js +0 -67
  73. package/dist/ui/assets/theme-3xH5jxKs.js +0 -1
  74. package/dist/usage-DYUmP0i4.mjs +0 -419
  75. package/dist/worktrees-DdMYoNOC.mjs +0 -212
@@ -1,88 +0,0 @@
1
- import { A as gitOk, O as removeWorktree } from "./src-Dujmvv4s.mjs";
2
- // ../core/src/worktree/clean.ts
3
- /**
4
- * @file What `ork worktrees clean` and `ork worktrees remove` do with what
5
- * list.ts reads: the plan (what goes, what's kept and why), by one rule for
6
- * every caller, and carrying it out. The CLI and the Worktrees panel both
7
- * plan here, so neither removes what the other would keep.
8
- */
9
- /** What names an item for `remove`: its branch, or its worktree's path. */
10
- const keyOf = (item) => item.branch ?? item.path ?? `${item.runId}/${item.nodeId}`;
11
- /** The reasons no `force` overrides: removing would break something. */
12
- const MAIN_CHECKOUT = "checked out in the main checkout";
13
- const RUN_GOING = "its run is still going";
14
- const kept = (item, skip) => ({
15
- item,
16
- removeWorktree: false,
17
- deleteBranch: false,
18
- skip
19
- });
20
- /** What clean does with one item. */
21
- const cleanStep = (item, options) => {
22
- if (item.inMainCheckout) return kept(item, MAIN_CHECKOUT);
23
- if (item.heldBy !== void 0) return kept(item, `checked out in ${item.heldBy}`);
24
- if (options.live?.has(item.runId) === true) return kept(item, RUN_GOING);
25
- if (item.dirty && !options.force) return kept(item, "uncommitted changes");
26
- if (item.branch === void 0 && item.checkedOut === void 0 && item.ahead > 0 && !options.force) return kept(item, "commits on no branch");
27
- const removable = item.path !== null && !item.missing;
28
- if (options.branches && item.branch !== void 0 && !item.merged && !options.force) return {
29
- item,
30
- removeWorktree: removable,
31
- deleteBranch: false,
32
- skip: "branch not merged"
33
- };
34
- return {
35
- item,
36
- removeWorktree: removable,
37
- deleteBranch: options.branches && item.branch !== void 0
38
- };
39
- };
40
- /** Whether a step drops a worktree whose folder is gone, by its own path. */
41
- const stepPrunes = (step) => step.item.missing && step.item.path !== null && step.skip === void 0;
42
- /** Whether a step does anything. */
43
- const stepActs = (step) => step.removeWorktree || step.deleteBranch || stepPrunes(step);
44
- /**
45
- * What `ork worktrees clean` would do. A worktree with uncommitted changes, an
46
- * unmerged branch, or a detached worktree holding commits no branch has, is
47
- * kept unless `force`; one checked out in the main checkout or in a worktree
48
- * Ork didn't create, or whose run is still going, is kept even then.
49
- */
50
- const planClean = (items, filter, options) => items.filter((item) => filter.runId === void 0 || item.runId === filter.runId).filter((item) => filter.key === void 0 || keyOf(item) === filter.key).filter((item) => !filter.merged || item.merged).map((item) => cleanStep(item, options));
51
- /**
52
- * Carries out one step; what it did goes into `done` as it goes. It touches
53
- * only its own item: a missing worktree is dropped by its own path (`git
54
- * worktree remove`), never by `git worktree prune`, which would drop every
55
- * missing worktree in the repository, the user's own included.
56
- */
57
- const applyStep = async (root, step, force, done) => {
58
- const { item } = step;
59
- if (stepPrunes(step) && !step.removeWorktree && item.path !== null) {
60
- await gitOk(root, [
61
- "worktree",
62
- "remove",
63
- item.path
64
- ]);
65
- done.push(`pruned ${item.path}`);
66
- }
67
- if (step.removeWorktree && item.path !== null) {
68
- await removeWorktree(root, item.path, force);
69
- done.push(`removed ${item.path}`);
70
- }
71
- if (step.deleteBranch && item.branch !== void 0) {
72
- await gitOk(root, [
73
- "branch",
74
- force ? "-D" : "-d",
75
- item.branch
76
- ]);
77
- done.push(`deleted ${item.branch}`);
78
- }
79
- };
80
- /**
81
- * Carries out a clean plan, step by step. What it did goes into `done` as it
82
- * goes, so a caller still has it when git fails halfway.
83
- */
84
- const applyClean = async (root, steps, force, done = []) => {
85
- for (const step of steps) await applyStep(root, step, force, done);
86
- return done;
87
- };
88
- export { planClean as a, keyOf as i, applyStep as n, stepActs as o, cleanStep as r, stepPrunes as s, applyClean as t };
@@ -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-Dujmvv4s.mjs";
2
- import { a as write, i as style, r as plain } from "./output-BLQWD6MJ.mjs";
3
- import { c as registeredProjects, i as refusedBuiltin, o as workflowArg, r as findWorkflowFiles, s as projectAt } from "./workflows-D1_WVukk.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 };