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

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 (71) hide show
  1. package/README.md +12 -7
  2. package/dist/__build_info__-D6mXC4cD.mjs +228 -0
  3. package/dist/apply-Mb0fNpCX.mjs +17 -0
  4. package/dist/argument-error-CihH46Le.mjs +27 -0
  5. package/dist/attach-C1OnxyMh.mjs +92 -0
  6. package/dist/attach-CEGbRg1D.mjs +1230 -0
  7. package/dist/bin.mjs +1312 -2390
  8. package/dist/brief-DH66xmj8.mjs +115 -0
  9. package/dist/{decide-CGyx9rv7.mjs → builtin-files-Cf-NZDqM.mjs} +3 -51
  10. package/dist/chips-BqcT58qr.mjs +43 -0
  11. package/dist/command-tree-CEkzWNy6.mjs +63 -0
  12. package/dist/{completion-CSU5vkEt.mjs → completion-DS0gCZRm.mjs} +200 -30
  13. package/dist/context-CGPh12HV.mjs +106 -0
  14. package/dist/detached-Dakw5RZj.mjs +38 -0
  15. package/dist/extra-arguments-BxQMXARO.mjs +13 -0
  16. package/dist/{find-D6Gj1sxg.mjs → find-BTikxc54.mjs} +2 -2
  17. package/dist/flags-C8yCq0j5.mjs +145 -0
  18. package/dist/follow-ups-CtlhHbwe.mjs +563 -0
  19. package/dist/format-BB4E-T6x.mjs +249 -0
  20. package/dist/{help-groups-BwYoAWsh.mjs → help-groups-BpRgBSTh.mjs} +42 -76
  21. package/dist/in-a-run-CbnKjO7t.mjs +27 -0
  22. package/dist/install-CWcpX5g4.mjs +211 -0
  23. package/dist/{limits-B1-DYc3d.mjs → limits-VQqsBoQk.mjs} +2 -2
  24. package/dist/{mcp-DE_EmyVm.mjs → mcp-wGfkMCVF.mjs} +6 -6
  25. package/dist/once-BHxSdZz_.mjs +112 -0
  26. package/dist/orphan-guard-BFKg8VSd.mjs +58 -0
  27. package/dist/output-B1kwo0YU.mjs +439 -0
  28. package/dist/outputs-text-CNTJ7Qq_.mjs +19 -0
  29. package/dist/{pause-CL6N_Xrj.mjs → pause-C_Wxh-KM.mjs} +7 -4
  30. package/dist/print-DNYzq4Rr.mjs +19 -0
  31. package/dist/project-records-XY3ku95x.mjs +233 -0
  32. package/dist/refusals-DQQX3AIb.mjs +116 -0
  33. package/dist/{relay-0SD0erwf.mjs → relay-BA6tsnpc.mjs} +2 -2
  34. package/dist/run-Bvvg-fiF.mjs +234 -0
  35. package/dist/run-DBUAq-Uu.mjs +1452 -0
  36. package/dist/send-nrKtak5F.mjs +105 -0
  37. package/dist/{src-Dujmvv4s.mjs → src-8cOPOgrT.mjs} +12523 -5507
  38. package/dist/{src-BbyEoMn4.mjs → src-CmEvHdju.mjs} +797 -233
  39. package/dist/src-D4JSymhK.mjs +3104 -0
  40. package/dist/{src-DOcK8Jfp.mjs → src-I_RyKu6_.mjs} +1022 -590
  41. package/dist/store-CDpk8Wtz.mjs +16 -0
  42. package/dist/ui/THIRD_PARTY_LICENSES.txt +612 -0
  43. package/dist/ui/assets/app--FijEXiJ.css +1 -0
  44. package/dist/ui/assets/app-BowhjEAe.js +112 -0
  45. package/dist/ui/assets/{index-9dFha9Qn.js → index-CrMa2oHB.js} +3 -3
  46. package/dist/ui/assets/theme-CdXvqTQ6.js +1 -0
  47. package/dist/ui/index.html +2 -2
  48. package/dist/{ui-CTmO2Xzu.mjs → ui-DY3Dnpho.mjs} +54 -25
  49. package/dist/usage-1VwSg_Qt.mjs +257 -0
  50. package/dist/validate-BxayjjkV.mjs +632 -0
  51. package/dist/verdict-CMvPCpWC.mjs +84 -0
  52. package/dist/{watch-CtbgDAcz.mjs → watch-CT0EtLPZ.mjs} +45 -17
  53. package/dist/{workflows-D1_WVukk.mjs → workflows-DHHi-APg.mjs} +30 -5
  54. package/dist/worktrees-CZvbHzbN.mjs +302 -0
  55. package/package.json +10 -8
  56. package/dist/__build_info__-fy6L1Mrd.mjs +0 -615
  57. package/dist/clean-DaHjs__2.mjs +0 -88
  58. package/dist/context-DT8MfEIR.mjs +0 -274
  59. package/dist/format-Dnfv8zMT.mjs +0 -427
  60. package/dist/in-a-run-pLAZeNys.mjs +0 -22
  61. package/dist/list-BrH8KRSJ.mjs +0 -110
  62. package/dist/output-BLQWD6MJ.mjs +0 -950
  63. package/dist/remove-BeGdqroy.mjs +0 -194
  64. package/dist/report-DK4LGqwF.mjs +0 -129
  65. package/dist/send-C8tunWhv.mjs +0 -163
  66. package/dist/src-CCUKRX51.mjs +0 -1204
  67. package/dist/ui/assets/app-BNT0SuIz.css +0 -1
  68. package/dist/ui/assets/app-T7wVAhgx.js +0 -67
  69. package/dist/ui/assets/theme-3xH5jxKs.js +0 -1
  70. package/dist/usage-DYUmP0i4.mjs +0 -419
  71. package/dist/worktrees-DdMYoNOC.mjs +0 -212
