agent-nuvira 3.1.3 → 3.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 (164) hide show
  1. package/dist/agents/agents/reasoner.d.ts +8 -0
  2. package/dist/agents/agents/reasoner.d.ts.map +1 -1
  3. package/dist/agents/agents/reasoner.js +53 -2
  4. package/dist/agents/agents/reasoner.js.map +1 -1
  5. package/dist/agents/agents/writer.d.ts +24 -0
  6. package/dist/agents/agents/writer.d.ts.map +1 -1
  7. package/dist/agents/agents/writer.js +200 -0
  8. package/dist/agents/agents/writer.js.map +1 -1
  9. package/dist/agents/composite-plan.d.ts +143 -0
  10. package/dist/agents/composite-plan.d.ts.map +1 -0
  11. package/dist/agents/composite-plan.js +399 -0
  12. package/dist/agents/composite-plan.js.map +1 -0
  13. package/dist/agents/long-form-plan.d.ts +156 -0
  14. package/dist/agents/long-form-plan.d.ts.map +1 -0
  15. package/dist/agents/long-form-plan.js +274 -0
  16. package/dist/agents/long-form-plan.js.map +1 -0
  17. package/dist/agents/orchestrator.d.ts +107 -0
  18. package/dist/agents/orchestrator.d.ts.map +1 -1
  19. package/dist/agents/orchestrator.js +501 -35
  20. package/dist/agents/orchestrator.js.map +1 -1
  21. package/dist/agents/prompt-assembly.d.ts +8 -0
  22. package/dist/agents/prompt-assembly.d.ts.map +1 -1
  23. package/dist/agents/prompt-assembly.js +17 -0
  24. package/dist/agents/prompt-assembly.js.map +1 -1
  25. package/dist/cli/chat.d.ts +33 -0
  26. package/dist/cli/chat.d.ts.map +1 -1
  27. package/dist/cli/chat.js +161 -7
  28. package/dist/cli/chat.js.map +1 -1
  29. package/dist/cli/execute.d.ts +12 -0
  30. package/dist/cli/execute.d.ts.map +1 -1
  31. package/dist/cli/execute.js +150 -2
  32. package/dist/cli/execute.js.map +1 -1
  33. package/dist/cli/loop-executor.d.ts +17 -0
  34. package/dist/cli/loop-executor.d.ts.map +1 -1
  35. package/dist/cli/loop-executor.js +160 -1
  36. package/dist/cli/loop-executor.js.map +1 -1
  37. package/dist/cli/models.d.ts.map +1 -1
  38. package/dist/cli/models.js +10 -0
  39. package/dist/cli/models.js.map +1 -1
  40. package/dist/cli/trace.d.ts +19 -0
  41. package/dist/cli/trace.d.ts.map +1 -1
  42. package/dist/cli/trace.js +109 -2
  43. package/dist/cli/trace.js.map +1 -1
  44. package/dist/gateway/registry.d.ts +31 -0
  45. package/dist/gateway/registry.d.ts.map +1 -1
  46. package/dist/gateway/registry.js +162 -13
  47. package/dist/gateway/registry.js.map +1 -1
  48. package/dist/inference/model-entitlement.d.ts +46 -0
  49. package/dist/inference/model-entitlement.d.ts.map +1 -0
  50. package/dist/inference/model-entitlement.js +98 -0
  51. package/dist/inference/model-entitlement.js.map +1 -0
  52. package/dist/inference/tool-call-utils.d.ts +10 -0
  53. package/dist/inference/tool-call-utils.d.ts.map +1 -1
  54. package/dist/inference/tool-call-utils.js +90 -0
  55. package/dist/inference/tool-call-utils.js.map +1 -1
  56. package/dist/learning/autonomy-policy.d.ts +370 -0
  57. package/dist/learning/autonomy-policy.d.ts.map +1 -0
  58. package/dist/learning/autonomy-policy.js +544 -0
  59. package/dist/learning/autonomy-policy.js.map +1 -0
  60. package/dist/learning/cost-tracker.d.ts +14 -0
  61. package/dist/learning/cost-tracker.d.ts.map +1 -1
  62. package/dist/learning/cost-tracker.js +22 -0
  63. package/dist/learning/cost-tracker.js.map +1 -1
  64. package/dist/learning/credential-fingerprint.d.ts +58 -0
  65. package/dist/learning/credential-fingerprint.d.ts.map +1 -0
  66. package/dist/learning/credential-fingerprint.js +126 -0
  67. package/dist/learning/credential-fingerprint.js.map +1 -0
  68. package/dist/learning/deliverable-class.d.ts +178 -0
  69. package/dist/learning/deliverable-class.d.ts.map +1 -0
  70. package/dist/learning/deliverable-class.js +504 -0
  71. package/dist/learning/deliverable-class.js.map +1 -0
  72. package/dist/learning/engine-router.d.ts +12 -1
  73. package/dist/learning/engine-router.d.ts.map +1 -1
  74. package/dist/learning/engine-router.js +28 -0
  75. package/dist/learning/engine-router.js.map +1 -1
  76. package/dist/learning/long-form.d.ts +252 -0
  77. package/dist/learning/long-form.d.ts.map +1 -0
  78. package/dist/learning/long-form.js +521 -0
  79. package/dist/learning/long-form.js.map +1 -0
  80. package/dist/learning/model-first-router.d.ts +17 -0
  81. package/dist/learning/model-first-router.d.ts.map +1 -1
  82. package/dist/learning/model-first-router.js +27 -0
  83. package/dist/learning/model-first-router.js.map +1 -1
  84. package/dist/learning/model-registry.d.ts +66 -4
  85. package/dist/learning/model-registry.d.ts.map +1 -1
  86. package/dist/learning/model-registry.js +67 -6
  87. package/dist/learning/model-registry.js.map +1 -1
  88. package/dist/learning/model-warmup.d.ts +97 -2
  89. package/dist/learning/model-warmup.d.ts.map +1 -1
  90. package/dist/learning/model-warmup.js +165 -60
  91. package/dist/learning/model-warmup.js.map +1 -1
  92. package/dist/learning/prompt-layers.d.ts +61 -0
  93. package/dist/learning/prompt-layers.d.ts.map +1 -0
  94. package/dist/learning/prompt-layers.js +140 -0
  95. package/dist/learning/prompt-layers.js.map +1 -0
  96. package/dist/learning/provider-limits.d.ts +66 -0
  97. package/dist/learning/provider-limits.d.ts.map +1 -0
  98. package/dist/learning/provider-limits.js +184 -0
  99. package/dist/learning/provider-limits.js.map +1 -0
  100. package/dist/learning/reasoning-trace.d.ts +125 -1
  101. package/dist/learning/reasoning-trace.d.ts.map +1 -1
  102. package/dist/learning/reasoning-trace.js +85 -2
  103. package/dist/learning/reasoning-trace.js.map +1 -1
  104. package/dist/learning/resilient-call.d.ts +36 -1
  105. package/dist/learning/resilient-call.d.ts.map +1 -1
  106. package/dist/learning/resilient-call.js +80 -5
  107. package/dist/learning/resilient-call.js.map +1 -1
  108. package/dist/learning/unattended-job.d.ts +350 -0
  109. package/dist/learning/unattended-job.d.ts.map +1 -0
  110. package/dist/learning/unattended-job.js +636 -0
  111. package/dist/learning/unattended-job.js.map +1 -0
  112. package/dist/learning/unattended-progress.d.ts +95 -0
  113. package/dist/learning/unattended-progress.d.ts.map +1 -0
  114. package/dist/learning/unattended-progress.js +147 -0
  115. package/dist/learning/unattended-progress.js.map +1 -0
  116. package/dist/learning/working-state.d.ts +109 -0
  117. package/dist/learning/working-state.d.ts.map +1 -0
  118. package/dist/learning/working-state.js +244 -0
  119. package/dist/learning/working-state.js.map +1 -0
  120. package/dist/nlu/conversation-gate.d.ts +33 -0
  121. package/dist/nlu/conversation-gate.d.ts.map +1 -1
  122. package/dist/nlu/conversation-gate.js +68 -3
  123. package/dist/nlu/conversation-gate.js.map +1 -1
  124. package/dist/tools/coding-tools.d.ts.map +1 -1
  125. package/dist/tools/coding-tools.js +95 -19
  126. package/dist/tools/coding-tools.js.map +1 -1
  127. package/dist/tools/edit-verification.d.ts +142 -0
  128. package/dist/tools/edit-verification.d.ts.map +1 -0
  129. package/dist/tools/edit-verification.js +262 -0
  130. package/dist/tools/edit-verification.js.map +1 -0
  131. package/dist/tools/git-tool.d.ts.map +1 -1
  132. package/dist/tools/git-tool.js +37 -4
  133. package/dist/tools/git-tool.js.map +1 -1
  134. package/dist/tools/registry.d.ts +30 -2
  135. package/dist/tools/registry.d.ts.map +1 -1
  136. package/dist/tools/registry.js +40 -11
  137. package/dist/tools/registry.js.map +1 -1
  138. package/dist/tools/run-cli.d.ts.map +1 -1
  139. package/dist/tools/run-cli.js +40 -13
  140. package/dist/tools/run-cli.js.map +1 -1
  141. package/dist/tools/run-terminal.d.ts +6 -1
  142. package/dist/tools/run-terminal.d.ts.map +1 -1
  143. package/dist/tools/run-terminal.js +158 -18
  144. package/dist/tools/run-terminal.js.map +1 -1
  145. package/dist/tools/tool-loop.d.ts +109 -0
  146. package/dist/tools/tool-loop.d.ts.map +1 -1
  147. package/dist/tools/tool-loop.js +362 -2
  148. package/dist/tools/tool-loop.js.map +1 -1
  149. package/dist/web-dashboard/chat-console.d.ts +8 -0
  150. package/dist/web-dashboard/chat-console.d.ts.map +1 -1
  151. package/dist/web-dashboard/chat-console.js +9 -0
  152. package/dist/web-dashboard/chat-console.js.map +1 -1
  153. package/dist/web-dashboard/chat-retry.d.ts.map +1 -1
  154. package/dist/web-dashboard/chat-retry.js +10 -2
  155. package/dist/web-dashboard/chat-retry.js.map +1 -1
  156. package/dist/web-dashboard/server.d.ts.map +1 -1
  157. package/dist/web-dashboard/server.js +80 -8
  158. package/dist/web-dashboard/server.js.map +1 -1
  159. package/dist/web-dashboard/src/types.d.ts +81 -4
  160. package/dist/web-dashboard/src/types.d.ts.map +1 -1
  161. package/package.json +1 -1
  162. package/src/web-dashboard/public/assets/{index-Co7Hk2FT.js → index-kCUkORm7.js} +2 -2
  163. package/src/web-dashboard/public/assets/{index-Co7Hk2FT.js.map → index-kCUkORm7.js.map} +1 -1
  164. package/src/web-dashboard/public/index.html +1 -1
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Measured progress for an unattended job (enterprise-grade hardening, G11).
3
+ *
4
+ * WHY THIS IS ITS OWN MODULE. The runner's central guarantee is that progress
5
+ * is MEASURED, not claimed: a batch that reports success but did not move the
6
+ * deliverable is a stall, and three stalls stop the run and ask. That rule is
7
+ * only as good as the measurement, so the measurement lives in one place,
8
+ * reading artifacts off disk — and every surface (CLI, dashboard, gateway)
9
+ * measures the same way instead of each inventing its own idea of "done".
10
+ *
11
+ * The two inputs:
12
+ * 1. the long-form ledger — how much of the CONTENT exists (words, units);
13
+ * 2. the job's `expectedArtifacts` — the files the deliverable promises
14
+ * (site, chapter index, optional tools). For a composite ask this is what
15
+ * stops "the prose phase finished" being reported as "the deliverable is
16
+ * done" while the site is still missing.
17
+ */
18
+ import { type BatchOutcome, type UnattendedJob, type UnattendedSurface } from './unattended-job.js';
19
+ /**
20
+ * Weight of the content phase in a composite deliverable's percentage.
21
+ *
22
+ * The content IS the deliverable, so it dominates; the surrounding artifacts
23
+ * are the remaining third. Weighting them any lower would let a beautiful
24
+ * empty shell sit at 99% after one chapter.
25
+ */
26
+ export declare const CONTENT_WEIGHT = 0.7;
27
+ /**
28
+ * How many expected artifacts exist on disk (relative paths resolved against
29
+ * the project root).
30
+ *
31
+ * Split out from the job-shaped wrapper because the orchestrator asks the same
32
+ * question at planning time — "has this deliverable already been produced?" —
33
+ * before any job record exists.
34
+ */
35
+ export declare function artifactsPresence(projectPath: string, expected: string[] | undefined): {
36
+ present: number;
37
+ total: number;
38
+ missing: string[];
39
+ };
40
+ /** How many of a job's expected artifacts exist on disk. */
41
+ export declare function countPresentArtifacts(job: UnattendedJob): {
42
+ present: number;
43
+ total: number;
44
+ missing: string[];
45
+ };
46
+ /**
47
+ * Measure the job from disk.
48
+ *
49
+ * Never throws: a measurement failure must degrade to "no progress recorded",
50
+ * which the runner correctly treats as a stall, rather than crashing the drain
51
+ * that is holding the user's promised work.
52
+ */
53
+ export declare function measureUnattendedProgress(job: UnattendedJob): BatchOutcome;
54
+ /**
55
+ * Is the deliverable complete right now?
56
+ *
57
+ * Used by surfaces to decide whether to keep scheduling a job at all — a
58
+ * resumed "continue" turn that finds the work already done must not start a
59
+ * second book (the ledger's oldest failure mode).
60
+ */
61
+ export declare function isDeliverableComplete(job: UnattendedJob): boolean;
62
+ /**
63
+ * The slice of an orchestrator result a surface needs to schedule the rest of
64
+ * the work.
65
+ *
66
+ * Declared STRUCTURALLY (not imported from the orchestrator) because the
67
+ * gateway, the CLI and the dashboard all consume it, and a shared consumer must
68
+ * not drag the whole agent graph into its import closure.
69
+ */
70
+ export interface PendingWorkLike {
71
+ kind: 'long-form' | 'phased';
72
+ goal: string;
73
+ projectPath: string;
74
+ continuationPrompt: string;
75
+ expectedArtifacts?: string[];
76
+ progressLine: string;
77
+ percent: number;
78
+ reason: string;
79
+ }
80
+ /**
81
+ * Schedule the continuation of a run that ended with unfinished work — the
82
+ * replacement for asking the user to type "continue".
83
+ *
84
+ * Returns the scheduled job, or `null` when there is nothing left to do. That
85
+ * second case matters as much as the first: a run that finished its deliverable
86
+ * must not enqueue a continuation that would immediately re-run and rebuild it.
87
+ *
88
+ * @param pending the orchestrator's `result.pendingWork` (may be undefined)
89
+ * @param surface who to report to and which drain owns the work
90
+ */
91
+ export declare function scheduleFromPendingWork(pending: PendingWorkLike | undefined, surface: UnattendedSurface, options?: {
92
+ deadlineMs?: number;
93
+ notify?: boolean;
94
+ }): UnattendedJob | null;
95
+ //# sourceMappingURL=unattended-progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unattended-progress.d.ts","sourceRoot":"","sources":["../../src/learning/unattended-progress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,EAAsB,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExH;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAS,GAC7B;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAWvD;AAED,4DAA4D;AAC5D,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,aAAa,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAE/G;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,aAAa,GAAG,YAAY,CA+C1E;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAGjE;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,WAAW,GAAG,QAAQ,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,eAAe,GAAG,SAAS,EACpC,OAAO,EAAE,iBAAiB,EAC1B,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACtD,aAAa,GAAG,IAAI,CAiBtB"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Measured progress for an unattended job (enterprise-grade hardening, G11).
3
+ *
4
+ * WHY THIS IS ITS OWN MODULE. The runner's central guarantee is that progress
5
+ * is MEASURED, not claimed: a batch that reports success but did not move the
6
+ * deliverable is a stall, and three stalls stop the run and ask. That rule is
7
+ * only as good as the measurement, so the measurement lives in one place,
8
+ * reading artifacts off disk — and every surface (CLI, dashboard, gateway)
9
+ * measures the same way instead of each inventing its own idea of "done".
10
+ *
11
+ * The two inputs:
12
+ * 1. the long-form ledger — how much of the CONTENT exists (words, units);
13
+ * 2. the job's `expectedArtifacts` — the files the deliverable promises
14
+ * (site, chapter index, optional tools). For a composite ask this is what
15
+ * stops "the prose phase finished" being reported as "the deliverable is
16
+ * done" while the site is still missing.
17
+ */
18
+ import { existsSync } from 'node:fs';
19
+ import { isAbsolute, resolve } from 'node:path';
20
+ import { findLatestJob, formatProgress, jobProgress } from './long-form.js';
21
+ import { startUnattendedJob } from './unattended-job.js';
22
+ /**
23
+ * Weight of the content phase in a composite deliverable's percentage.
24
+ *
25
+ * The content IS the deliverable, so it dominates; the surrounding artifacts
26
+ * are the remaining third. Weighting them any lower would let a beautiful
27
+ * empty shell sit at 99% after one chapter.
28
+ */
29
+ export const CONTENT_WEIGHT = 0.7;
30
+ /**
31
+ * How many expected artifacts exist on disk (relative paths resolved against
32
+ * the project root).
33
+ *
34
+ * Split out from the job-shaped wrapper because the orchestrator asks the same
35
+ * question at planning time — "has this deliverable already been produced?" —
36
+ * before any job record exists.
37
+ */
38
+ export function artifactsPresence(projectPath, expected) {
39
+ const paths = expected ?? [];
40
+ if (paths.length === 0)
41
+ return { present: 0, total: 0, missing: [] };
42
+ const missing = [];
43
+ let present = 0;
44
+ for (const rel of paths) {
45
+ const abs = isAbsolute(rel) ? rel : resolve(projectPath, rel);
46
+ if (existsSync(abs))
47
+ present++;
48
+ else
49
+ missing.push(rel);
50
+ }
51
+ return { present, total: paths.length, missing };
52
+ }
53
+ /** How many of a job's expected artifacts exist on disk. */
54
+ export function countPresentArtifacts(job) {
55
+ return artifactsPresence(job.projectPath, job.expectedArtifacts);
56
+ }
57
+ /**
58
+ * Measure the job from disk.
59
+ *
60
+ * Never throws: a measurement failure must degrade to "no progress recorded",
61
+ * which the runner correctly treats as a stall, rather than crashing the drain
62
+ * that is holding the user's promised work.
63
+ */
64
+ export function measureUnattendedProgress(job) {
65
+ try {
66
+ const ledger = findLatestJob(job.projectPath);
67
+ const artifacts = countPresentArtifacts(job);
68
+ if (!ledger) {
69
+ // No content ledger for this project: either the job is a phased build
70
+ // with no prose, or the first batch has not recorded anything yet. The
71
+ // artifacts are then the only honest signal.
72
+ if (artifacts.total > 0) {
73
+ const pct = Math.round((artifacts.present / artifacts.total) * 100);
74
+ return {
75
+ progress: pct,
76
+ progressLine: `${artifacts.present}/${artifacts.total} deliverable files present`,
77
+ finished: artifacts.present === artifacts.total,
78
+ };
79
+ }
80
+ return { progress: 0, progressLine: 'no progress recorded yet' };
81
+ }
82
+ const contentProgress = jobProgress(ledger);
83
+ const contentPercent = contentProgress.percent;
84
+ if (artifacts.total === 0) {
85
+ return {
86
+ progress: contentPercent,
87
+ progressLine: formatProgress(ledger),
88
+ finished: contentProgress.complete,
89
+ };
90
+ }
91
+ const artifactPercent = Math.round((artifacts.present / artifacts.total) * 100);
92
+ const combined = Math.round(contentPercent * CONTENT_WEIGHT + artifactPercent * (1 - CONTENT_WEIGHT));
93
+ const finished = contentProgress.complete && artifacts.present === artifacts.total;
94
+ return {
95
+ progress: finished ? 100 : combined,
96
+ progressLine: `${formatProgress(ledger)} · ${artifacts.present}/${artifacts.total} deliverable files` +
97
+ (artifacts.missing.length > 0 && artifacts.missing.length <= 3
98
+ ? ` (missing ${artifacts.missing.join(', ')})`
99
+ : ''),
100
+ finished,
101
+ };
102
+ }
103
+ catch {
104
+ return { progress: 0, progressLine: 'progress measurement unavailable' };
105
+ }
106
+ }
107
+ /**
108
+ * Is the deliverable complete right now?
109
+ *
110
+ * Used by surfaces to decide whether to keep scheduling a job at all — a
111
+ * resumed "continue" turn that finds the work already done must not start a
112
+ * second book (the ledger's oldest failure mode).
113
+ */
114
+ export function isDeliverableComplete(job) {
115
+ const measured = measureUnattendedProgress(job);
116
+ return measured.finished === true;
117
+ }
118
+ /**
119
+ * Schedule the continuation of a run that ended with unfinished work — the
120
+ * replacement for asking the user to type "continue".
121
+ *
122
+ * Returns the scheduled job, or `null` when there is nothing left to do. That
123
+ * second case matters as much as the first: a run that finished its deliverable
124
+ * must not enqueue a continuation that would immediately re-run and rebuild it.
125
+ *
126
+ * @param pending the orchestrator's `result.pendingWork` (may be undefined)
127
+ * @param surface who to report to and which drain owns the work
128
+ */
129
+ export function scheduleFromPendingWork(pending, surface, options = {}) {
130
+ if (!pending)
131
+ return null;
132
+ const presence = artifactsPresence(pending.projectPath, pending.expectedArtifacts);
133
+ const filesComplete = presence.total === 0 || presence.present === presence.total;
134
+ if (pending.percent >= 100 && filesComplete)
135
+ return null;
136
+ return startUnattendedJob({
137
+ kind: pending.kind,
138
+ goal: pending.goal,
139
+ projectPath: pending.projectPath,
140
+ surface,
141
+ continuationPrompt: pending.continuationPrompt,
142
+ ...(pending.expectedArtifacts ? { expectedArtifacts: pending.expectedArtifacts } : {}),
143
+ ...(options.deadlineMs !== undefined ? { deadlineMs: options.deadlineMs } : {}),
144
+ ...(options.notify !== undefined ? { notify: options.notify } : {}),
145
+ }).job;
146
+ }
147
+ //# sourceMappingURL=unattended-progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unattended-progress.js","sourceRoot":"","sources":["../../src/learning/unattended-progress.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Working state — the per-project ledger that gives the agent a memory of
3
+ * what it changed, whether the change was verified, and what the user has
4
+ * already reported broken (enterprise-grade hardening, G3 + G4).
5
+ *
6
+ * WHY THIS EXISTS (the trace audit):
7
+ * The calculator session ran 15 turns over 77 minutes. Each turn RE-DERIVED
8
+ * the same root cause from scratch (input tokens grew 2,172 → 7,317), the
9
+ * model flip-flopped on the diagnosis (found the `id`-mapping bug in turn 23,
10
+ * declared the CSS "perfectly valid" in turn 25), and its own fixes kept
11
+ * undoing earlier ones (turn 17 made the converter vanish; turn 21 broke the
12
+ * dropdowns). Nothing carried the STATE of the work across turns — only the
13
+ * raw transcript, which is the worst possible carrier.
14
+ *
15
+ * This ledger is deliberately DETERMINISTIC and LLM-free: it records facts
16
+ * (files touched, verified-or-not, user-reported regressions) and formats a
17
+ * compact block that is injected at the start of the next turn. No summarizer,
18
+ * no latency, no drift — the same philosophy as `trimThreadBudget`.
19
+ *
20
+ * Storage: `~/.nuvira/memory/working-state.json`, keyed by project path.
21
+ * Honours `NUVIRA_MEMORY_DIR` / `BUFF_MEMORY_DIR` like the reasoning traces.
22
+ * Every write is best-effort — a ledger write must NEVER break a turn.
23
+ */
24
+ /** One project's working state — everything worth remembering between turns. */
25
+ export interface ProjectWorkingState {
26
+ /** Absolute project path (the ledger key). */
27
+ projectPath: string;
28
+ /** Files the agent changed, most-recent last (deduped, capped). */
29
+ filesTouched: string[];
30
+ /** Distinct tools used across the session (for a quick capability read). */
31
+ toolsUsed: string[];
32
+ /** Turns recorded against this project. */
33
+ turns: number;
34
+ /**
35
+ * Consecutive unverified edit turns still outstanding. Reset to 0 the
36
+ * moment a turn verifies, because a verified state supersedes the backlog.
37
+ */
38
+ unverifiedEdits: number;
39
+ /** Epoch ms of the last turn that verified (ran tests/typecheck/browser). */
40
+ lastVerifiedAt?: number;
41
+ /**
42
+ * What the USER reported broken, newest last (deduped, capped). This is the
43
+ * regression memory: the exact thing the agent must not re-break or
44
+ * re-derive next turn.
45
+ */
46
+ openIssues: string[];
47
+ /** How many turns carried a regression signal ("still", "same issue"...). */
48
+ corrections: number;
49
+ /** Epoch ms of the last write. */
50
+ updatedAt: number;
51
+ }
52
+ /** A single finished turn, as recorded by the caller. */
53
+ export interface TurnRecord {
54
+ /** Files edited this turn (any order; deduped + capped on write). */
55
+ filesTouched?: string[];
56
+ /** Tools that ran successfully this turn. */
57
+ toolsUsed?: readonly string[];
58
+ /** A verification tool ran successfully this turn. */
59
+ verified?: boolean;
60
+ /** The turn mutated the workspace and verified nothing. */
61
+ unverifiedEdit?: boolean;
62
+ /** The user's message for this turn (scanned for a regression signal). */
63
+ userMessage?: string;
64
+ }
65
+ /** Cap on remembered files per project (oldest drop first). */
66
+ export declare const MAX_FILES = 40;
67
+ /** Cap on remembered user-reported issues per project. */
68
+ export declare const MAX_ISSUES = 8;
69
+ /** Cap on remembered tools per project. */
70
+ export declare const MAX_TOOLS = 24;
71
+ /** Normalize a project path so the same project always maps to one entry. */
72
+ export declare function normalizeProjectPath(projectPath: string): string;
73
+ /**
74
+ * Does the user's message report that something is STILL broken?
75
+ *
76
+ * This is the correction signal the audit was built on: the user said
77
+ * "still same issue", "i don't see any change", "converter is not having any
78
+ * conversion logic" six turns in a row. Detecting it lets the ledger keep the
79
+ * issue in front of the agent instead of letting it re-diagnose from zero.
80
+ *
81
+ * Deliberately conservative: a bare question ("does this work?") is not a
82
+ * regression, and neither is a fresh feature request.
83
+ */
84
+ export declare function detectRegressionSignal(userMessage: string): boolean;
85
+ /** Read one project's state (null when nothing has been recorded). */
86
+ export declare function getWorkingState(projectPath: string): ProjectWorkingState | null;
87
+ /**
88
+ * Record a finished turn and return the updated state. Best-effort: on any
89
+ * failure the caller still gets a usable (possibly unchanged) state.
90
+ *
91
+ * The rules encode the audit's lessons:
92
+ * - Touched files accumulate and are capped oldest-first.
93
+ * - A VERIFIED turn clears the unverified backlog AND the open issues (the
94
+ * fix is proven, so the previous report is answered).
95
+ * - An UNVERIFIED edit turn increments the backlog — the debt the agent owes.
96
+ * - A regression signal keeps the user's own words as an open issue.
97
+ */
98
+ export declare function recordWorkingState(projectPath: string, turn: TurnRecord): ProjectWorkingState;
99
+ /** Forget one project (or the whole ledger when no path is given). */
100
+ export declare function clearWorkingState(projectPath?: string): void;
101
+ /**
102
+ * Format the state as a compact, model-readable block ('' when there is
103
+ * nothing worth saying — a pristine project must not add noise to the prompt).
104
+ *
105
+ * Kept short on purpose: this rides in EVERY turn, so a verbose block would
106
+ * recreate the very drift it exists to prevent.
107
+ */
108
+ export declare function formatWorkingState(state: ProjectWorkingState | null, now?: number): string;
109
+ //# sourceMappingURL=working-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"working-state.d.ts","sourceRoot":"","sources":["../../src/learning/working-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAQH,gFAAgF;AAChF,MAAM,WAAW,mBAAmB;IAClC,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,4EAA4E;IAC5E,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,yDAAyD;AACzD,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,sDAAsD;IACtD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2DAA2D;IAC3D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAUD,+DAA+D;AAC/D,eAAO,MAAM,SAAS,KAAK,CAAC;AAC5B,0DAA0D;AAC1D,eAAO,MAAM,UAAU,IAAI,CAAC;AAC5B,2CAA2C;AAC3C,eAAO,MAAM,SAAS,KAAK,CAAC;AAkC5B,6EAA6E;AAC7E,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAMhE;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAkBnE;AAID,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAG/E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,mBAAmB,CAoE7F;AAED,sEAAsE;AACtE,wBAAgB,iBAAiB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAQ5D;AAaD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,EAAE,GAAG,GAAE,MAAmB,GAAG,MAAM,CAyBtG"}
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Working state — the per-project ledger that gives the agent a memory of
3
+ * what it changed, whether the change was verified, and what the user has
4
+ * already reported broken (enterprise-grade hardening, G3 + G4).
5
+ *
6
+ * WHY THIS EXISTS (the trace audit):
7
+ * The calculator session ran 15 turns over 77 minutes. Each turn RE-DERIVED
8
+ * the same root cause from scratch (input tokens grew 2,172 → 7,317), the
9
+ * model flip-flopped on the diagnosis (found the `id`-mapping bug in turn 23,
10
+ * declared the CSS "perfectly valid" in turn 25), and its own fixes kept
11
+ * undoing earlier ones (turn 17 made the converter vanish; turn 21 broke the
12
+ * dropdowns). Nothing carried the STATE of the work across turns — only the
13
+ * raw transcript, which is the worst possible carrier.
14
+ *
15
+ * This ledger is deliberately DETERMINISTIC and LLM-free: it records facts
16
+ * (files touched, verified-or-not, user-reported regressions) and formats a
17
+ * compact block that is injected at the start of the next turn. No summarizer,
18
+ * no latency, no drift — the same philosophy as `trimThreadBudget`.
19
+ *
20
+ * Storage: `~/.nuvira/memory/working-state.json`, keyed by project path.
21
+ * Honours `NUVIRA_MEMORY_DIR` / `BUFF_MEMORY_DIR` like the reasoning traces.
22
+ * Every write is best-effort — a ledger write must NEVER break a turn.
23
+ */
24
+ import { envBuff, resolveNuviraHome } from '../config/paths.js';
25
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
26
+ import { join, resolve } from 'node:path';
27
+ // ─── Constants ──────────────────────────────────────────────────────────────
28
+ const CURRENT_VERSION = 1;
29
+ /** Cap on remembered files per project (oldest drop first). */
30
+ export const MAX_FILES = 40;
31
+ /** Cap on remembered user-reported issues per project. */
32
+ export const MAX_ISSUES = 8;
33
+ /** Cap on remembered tools per project. */
34
+ export const MAX_TOOLS = 24;
35
+ // ─── Storage ────────────────────────────────────────────────────────────────
36
+ function memoryDir() {
37
+ return envBuff('MEMORY_DIR') || join(resolveNuviraHome(), 'memory');
38
+ }
39
+ function statePath() {
40
+ return join(memoryDir(), 'working-state.json');
41
+ }
42
+ function readFileSafe() {
43
+ try {
44
+ if (!existsSync(statePath()))
45
+ return { version: CURRENT_VERSION, projects: {} };
46
+ const data = JSON.parse(readFileSync(statePath(), 'utf-8'));
47
+ if (!data || typeof data !== 'object' || !data.projects || typeof data.projects !== 'object') {
48
+ return { version: CURRENT_VERSION, projects: {} };
49
+ }
50
+ return data;
51
+ }
52
+ catch {
53
+ return { version: CURRENT_VERSION, projects: {} };
54
+ }
55
+ }
56
+ function writeFileSafe(data) {
57
+ try {
58
+ if (!existsSync(memoryDir()))
59
+ mkdirSync(memoryDir(), { recursive: true });
60
+ writeFileSync(statePath(), JSON.stringify(data, null, 2), 'utf-8');
61
+ }
62
+ catch {
63
+ // Best-effort — the ledger must never break a turn.
64
+ }
65
+ }
66
+ /** Normalize a project path so the same project always maps to one entry. */
67
+ export function normalizeProjectPath(projectPath) {
68
+ try {
69
+ return resolve(projectPath);
70
+ }
71
+ catch {
72
+ return projectPath;
73
+ }
74
+ }
75
+ // ─── Regression signals ─────────────────────────────────────────────────────
76
+ /**
77
+ * Does the user's message report that something is STILL broken?
78
+ *
79
+ * This is the correction signal the audit was built on: the user said
80
+ * "still same issue", "i don't see any change", "converter is not having any
81
+ * conversion logic" six turns in a row. Detecting it lets the ledger keep the
82
+ * issue in front of the agent instead of letting it re-diagnose from zero.
83
+ *
84
+ * Deliberately conservative: a bare question ("does this work?") is not a
85
+ * regression, and neither is a fresh feature request.
86
+ */
87
+ export function detectRegressionSignal(userMessage) {
88
+ const text = (userMessage || '').trim();
89
+ if (!text)
90
+ return false;
91
+ if (text.length > 600)
92
+ return false; // a long brief is a new task, not a correction
93
+ const patterns = [
94
+ /\bstill\b/i,
95
+ /\bsame (?:issue|problem|bug|thing|error|behaviou?r)\b/i,
96
+ /\bnot (?:working|fixed|visible|showing|appearing|there)\b/i,
97
+ /\bdoesn'?t work\b/i,
98
+ /\bdidn'?t work\b/i,
99
+ /\bno (?:change|changes|luck|effect)\b/i,
100
+ /\bi (?:still )?(?:can'?t|cannot|don'?t) (?:see|find)\b/i,
101
+ /\byou (?:broke|broke?n)\b/i,
102
+ /\bregress(?:ion|ed)?\b/i,
103
+ /\bit'?s (?:blank|empty|gone|missing)\b/i,
104
+ /\bagain\b/i,
105
+ ];
106
+ return patterns.some((re) => re.test(text));
107
+ }
108
+ // ─── API ────────────────────────────────────────────────────────────────────
109
+ /** Read one project's state (null when nothing has been recorded). */
110
+ export function getWorkingState(projectPath) {
111
+ const data = readFileSafe();
112
+ return data.projects[normalizeProjectPath(projectPath)] ?? null;
113
+ }
114
+ /**
115
+ * Record a finished turn and return the updated state. Best-effort: on any
116
+ * failure the caller still gets a usable (possibly unchanged) state.
117
+ *
118
+ * The rules encode the audit's lessons:
119
+ * - Touched files accumulate and are capped oldest-first.
120
+ * - A VERIFIED turn clears the unverified backlog AND the open issues (the
121
+ * fix is proven, so the previous report is answered).
122
+ * - An UNVERIFIED edit turn increments the backlog — the debt the agent owes.
123
+ * - A regression signal keeps the user's own words as an open issue.
124
+ */
125
+ export function recordWorkingState(projectPath, turn) {
126
+ const key = normalizeProjectPath(projectPath);
127
+ const data = readFileSafe();
128
+ const now = Date.now();
129
+ const prev = data.projects[key] ??
130
+ {
131
+ projectPath: key,
132
+ filesTouched: [],
133
+ toolsUsed: [],
134
+ turns: 0,
135
+ unverifiedEdits: 0,
136
+ openIssues: [],
137
+ corrections: 0,
138
+ updatedAt: now,
139
+ };
140
+ const next = { ...prev, filesTouched: [...prev.filesTouched], toolsUsed: [...prev.toolsUsed], openIssues: [...prev.openIssues] };
141
+ next.turns = prev.turns + 1;
142
+ next.updatedAt = now;
143
+ // Files — dedupe (move-to-end so recency is meaningful) then cap.
144
+ for (const f of turn.filesTouched ?? []) {
145
+ if (!f)
146
+ continue;
147
+ const idx = next.filesTouched.indexOf(f);
148
+ if (idx !== -1)
149
+ next.filesTouched.splice(idx, 1);
150
+ next.filesTouched.push(f);
151
+ }
152
+ if (next.filesTouched.length > MAX_FILES) {
153
+ next.filesTouched = next.filesTouched.slice(-MAX_FILES);
154
+ }
155
+ // Tools — distinct, capped.
156
+ for (const t of turn.toolsUsed ?? []) {
157
+ if (t && !next.toolsUsed.includes(t))
158
+ next.toolsUsed.push(t);
159
+ }
160
+ if (next.toolsUsed.length > MAX_TOOLS) {
161
+ next.toolsUsed = next.toolsUsed.slice(-MAX_TOOLS);
162
+ }
163
+ // Verification debt.
164
+ if (turn.verified) {
165
+ next.unverifiedEdits = 0;
166
+ next.lastVerifiedAt = now;
167
+ // A proven fix answers the open reports.
168
+ next.openIssues = [];
169
+ }
170
+ else if (turn.unverifiedEdit) {
171
+ next.unverifiedEdits = prev.unverifiedEdits + 1;
172
+ }
173
+ // Regression memory — keep the user's own words.
174
+ const msg = (turn.userMessage || '').trim();
175
+ if (msg && detectRegressionSignal(msg)) {
176
+ next.corrections = prev.corrections + 1;
177
+ const short = msg.replace(/\s+/g, ' ').slice(0, 200);
178
+ if (!next.openIssues.includes(short))
179
+ next.openIssues.push(short);
180
+ if (next.openIssues.length > MAX_ISSUES)
181
+ next.openIssues = next.openIssues.slice(-MAX_ISSUES);
182
+ }
183
+ data.projects[key] = next;
184
+ // Bound the file: keep the most recently updated projects only.
185
+ const entries = Object.entries(data.projects);
186
+ if (entries.length > 50) {
187
+ entries.sort((a, b) => b[1].updatedAt - a[1].updatedAt);
188
+ data.projects = Object.fromEntries(entries.slice(0, 50));
189
+ }
190
+ writeFileSafe(data);
191
+ return next;
192
+ }
193
+ /** Forget one project (or the whole ledger when no path is given). */
194
+ export function clearWorkingState(projectPath) {
195
+ if (!projectPath) {
196
+ writeFileSafe({ version: CURRENT_VERSION, projects: {} });
197
+ return;
198
+ }
199
+ const data = readFileSafe();
200
+ delete data.projects[normalizeProjectPath(projectPath)];
201
+ writeFileSafe(data);
202
+ }
203
+ // ─── Formatting (the injected block) ────────────────────────────────────────
204
+ function relativeAge(ts, now) {
205
+ const mins = Math.max(0, Math.round((now - ts) / 60_000));
206
+ if (mins < 1)
207
+ return 'just now';
208
+ if (mins < 60)
209
+ return `${mins}m ago`;
210
+ const hours = Math.round(mins / 60);
211
+ if (hours < 24)
212
+ return `${hours}h ago`;
213
+ return `${Math.round(hours / 24)}d ago`;
214
+ }
215
+ /**
216
+ * Format the state as a compact, model-readable block ('' when there is
217
+ * nothing worth saying — a pristine project must not add noise to the prompt).
218
+ *
219
+ * Kept short on purpose: this rides in EVERY turn, so a verbose block would
220
+ * recreate the very drift it exists to prevent.
221
+ */
222
+ export function formatWorkingState(state, now = Date.now()) {
223
+ if (!state)
224
+ return '';
225
+ const lines = [];
226
+ if (state.filesTouched.length > 0) {
227
+ const files = state.filesTouched.slice(-8);
228
+ lines.push(`• Files changed this session (${state.filesTouched.length}): ${files.join(', ')}${state.filesTouched.length > files.length ? ', …' : ''}`);
229
+ }
230
+ if (state.unverifiedEdits > 0) {
231
+ lines.push(`• ⚠️ ${state.unverifiedEdits} edit turn(s) were NEVER verified — do not assume they work; re-check before building on them.`);
232
+ }
233
+ if (state.lastVerifiedAt !== undefined) {
234
+ lines.push(`• Last verified: ${relativeAge(state.lastVerifiedAt, now)} (a test/typecheck/browser run passed).`);
235
+ }
236
+ if (state.openIssues.length > 0) {
237
+ const latest = state.openIssues[state.openIssues.length - 1];
238
+ lines.push(`• User has reported ${state.corrections} regression(s). Most recent report: "${latest}" — fix THIS, do not re-diagnose from scratch.`);
239
+ }
240
+ if (lines.length === 0)
241
+ return '';
242
+ return `[Working state — carried from previous turns in THIS project]\n${lines.join('\n')}`;
243
+ }
244
+ //# sourceMappingURL=working-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"working-state.js","sourceRoot":"","sources":["../../src/learning/working-state.ts"],"names":[],"mappings":"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"}