@cruxy/cli 1.11.1 → 1.11.3

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 (48) hide show
  1. package/dist/agent/instruction-loss.js +204 -0
  2. package/dist/agent/prompts.js +25 -4
  3. package/dist/agent/session.js +165 -33
  4. package/dist/agent/status.js +18 -0
  5. package/dist/checkpoint/service.js +44 -3
  6. package/dist/cli/commands/pr.js +14 -0
  7. package/dist/cli/commands/run.js +35 -0
  8. package/dist/cli/commands/sessions.js +8 -0
  9. package/dist/cli/session-commands.js +3 -1
  10. package/dist/cli/session-factory.js +54 -6
  11. package/dist/config/schema.js +9 -0
  12. package/dist/errors/constructors.js +15 -6
  13. package/dist/errors/types.js +7 -0
  14. package/dist/indexing/embedder.js +34 -11
  15. package/dist/indexing/model-cache.js +399 -0
  16. package/dist/mcp/bounds.js +8 -1
  17. package/dist/plan/execute.js +4 -1
  18. package/dist/plan/service.js +42 -5
  19. package/dist/plan/step-message.js +49 -0
  20. package/dist/render/context-view.js +44 -1
  21. package/dist/render/status-view.js +13 -0
  22. package/dist/session/index.js +7 -3
  23. package/dist/session/log.js +163 -2
  24. package/dist/session/owner.js +123 -0
  25. package/dist/session/prune.js +11 -0
  26. package/dist/session/recorded-runs.js +56 -0
  27. package/dist/session/replay.js +75 -1
  28. package/dist/session/resume.js +110 -3
  29. package/dist/session/types.js +158 -0
  30. package/dist/subagent/orchestrator.js +2 -2
  31. package/dist/subagent/registry-scope.js +28 -5
  32. package/dist/testing/run-tests-tool.js +3 -1
  33. package/dist/tools/create-pull-request.js +8 -1
  34. package/dist/tools/file/apply-patch.js +53 -23
  35. package/dist/tools/file/edit-file.js +19 -1
  36. package/dist/tools/file/snapshot.js +68 -0
  37. package/dist/tools/file/write-file.js +31 -5
  38. package/dist/tools/registry.js +39 -8
  39. package/dist/tools/schema-depth.js +79 -6
  40. package/dist/tools/shell/exec.js +7 -0
  41. package/dist/tools/shell/run-command.js +45 -21
  42. package/dist/utils/process-owner.js +107 -0
  43. package/dist/vcs/generate.js +48 -6
  44. package/dist/verification/index.js +15 -0
  45. package/dist/verification/ledger.js +99 -0
  46. package/dist/verification/types.js +26 -0
  47. package/dist/verification/view.js +87 -0
  48. package/package.json +3 -2
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The verification record (P2 verification): what ran, and how it exited.
3
+ *
4
+ * The loop's only completion criterion is "the model emitted no tool calls"
5
+ * (`agent/loop.ts`). Nothing checks that tests ran, a build passed, or a diff
6
+ * was reviewed, and the system prompt's instruction to verify is exactly that:
7
+ * an instruction. This module makes the absence VISIBLE without making the
8
+ * presence MANDATORY — C.13 shipped voluntary verification and delegated the
9
+ * iteration to the ordinary loop, and that decision stands. Three reasons it
10
+ * is not reversed here:
11
+ *
12
+ * - `run_tests`' failing-run breaker latches for the turn after
13
+ * `test.maxIterations` runs, so a turn that MUST end green could never end.
14
+ * - A project with no test command has no defensible verdict: the coded
15
+ * not-found error already tells the model to ask the user, not to guess.
16
+ * - Enforcement changes the one-shot exit contract — "completed but
17
+ * unverified" would be a new stop kind, and CI reads that exit code today.
18
+ *
19
+ * So this is EVIDENCE: a record of each run that actually executed, keyed to
20
+ * the turn it ran in, read back by the surfaces a user checks afterwards. What
21
+ * it never does is INFER. `passed` is the exit code and nothing else; nothing
22
+ * here decides that a command was "a build" or "the tests" from its text. The
23
+ * record says what ran and how it exited; the reader judges.
24
+ */
25
+ /** Most failure names kept per record — an index, not a transcript. */
26
+ export const MAX_FAILURE_NAMES = 5;
@@ -0,0 +1,87 @@
1
+ import { formatDuration } from "../render/test-view.js";
2
+ /**
3
+ * Rendering the verification record — the shared formatter behind every
4
+ * surface that reads it, so the one-shot summary, `/status`, the resume
5
+ * notice and the PR body all describe a run the same way.
6
+ *
7
+ * The honesty rules are `verification/types`'s, carried through rather than
8
+ * re-derived: the exit code is the fact, the tool and command are named as
9
+ * they ran, and nothing here calls a run "the build" or "the tests" from its
10
+ * text. A non-zero exit is shown as that exit — never as "1 test failed"
11
+ * unless a parser actually counted one.
12
+ */
13
+ /** `run_tests pnpm test → exit 0 (4.2s)`, coloured by exit. */
14
+ export function describeRun(rec, t) {
15
+ const exit = rec.exitCode === null ? "no exit code" : `exit ${rec.exitCode}`;
16
+ const verdict = rec.passed ? t.muted(exit) : t.danger(exit);
17
+ const counts = countClause(rec);
18
+ return (`${t.muted(rec.tool)} ${rec.command} ${t.glyph.arrow} ${verdict}` +
19
+ (counts ? ` ${t.danger(counts)}` : "") +
20
+ ` ${t.muted(`(${formatDuration(rec.durationMs)})`)}`);
21
+ }
22
+ /** "3 of 128 failed" / "3 failures" / "" — only what a parser actually counted. */
23
+ function countClause(rec) {
24
+ if (rec.passed)
25
+ return "";
26
+ if (rec.total !== undefined && rec.failureCount > 0)
27
+ return `${rec.failureCount} of ${rec.total} failed`;
28
+ if (rec.failureCount > 0)
29
+ return `${rec.failureCount} failure${rec.failureCount === 1 ? "" : "s"}`;
30
+ return "";
31
+ }
32
+ /**
33
+ * The one-shot summary's block (the CI reader). Printed next to the exit code
34
+ * CI already trusts, for BOTH a completed run and one that gave up, so the
35
+ * line that says "completed" is never read on its own.
36
+ *
37
+ * "none ran this turn" is a sentence, not an omitted row: the whole point of
38
+ * the record is that the absence of verification is visible.
39
+ */
40
+ export function verificationTurnLines(turn, t) {
41
+ const lines = [];
42
+ const key = t.strong("verification");
43
+ if (turn.verifications.length === 0) {
44
+ lines.push(`${key} ${t.warning("none ran this turn")}`);
45
+ }
46
+ else {
47
+ turn.verifications.forEach((rec, i) => {
48
+ lines.push(`${i === 0 ? key : " ".repeat(12)} ${describeRun(rec, t)}`);
49
+ });
50
+ }
51
+ turn.externalChanges.forEach((change, i) => {
52
+ lines.push(`${i === 0 ? t.strong("refused") : " ".repeat(7)} ${t.warning(`${change.path} ${change.what} — nothing was written`)}`);
53
+ });
54
+ return lines;
55
+ }
56
+ /**
57
+ * The `## Verification` section for a PR body, from the runs a session
58
+ * recorded — newest first, with their timestamps, so a run from before the
59
+ * last edit is dated rather than presented as current. Returns `null` when
60
+ * nothing ran: a missing section is the honest shape for missing evidence.
61
+ *
62
+ * `from` names where the runs were read from when it is NOT the live session
63
+ * — `cruxy pr` runs outside any session and reads the project's latest log —
64
+ * so the header never says "this session" about a session that has ended.
65
+ */
66
+ export function verificationMarkdown(runs, opts = {}) {
67
+ if (runs.length === 0)
68
+ return null;
69
+ const shown = [...runs].reverse().slice(0, opts.limit ?? MARKDOWN_LIMIT);
70
+ const items = shown.map((rec) => {
71
+ const exit = rec.exitCode === null ? "no exit code" : `exit ${rec.exitCode}`;
72
+ const counts = countClause(rec);
73
+ return (`- \`${rec.command}\` — ${exit}${counts ? ` (${counts})` : ""}, ` +
74
+ `${formatDuration(rec.durationMs)}, via ${rec.tool} at ${rec.at}`);
75
+ });
76
+ const omitted = runs.length - shown.length;
77
+ return [
78
+ `Runs recorded by cruxy ${opts.from ?? "this session"}, newest first (exit codes as observed; nothing inferred):`,
79
+ "",
80
+ ...items,
81
+ ...(omitted > 0
82
+ ? ["", `…and ${omitted} earlier run${omitted === 1 ? "" : "s"}.`]
83
+ : []),
84
+ ].join("\n");
85
+ }
86
+ /** Most runs listed in a PR body. */
87
+ export const MARKDOWN_LIMIT = 8;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cruxy/cli",
3
- "version": "1.11.1",
3
+ "version": "1.11.3",
4
4
  "description": "an agentic coding CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -32,8 +32,9 @@
32
32
  "commander": "^12.1.0",
33
33
  "fastembed": "^2.1.0",
34
34
  "picocolors": "^1.1.1",
35
+ "tar": "^7.5.22",
35
36
  "tinyglobby": "^0.2.10",
36
- "undici": "^6.21.0",
37
+ "undici": "^6.28.1",
37
38
  "zod": "^3.23.8",
38
39
  "zod-to-json-schema": "^3.23.5",
39
40
  "@cruxy/sdk": "0.8.0"