@@ -0,0 +1,106 @@
1
+ import { Qr as LESSON_CAP_TOKENS, bt as explainSession } from "./src-8cOPOgrT.mjs";
2
+ import { c as write, s as style } from "./output-B1kwo0YU.mjs";
3
+ import { a as refusedBuiltin, s as workflowArg } from "./workflows-DHHi-APg.mjs";
4
+ import { a as formatReport, t as loadWorkflow } from "./validate-BxayjjkV.mjs";
5
+ import { defineCommand } from "citty";
6
+ // src/commands/context.ts
7
+ /**
8
+ * @file `ork context explain <wf> <node>`: what one node's session would load,
9
+ * layer by layer, as core's `explainSession` plans it without writing
10
+ * anything (one of Ork's own `ork:` workflows is written into the project's
11
+ * run folder first, as `ork run` does): its project instructions, every skill
12
+ * with the layer it came from and whether it is live, shadowed or switched
13
+ * off, its context files, its practices, and estimated tokens.
14
+ */
15
+ /** Loads a workflow file and plans one node's session in it, in place. */
16
+ const explainNode = (file, nodeId, cwd, home) => {
17
+ const { report, workflow, graph, place, workflowDir } = loadWorkflow(file, cwd, home);
18
+ if (workflow === null) return {
19
+ ok: false,
20
+ lines: formatReport(report)
21
+ };
22
+ const result = explainSession(workflow, graph, nodeId, {
23
+ root: place.root,
24
+ orkDir: place.dir,
25
+ workflowDir,
26
+ ...home === void 0 ? {} : { home }
27
+ });
28
+ return result.ok ? result : {
29
+ ok: false,
30
+ lines: [result.error]
31
+ };
32
+ };
33
+ const approx = (count) => style("dim", `≈${count.toLocaleString("en")} tokens`);
34
+ const formatExplanation = (e) => {
35
+ const width = Math.max(8, ...e.skills.map((s) => s.name.length));
36
+ const sourceWidth = Math.max(0, ...e.skills.map((s) => s.source.length));
37
+ const lines = [
38
+ `${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`)}`,
39
+ "",
40
+ ...e.agent === void 0 ? [] : [`${style("bold", "Agent")} ${e.agent.name} ${style("dim", `(${e.agent.where})`)} ${approx(e.agent.tokens)}`],
41
+ `${style("bold", "Instructions")} ${e.instructions}`,
42
+ "",
43
+ style("bold", "Skills")
44
+ ];
45
+ if (e.skills.length === 0) lines.push(style("dim", " none"));
46
+ for (const s of e.skills) {
47
+ const mark = s.state === "live" ? style("green", "✓") : style("dim", "−");
48
+ const state = s.why === void 0 ? approx(s.tokens).replace("tokens", "tokens when used") : style("yellow", `off: ${s.why}`);
49
+ lines.push(` ${mark} ${s.name.padEnd(width)} ${s.layer.padEnd(8)} ${style("dim", s.source.padEnd(sourceWidth))} ${state}`);
50
+ }
51
+ lines.push("", style("bold", "Context files"));
52
+ if (e.files.length === 0) lines.push(style("dim", " none"));
53
+ for (const f of e.files) {
54
+ 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)}`)}`;
55
+ lines.push(` ${f.layer.padEnd(8)} ${f.name} ${approx(f.tokens)}${cut}`);
56
+ }
57
+ lines.push("", style("bold", "Practices"));
58
+ for (const p of e.practices) lines.push(` ${p.name.padEnd(8)} ${approx(p.tokens)}`);
59
+ for (const name of e.skippedPractices) lines.push(` ${name.padEnd(8)} ${style("dim", "the project's own skill wins")}`);
60
+ if (e.practices.length === 0 && e.skippedPractices.length === 0) lines.push(style("dim", " off"));
61
+ lines.push("", `Appended to Claude Code's system prompt: ${approx(e.appendedTokens)}`);
62
+ return lines;
63
+ };
64
+ const explain = defineCommand({
65
+ meta: {
66
+ name: "explain",
67
+ description: "Show what one node's session loads, layer by layer"
68
+ },
69
+ args: {
70
+ workflow: {
71
+ type: "positional",
72
+ description: "A workflow file, the name of one in the project's workflows (.ork/workflows/), or one of Ork's own (ork:feedback-apply)",
73
+ required: true
74
+ },
75
+ node: {
76
+ type: "positional",
77
+ description: "Node id",
78
+ required: true
79
+ },
80
+ json: {
81
+ type: "boolean",
82
+ description: "Print JSON",
83
+ default: false
84
+ }
85
+ },
86
+ run: ({ args }) => {
87
+ const cwd = process.cwd();
88
+ if (refusedBuiltin([args.workflow], cwd)) return;
89
+ const result = explainNode(workflowArg(args.workflow, cwd).file, args.node, cwd);
90
+ if (!result.ok) {
91
+ for (const line of result.lines) process.stderr.write(`${line}\n`);
92
+ process.exitCode = 1;
93
+ return;
94
+ }
95
+ if (args.json) write(JSON.stringify(result.explanation, void 0, 2));
96
+ else for (const line of formatExplanation(result.explanation)) write(line);
97
+ }
98
+ });
99
+ const context = defineCommand({
100
+ meta: {
101
+ name: "context",
102
+ description: "Inspect the context Ork compiles for each node"
103
+ },
104
+ subCommands: { explain }
105
+ });
106
+ export { explainNode as n, context as t };
@@ -0,0 +1,38 @@
1
+ import { pt as detachRun } from "./src-8cOPOgrT.mjs";
2
+ import { n as newRunId } from "./find-BTikxc54.mjs";
3
+ import { c as write, i as detachHint, l as writeErr, s as style } from "./output-B1kwo0YU.mjs";
4
+ // src/run/detached.ts
5
+ /**
6
+ * @file `ork run --detach`: checks what the run would refuse (a `--follow-ups`
7
+ * that can't be taken) before any run folder is made, then starts the run in
8
+ * the background and says how to follow it.
9
+ */
10
+ /** Starts the run in the background; `rawArgs` are `ork run`'s own, as typed. */
11
+ const startDetached = async (store, options) => {
12
+ const { rawArgs, cwd, target } = options;
13
+ const { prepareFollowUps } = await import("./brief-DH66xmj8.mjs");
14
+ if (await prepareFollowUps(store, rawArgs, void 0, target, void 0, false) === void 0) return;
15
+ const single = options.node !== void 0 && options.node !== "";
16
+ const runId = newRunId(store, single ? "node-" : "");
17
+ const detached = await detachRun({
18
+ store,
19
+ runId,
20
+ args: [
21
+ "run",
22
+ ...rawArgs.filter((arg) => arg !== "--detach"),
23
+ "--run-id",
24
+ runId
25
+ ],
26
+ cwd,
27
+ runDir: target.runDir(runId)
28
+ });
29
+ if (detached.ok) {
30
+ write(`▸ run ${detached.runId} started in the background`);
31
+ write(style("dim", ` ${detachHint(detached.runId)}`));
32
+ } else {
33
+ writeErr(detached.error);
34
+ writeErr(style("dim", `(output: ${detached.log})`));
35
+ process.exitCode = 1;
36
+ }
37
+ };
38
+ export { startDetached };
@@ -0,0 +1,13 @@
1
+ import { n as argsOf } from "./command-tree-CEkzWNy6.mjs";
2
+ import { t as argumentError } from "./argument-error-CihH46Le.mjs";
3
+ // src/extra-arguments.ts
4
+ /** Refuses the first word beyond the positionals the command declares. */
5
+ const refuseExtraArguments = {
6
+ name: "refuse-extra-arguments",
7
+ setup: async ({ cmd, args }) => {
8
+ const declared = Object.values(await argsOf(cmd)).filter((def) => def.type === "positional").length;
9
+ const extra = args._[declared];
10
+ if (extra !== void 0) throw argumentError(`Unexpected argument \`${extra}\`.`);
11
+ }
12
+ };
13
+ export { refuseExtraArguments as t };
@@ -1,4 +1,4 @@
1
- import { xn as placeFor } from "./src-Dujmvv4s.mjs";
1
+ import { Gr as placeFor } from "./src-8cOPOgrT.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  // ../core/src/remote/find.ts
4
4
  /**
@@ -16,7 +16,7 @@ const findRun = (store, arg, cwd) => {
16
16
  });
17
17
  return latest === void 0 ? {
18
18
  ok: false,
19
- error: "No runs in this project yet; see `ork ps --all`."
19
+ error: "No runs in this project yet; see `ork ps --project all`."
20
20
  } : {
21
21
  ok: true,
22
22
  run: latest
@@ -0,0 +1,145 @@
1
+ import { Gr as placeFor } from "./src-8cOPOgrT.mjs";
2
+ import { i as parseLimit, n as unknownProjectRefusal, r as parseFilters, t as limitRefusal } from "./refusals-DQQX3AIb.mjs";
3
+ import { t as findRun } from "./find-BTikxc54.mjs";
4
+ import { a as resolved, n as argsOf } from "./command-tree-CEkzWNy6.mjs";
5
+ import { l as writeErr } from "./output-B1kwo0YU.mjs";
6
+ import { t as argumentError } from "./argument-error-CihH46Le.mjs";
7
+ // src/list/known-flags.ts
8
+ /** Names citty reads without the command declaring them. */
9
+ const BUILT_IN = /* @__PURE__ */ new Set([
10
+ "_",
11
+ "help",
12
+ "h"
13
+ ]);
14
+ /** A flag's name without its spelling: `run-id`, `runId` and `run_id` agree. */
15
+ const spelling = (name) => name.replaceAll(/[-_]/gu, "").toLowerCase();
16
+ /** How the flag is typed: `--since`, or `-x` for a one-letter name. */
17
+ const written = (name) => name.length === 1 ? `-${name}` : `--${name}`;
18
+ /** Refuses the first flag the command does not declare. */
19
+ const refuseUnknownFlags = {
20
+ name: "refuse-unknown-flags",
21
+ setup: async ({ cmd, rawArgs, args }) => {
22
+ const [first] = rawArgs;
23
+ const subs = await resolved(cmd.subCommands ?? {});
24
+ if (first !== void 0 && first in subs) return;
25
+ const known = /* @__PURE__ */ new Set();
26
+ for (const [name, def] of Object.entries(await argsOf(cmd))) {
27
+ known.add(spelling(name));
28
+ if ("alias" in def && def.alias !== void 0) for (const alias of [def.alias].flat()) known.add(spelling(alias));
29
+ }
30
+ const unknown = Object.keys(args).find((key) => !BUILT_IN.has(key) && !known.has(spelling(key)));
31
+ if (unknown !== void 0) throw argumentError(`Unknown flag \`${written(unknown)}\`.`);
32
+ }
33
+ };
34
+ // src/list/flags.ts
35
+ /**
36
+ * @file The flags every list command shares (RFC-017), made from its field
37
+ * table: one flag per field (an enum field's values as citty `options`, so
38
+ * `--help` and Tab completion read them), `--ids`, `--limit` and `--json`;
39
+ * and reading them back: each value checked by core's `parseFilters`,
40
+ * `--limit` a positive whole number, `--project` a registered one. A refusal
41
+ * says why on stderr and sets the exit code; the command then returns.
42
+ */
43
+ const fieldArg = (field) => {
44
+ if (field.type !== "enum") return {
45
+ type: "string",
46
+ description: field.description
47
+ };
48
+ return {
49
+ type: "enum",
50
+ options: [...field.values ?? [], ...field.all === true ? ["all"] : []],
51
+ description: field.description
52
+ };
53
+ };
54
+ /** The citty flags of `table`, then `--ids`, `--limit`, `--json`, `extra`. */
55
+ const filterArgs = (table, options = {}) => ({
56
+ ...Object.fromEntries(table.fields.map((field) => [field.name, fieldArg(field)])),
57
+ ...options.ids ?? table.id !== void 0 ? { ids: {
58
+ type: "boolean",
59
+ description: "Print only the ids, comma-separated, on one line",
60
+ default: false
61
+ } } : {},
62
+ ...options.limit ?? true ? { limit: {
63
+ type: "string",
64
+ description: "Show at most this many (a positive whole number)"
65
+ } } : {},
66
+ ...options.json ?? true ? { json: {
67
+ type: "boolean",
68
+ description: "Print JSON",
69
+ default: false
70
+ } } : {},
71
+ ...options.extra
72
+ });
73
+ /** Says why, and makes the command exit 1. */
74
+ const fail = (message) => {
75
+ writeErr(message);
76
+ process.exitCode = 1;
77
+ };
78
+ /** The `--ids` with `--json` refusal; `true` when `args` has both. */
79
+ const refuseIdsWithJson = (args) => {
80
+ if (args.ids !== true || args.json !== true) return false;
81
+ fail("--ids and --json can't be used together.");
82
+ return true;
83
+ };
84
+ /**
85
+ * `args` (a command's parsed flags) read against `table`: the filter, and the
86
+ * limit. `undefined` when something was refused (already said, exit code set).
87
+ */
88
+ const readListArgs = (table, args, options = {}) => {
89
+ if (refuseIdsWithJson(args)) return void 0;
90
+ const parsed = parseFilters(table, args, options.now ?? Date.now());
91
+ if (!parsed.ok) {
92
+ fail(parsed.error);
93
+ return;
94
+ }
95
+ const text = args["limit"];
96
+ if (typeof text !== "string") return {
97
+ filter: parsed.filter,
98
+ limit: void 0
99
+ };
100
+ const limit = parseLimit(text);
101
+ if (limit === null) {
102
+ fail(limitRefusal(text));
103
+ return;
104
+ }
105
+ return {
106
+ filter: parsed.filter,
107
+ limit
108
+ };
109
+ };
110
+ /** The project root a scope other than `all` names. */
111
+ const rootOf = (scope, projects) => scope === "here" ? placeFor(process.cwd(), projects).root : scope.root;
112
+ /**
113
+ * The scope the filter's `project` names, checked against the registered
114
+ * projects (core does not know them): an id or a root, or `all`; none given is
115
+ * `here`. A project not registered is refused, listing the registered ones
116
+ * (said, exit code set, `undefined`).
117
+ */
118
+ const projectScope = (filter, projects) => {
119
+ const key = filter["project"];
120
+ if (key === void 0) return "here";
121
+ if (key === "all") return "all";
122
+ const found = projects.find((p) => p.id === key || p.root === key);
123
+ if (found !== void 0) return { root: found.root };
124
+ fail(unknownProjectRefusal(key, projects.map((p) => p.id)));
125
+ };
126
+ /**
127
+ * `filter` with its `run` (a prefix) made the full id of the run it names, as
128
+ * `ork decide --run` reads it; an unknown or ambiguous run is refused with
129
+ * `findRun`'s message (said, exit code set, `undefined`). No `run` (or an empty
130
+ * one) leaves `filter` as it is.
131
+ */
132
+ const resolveRun = (store, filter) => {
133
+ const run = filter["run"];
134
+ if (run === void 0 || run === "") return filter;
135
+ const found = findRun(store, run, process.cwd());
136
+ if (!found.ok) {
137
+ fail(found.error);
138
+ return;
139
+ }
140
+ return {
141
+ ...filter,
142
+ run: found.run.id
143
+ };
144
+ };
145
+ export { refuseIdsWithJson as a, refuseUnknownFlags as c, readListArgs as i, filterArgs as n, resolveRun as o, projectScope as r, rootOf as s, fail as t };