@wrongstack/core 0.89.3 → 0.104.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 (51) hide show
  1. package/dist/{agent-bridge-DbVe1dHT.d.ts → agent-bridge-mOxbpFcg.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-C6eqID1t.d.ts → agent-subagent-runner-DukQLUcS.d.ts} +5 -5
  3. package/dist/{brain-s9DyD_Vf.d.ts → brain-Dfv4Y82E.d.ts} +1 -1
  4. package/dist/{config-84VaZpH6.d.ts → config-BSU-6vah.d.ts} +1 -1
  5. package/dist/coordination/index.d.ts +9 -9
  6. package/dist/coordination/index.js +103 -0
  7. package/dist/coordination/index.js.map +1 -1
  8. package/dist/defaults/index.d.ts +18 -17
  9. package/dist/defaults/index.js +276 -12
  10. package/dist/defaults/index.js.map +1 -1
  11. package/dist/execution/index.d.ts +61 -365
  12. package/dist/execution/index.js +423 -8
  13. package/dist/execution/index.js.map +1 -1
  14. package/dist/extension/index.d.ts +4 -4
  15. package/dist/goal-preamble-CI8lxeY1.d.ts +378 -0
  16. package/dist/{goal-store-DvWLNu52.d.ts → goal-store-ht0VmR1A.d.ts} +63 -21
  17. package/dist/{index-CqrroYcU.d.ts → index-BWRN6wOb.d.ts} +5 -5
  18. package/dist/{index-D3Nax3YU.d.ts → index-DIKEcfgC.d.ts} +3 -3
  19. package/dist/index.d.ts +31 -29
  20. package/dist/index.js +530 -53
  21. package/dist/index.js.map +1 -1
  22. package/dist/infrastructure/index.d.ts +4 -4
  23. package/dist/kernel/index.d.ts +6 -6
  24. package/dist/{mcp-servers-D3E5ixAR.d.ts → mcp-servers-CXCsANdY.d.ts} +1 -1
  25. package/dist/{multi-agent-coordinator-DHNrjPaA.d.ts → multi-agent-coordinator-51LvnXkD.d.ts} +1 -1
  26. package/dist/{null-fleet-bus-BzzciAc4.d.ts → null-fleet-bus-D09hMzFQ.d.ts} +5 -5
  27. package/dist/observability/index.d.ts +1 -1
  28. package/dist/{parallel-eternal-engine-CTpcrb9O.d.ts → parallel-eternal-engine-CUtmM_0V.d.ts} +24 -5
  29. package/dist/{path-resolver-B7hgMAVe.d.ts → path-resolver-DDJiMAtX.d.ts} +1 -1
  30. package/dist/{pipeline-C1Ad9OjI.d.ts → pipeline-BqiA_UMr.d.ts} +2 -2
  31. package/dist/{plan-templates-CNphsz0n.d.ts → plan-templates-BdDxl9cI.d.ts} +2 -2
  32. package/dist/{provider-runner-cqvlB_oS.d.ts → provider-runner-BUunikwY.d.ts} +1 -1
  33. package/dist/sdd/index.d.ts +11 -6
  34. package/dist/sdd/index.js +124 -5
  35. package/dist/sdd/index.js.map +1 -1
  36. package/dist/{session-event-bridge-IVzs2GpE.d.ts → session-event-bridge-BpJ5trO9.d.ts} +1 -1
  37. package/dist/{skill-BJxzIyyN.d.ts → skill-Bj6Ezqb8.d.ts} +1 -1
  38. package/dist/skills/index.d.ts +1 -1
  39. package/dist/spec-TBi3Jr6T.d.ts +78 -0
  40. package/dist/storage/index.d.ts +21 -9
  41. package/dist/storage/index.js +157 -14
  42. package/dist/storage/index.js.map +1 -1
  43. package/dist/task-format-vGOIftmK.d.ts +23 -0
  44. package/dist/task-graph-u1q9Jkyk.d.ts +84 -0
  45. package/dist/types/index.d.ts +15 -14
  46. package/dist/utils/index.d.ts +3 -1
  47. package/dist/utils/index.js +110 -1
  48. package/dist/utils/index.js.map +1 -1
  49. package/package.json +1 -1
  50. package/skills/tech-stack/SKILL.md +177 -0
  51. package/dist/task-graph-DJBqO0EY.d.ts +0 -161
@@ -1,9 +1,9 @@
1
- export { i as AfterIterationHook, j as AfterRunHook, k as AfterToolExecutionHook, l as AgentExtension, B as BeforeIterationHook, m as BeforeRunHook, n as BeforeToolExecutionHook, E as ExtensionRegistry, O as OnErrorHook, v as ProviderRunnerFn, t as ProviderRunnerWrapper } from '../index-D3Nax3YU.js';
1
+ export { i as AfterIterationHook, j as AfterRunHook, k as AfterToolExecutionHook, l as AgentExtension, B as BeforeIterationHook, m as BeforeRunHook, n as BeforeToolExecutionHook, E as ExtensionRegistry, O as OnErrorHook, v as ProviderRunnerFn, t as ProviderRunnerWrapper } from '../index-DIKEcfgC.js';
2
2
  import '../context-CNRYfhUv.js';
3
3
  import '../logger-B63L5bTg.js';
4
- import '../pipeline-C1Ad9OjI.js';
5
- import '../config-84VaZpH6.js';
4
+ import '../pipeline-BqiA_UMr.js';
5
+ import '../config-BSU-6vah.js';
6
6
  import '../models-registry-B6_KfS65.js';
7
7
  import '../observability-D-HZN_mF.js';
8
- import '../brain-s9DyD_Vf.js';
8
+ import '../brain-Dfv4Y82E.js';
9
9
  import '../permission-BDv7z0mk.js';
@@ -0,0 +1,378 @@
1
+ import { S as SkillLoader, a as SkillManifest, b as SkillEntry } from './skill-Bj6Ezqb8.js';
2
+ import { W as WstackPaths } from './wstack-paths-_lqjzErq.js';
3
+ import { P as Provider, C as Context } from './context-CNRYfhUv.js';
4
+ import { C as Compactor, a as CompactReport } from './compactor-DXLxLcmU.js';
5
+ import { M as MessageSelector } from './selector-C7wcdqMA.js';
6
+ import { E as EventBus } from './brain-Dfv4Y82E.js';
7
+ import { M as MiddlewareHandler } from './pipeline-BqiA_UMr.js';
8
+ import { S as SessionEventBridge } from './session-event-bridge-BpJ5trO9.js';
9
+ import { C as ContextWindowAggressiveOn, c as ContextWindowPolicy } from './config-BSU-6vah.js';
10
+ import { g as Agent, D as DoneCondition } from './agent-subagent-runner-DukQLUcS.js';
11
+ import { R as RunResult, S as SystemPromptContributor } from './index-DIKEcfgC.js';
12
+
13
+ interface SkillLoaderOptions {
14
+ paths: WstackPaths;
15
+ bundledDir?: string | undefined;
16
+ }
17
+ /**
18
+ * Discovery order (later layers shadow earlier ones at boot, but we walk
19
+ * highest priority first and skip names already seen):
20
+ * 1. Project-committed: <project>/.wrongstack/skills/
21
+ * 2. User-global: ~/.wrongstack/skills/
22
+ * 3. Bundled with build: packages/core/skills/
23
+ */
24
+ declare class DefaultSkillLoader implements SkillLoader {
25
+ private readonly dirs;
26
+ private cache?;
27
+ constructor(opts: SkillLoaderOptions);
28
+ list(): Promise<SkillManifest[]>;
29
+ find(name: string): Promise<SkillManifest | undefined>;
30
+ manifestText(): Promise<string>;
31
+ listEntries(): Promise<SkillEntry[]>;
32
+ invalidateCache(): void;
33
+ readBody(name: string): Promise<string>;
34
+ }
35
+
36
+ /**
37
+ * Options for IntelligentCompactor.
38
+ */
39
+ interface IntelligentCompactorOptions {
40
+ /** Provider to use for LLM-assisted summarization. Required. */
41
+ provider: Provider;
42
+ /** Fraction of maxContext that triggers a warning (default 0.6). */
43
+ warnThreshold?: number | undefined;
44
+ /** Fraction of maxContext that triggers soft compaction (default 0.75). */
45
+ softThreshold?: number | undefined;
46
+ /** Fraction of maxContext that triggers hard compaction (default 0.9). */
47
+ hardThreshold?: number | undefined;
48
+ /** Max context window in tokens (used only for threshold fraction math). */
49
+ maxContext?: number | undefined;
50
+ /** How many recent (user+assistant) pairs to always preserve (default 4). */
51
+ preserveK?: number | undefined;
52
+ /** Token threshold below which tool results are not elided (default 500). */
53
+ eliseThreshold?: number | undefined;
54
+ /** System prompt for the summarizer sub-LLM. */
55
+ summarizerPrompt?: string | undefined;
56
+ /**
57
+ * Model ID to use for summarization. When not set, the same model as the
58
+ * agent is used (which risks cascading failure on context overflow). Set to
59
+ * a fast/cheap model like `claude-3-5-haiku-20240620` for resilience.
60
+ */
61
+ summarizerModel?: string | undefined;
62
+ }
63
+ /**
64
+ * IntelligentCompactor uses an LLM to:
65
+ * - Analyze message importance and preserve critical context
66
+ * - Generate semantic summaries for old message ranges
67
+ * - Make intelligent decisions about what to compact
68
+ *
69
+ * It extends HybridCompactor's elision logic with LLM-assisted summarization.
70
+ */
71
+ declare class IntelligentCompactor implements Compactor {
72
+ private readonly provider;
73
+ private readonly warnThreshold;
74
+ private readonly softThreshold;
75
+ private readonly hardThreshold;
76
+ private readonly maxContext;
77
+ private readonly preserveK;
78
+ private readonly eliseThreshold;
79
+ private readonly summarizerPrompt;
80
+ private readonly summarizerModel?;
81
+ constructor(opts: IntelligentCompactorOptions);
82
+ compact(ctx: Context, opts?: {
83
+ aggressive?: boolean | undefined;
84
+ }): Promise<CompactReport>;
85
+ /**
86
+ * Estimate the full API request token count: messages + systemPrompt + toolDefs.
87
+ * This is the accurate figure for context-window pressure monitoring.
88
+ */
89
+ private estimateFullRequest;
90
+ private summarizeAncientTurns;
91
+ private findSafeBoundary;
92
+ private findExchangeStart;
93
+ private callSummarizer;
94
+ private messagesToText;
95
+ private lightweightCompact;
96
+ private eliseOldToolResults;
97
+ private hasTextContent;
98
+ private estimateTokens;
99
+ }
100
+
101
+ /**
102
+ * Options for SelectiveCompactor — the most configurable compactor.
103
+ */
104
+ interface SelectiveCompactorOptions {
105
+ /** Provider for LLM calls (selector + summarizer). Required. */
106
+ provider: Provider;
107
+ /** Selector for LLM-driven importance analysis. */
108
+ selector?: MessageSelector | undefined;
109
+ /** Fraction of maxContext that triggers a warning (default 0.6). */
110
+ warnThreshold?: number | undefined;
111
+ /** Fraction of maxContext that triggers soft compaction (default 0.75). */
112
+ softThreshold?: number | undefined;
113
+ /** Fraction of maxContext that triggers hard compaction (default 0.9). */
114
+ hardThreshold?: number | undefined;
115
+ /** Max context window in tokens (used for threshold fraction math). */
116
+ maxContext?: number | undefined;
117
+ /** How many recent (user+assistant) pairs to always preserve (default 4). */
118
+ preserveK?: number | undefined;
119
+ /** Token threshold below which tool results are not elided (default 500). */
120
+ eliseThreshold?: number | undefined;
121
+ /** Model for selector LLM calls (default: same as provider default). */
122
+ selectorModel?: string | undefined;
123
+ /** Summarizer model for collapsed ranges (default: same as selectorModel). */
124
+ summarizerModel?: string | undefined;
125
+ /** Prompt for the summarizer sub-LLM. */
126
+ summarizerPrompt?: string | undefined;
127
+ }
128
+ /**
129
+ * SelectiveCompactor uses an LLM-driven MessageSelector to make
130
+ * surgical decisions about which message ranges to keep vs collapse.
131
+ *
132
+ * Compared to HybridCompactor / IntelligentCompactor:
133
+ * - HybridCompactor: rule-based (preserveK + elision), no LLM calls
134
+ * - IntelligentCompactor: LLM summarization but no structured selection
135
+ * - SelectiveCompactor: full LLM-driven selection + optional summarization
136
+ */
137
+ declare class SelectiveCompactor implements Compactor {
138
+ private readonly provider;
139
+ private readonly selector;
140
+ private readonly warnThreshold;
141
+ private readonly softThreshold;
142
+ private readonly hardThreshold;
143
+ private readonly maxContext;
144
+ private readonly preserveK;
145
+ private readonly eliseThreshold;
146
+ private readonly summarizerModel;
147
+ private readonly summarizerPrompt;
148
+ constructor(opts: SelectiveCompactorOptions);
149
+ compact(ctx: Context, opts?: {
150
+ aggressive?: boolean | undefined;
151
+ }): Promise<CompactReport>;
152
+ /**
153
+ * Estimate the full API request token count: messages + systemPrompt + toolDefs.
154
+ * This is the accurate figure for context-window pressure monitoring.
155
+ */
156
+ private estimateFullRequest;
157
+ private repairProtocolAdjacency;
158
+ /**
159
+ * Run the LLM selector to decide what to keep vs collapse.
160
+ * Returns the token savings achieved.
161
+ */
162
+ private runSelector;
163
+ /**
164
+ * Execute a SelectorResult plan: collapse/remove ranges and
165
+ * insert summaries where the selector provided them.
166
+ */
167
+ private executePlan;
168
+ private summarizeRange;
169
+ private messagePreview;
170
+ /**
171
+ * Fallback when selector fails: aggressively trim from the oldest end
172
+ * until we hit targetBudget.
173
+ */
174
+ private aggressiveRecencyTrim;
175
+ private computeTargetBudget;
176
+ private eliseOldToolResults;
177
+ private hasTextContent;
178
+ private estimateTokens;
179
+ private roughTokenEstimate;
180
+ }
181
+
182
+ type CompactionFailureMode = 'throw' | 'throw_on_hard' | 'continue';
183
+ interface AutoCompactionOptions {
184
+ aggressiveOn?: ContextWindowAggressiveOn | undefined;
185
+ events?: EventBus | undefined;
186
+ failureMode?: CompactionFailureMode | undefined;
187
+ policyProvider?: (ctx: Context) => Pick<ContextWindowPolicy, 'thresholds' | 'aggressiveOn'> | null | undefined;
188
+ /** Optional bridge for writing compaction events into the persistent session log. */
189
+ sessionBridge?: SessionEventBridge | undefined;
190
+ }
191
+ /**
192
+ * Pipeline middleware that monitors context token load and automatically
193
+ * triggers compaction when the warn/soft/hard thresholds are crossed.
194
+ * Runs before the next agent iteration.
195
+ *
196
+ * Uses `estimateRequestTokens` for accurate full-request token counting:
197
+ * messages + systemPrompt + toolDefs. This replaces the previous pattern
198
+ * of applying an OVERHEAD_FACTOR to a messages-only estimate.
199
+ */
200
+ declare class AutoCompactionMiddleware {
201
+ readonly name = "AutoCompaction";
202
+ private readonly compactor;
203
+ /** Deprecated. Kept for backward compat with tests that pass simpleEstimator. */
204
+ private readonly _estimator?;
205
+ private readonly warnThreshold;
206
+ private readonly softThreshold;
207
+ private readonly hardThreshold;
208
+ /** Writable so model-switch can update the denominator without re-registering the middleware. */
209
+ private _maxContext;
210
+ private readonly aggressiveOn;
211
+ private readonly events?;
212
+ private readonly failureMode;
213
+ private readonly policyProvider?;
214
+ private readonly sessionBridge?;
215
+ /**
216
+ * Once a compaction attempt reduces nothing (preserveK protects everything,
217
+ * no oversized tool_results remain to elide), retrying on every iteration
218
+ * just spams `compaction.fired` events without making progress. We remember
219
+ * the no-op and skip until either the pressure level escalates or context
220
+ * has grown by at least this many tokens since the failed attempt.
221
+ */
222
+ private static readonly NOOP_RETRY_DELTA_TOKENS;
223
+ /** Tracks the most recent no-op attempt so we can avoid re-firing per turn. */
224
+ private lastNoopAttempt;
225
+ /**
226
+ * @param compactor Compactor to use for compaction.
227
+ * @param maxContext Provider's max context window in tokens.
228
+ * @param _estimator Deprecated parameter kept for backward compatibility.
229
+ * The middleware now uses `estimateRequestTokens` internally
230
+ * for accurate full-request token counting (messages +
231
+ * systemPrompt + toolDefs).
232
+ * @param thresholds Threshold fractions (0-1) of maxContext.
233
+ * @param opts Optional behavior. By default, failures at the
234
+ * hard threshold throw AGENT_CONTEXT_OVERFLOW so
235
+ * the agent does not continue into a likely
236
+ * provider context overflow. Warn/soft failures
237
+ * still emit compaction.failed and continue.
238
+ */
239
+ constructor(compactor: Compactor, maxContext: number, _estimator: (ctx: Context) => number, thresholds: {
240
+ warn: number;
241
+ soft: number;
242
+ hard: number;
243
+ }, optsOrAggressiveOn?: AutoCompactionOptions | ContextWindowAggressiveOn, events?: EventBus | undefined);
244
+ /** Allow callers (e.g. model-switch in WebUI) to update the context window
245
+ * denominator when the active model changes. */
246
+ setMaxContext(maxContext: number): void;
247
+ handler(): MiddlewareHandler<Context>;
248
+ /**
249
+ * Returns true when the previous compaction at the same or higher pressure
250
+ * level reduced nothing and context has not grown materially since. Prevents
251
+ * a stuck preserveK window from spamming compaction events every iteration.
252
+ */
253
+ private shouldSkipNoopRetry;
254
+ private recordAttempt;
255
+ private compact;
256
+ }
257
+
258
+ type AutonomousResult = RunResult & {
259
+ toolCalls: number;
260
+ reason?: string | undefined;
261
+ };
262
+ interface DoneCheckResult {
263
+ done: boolean;
264
+ reason?: string | undefined;
265
+ iterations: number;
266
+ toolCalls: number;
267
+ }
268
+ declare class DoneConditionChecker {
269
+ private readonly condition;
270
+ private readonly compiledRegex;
271
+ constructor(condition: DoneCondition);
272
+ check(state: {
273
+ iterations: number;
274
+ toolCalls: number;
275
+ lastOutput?: string | undefined;
276
+ }): DoneCheckResult;
277
+ }
278
+ interface AutonomousRunnerOptions {
279
+ agent: Agent;
280
+ context: Context;
281
+ doneCondition: DoneCondition;
282
+ iterationTimeoutMs?: number | undefined;
283
+ onIteration?: (state: {
284
+ iteration: number | undefined;
285
+ toolCalls: number;
286
+ }) => void;
287
+ onDone?: (((result: AutonomousResult) => void)) | undefined;
288
+ /**
289
+ * When true and `doneCondition.type === 'directive'`, the runner
290
+ * runs the agent with `autonomousContinue: true` so the agent loop
291
+ * handles its own [continue]/[done] markers internally (no outer
292
+ * re-invocation needed). The runner still provides iteration/timeouts.
293
+ */
294
+ enableAutonomousContinue?: boolean | undefined;
295
+ }
296
+ declare class AutonomousRunner {
297
+ private readonly opts;
298
+ private iterations;
299
+ private toolCalls;
300
+ private lastOutput?;
301
+ private stopped;
302
+ private readonly doneChecker;
303
+ constructor(opts: AutonomousRunnerOptions);
304
+ run(): Promise<AutonomousResult>;
305
+ private runLoop;
306
+ stop(): void;
307
+ }
308
+
309
+ /**
310
+ * System-prompt contributor that surfaces eternal-autonomy state to the
311
+ * model on every turn.
312
+ *
313
+ * Why this exists: when the engine drives a long-running loop, the
314
+ * per-iteration directive carries the rules. But the directive is a USER
315
+ * message — it scrolls out of working memory after a few compactions and
316
+ * the model forgets it's in autonomy mode (forgets `[GOAL_COMPLETE]`,
317
+ * forgets the todo-state protocol, forgets the no-confirmation rule).
318
+ * Injecting the same anchor as a CACHED system-prompt block solves that
319
+ * — the rules sit next to the identity layer and survive compactions.
320
+ *
321
+ * Block is tagged `ephemeral` so its content (journal tail, iteration
322
+ * counter) changes each turn without invalidating the upstream prefix
323
+ * cache.
324
+ */
325
+
326
+ interface AutonomyPromptContributorOptions {
327
+ /** Absolute path to the project's `goal.json`. */
328
+ goalPath: string;
329
+ /**
330
+ * Gating function. The contributor consults this on every build and
331
+ * returns an empty array when `false` — without this, the block would
332
+ * leak into interactive runs that happen to have a goal on disk and
333
+ * teach the model loop-control markers it shouldn't emit.
334
+ *
335
+ * Typical wiring: enable while `eternal` or `eternal-parallel` autonomy is active.
336
+ */
337
+ enabled: () => boolean;
338
+ /** Number of journal entries to include in the recent-tail block. Default 5. */
339
+ journalTailSize?: number | undefined;
340
+ }
341
+ /**
342
+ * Build a contributor that renders the autonomy-state system block.
343
+ * Returns `[]` when disabled, no goal exists, or the goal has been
344
+ * completed/abandoned — all silent fast-paths.
345
+ */
346
+ declare function makeAutonomyPromptContributor(opts: AutonomyPromptContributorOptions): SystemPromptContributor;
347
+
348
+ /**
349
+ * `/goal <description>` preamble — the "no force can stop this" mode.
350
+ *
351
+ * Unlike STEERING (which redirects mid-flight), GOAL is a contract:
352
+ * the user hands over a problem, the agent commits to verifiably
353
+ * finishing it, and every iteration re-reads this preamble from the
354
+ * conversation history. The hardening is entirely prompt-level —
355
+ * the system has already removed implicit budget caps, so this
356
+ * preamble's job is to remove the MODEL's tendency to hedge, ask
357
+ * permission, or declare premature success.
358
+ *
359
+ * The four sections are intentional:
360
+ * 1. AUTHORITY — explicit grant of unbounded fan-out + model
361
+ * switching. Without this the model self-throttles ("I shouldn't
362
+ * spawn too many…") even when budgets are unlimited.
363
+ * 2. DONE — concrete bar for completion. Forces a verifiable
364
+ * artifact (test passing, file written, bug re-run clean).
365
+ * Without this the model returns "I believe it's fixed" and
366
+ * counts that as done.
367
+ * 3. NOT DONE — explicit anti-patterns. Each item is something we
368
+ * saw real agents do as a "completion" that wasn't.
369
+ * 4. PERSISTENCE — three-angle rule for blockers. Stops the model
370
+ * from giving up on the first tool failure.
371
+ *
372
+ * Located in @wrongstack/core (rather than @wrongstack/tui) so headless
373
+ * callers and the WebUI can issue `/goal set` without dragging the TUI
374
+ * package in. The tui re-exports this for backward compatibility.
375
+ */
376
+ declare function buildGoalPreamble(goal: string, deliverables?: string[]): string;
377
+
378
+ export { AutoCompactionMiddleware as A, DefaultSkillLoader as D, IntelligentCompactor as I, SelectiveCompactor as S, AutonomousRunner as a, type AutonomousRunnerOptions as b, type AutonomyPromptContributorOptions as c, type DoneCheckResult as d, DoneConditionChecker as e, type IntelligentCompactorOptions as f, type SelectiveCompactorOptions as g, type SkillLoaderOptions as h, buildGoalPreamble as i, makeAutonomyPromptContributor as m };
@@ -30,8 +30,34 @@ interface JournalEntry {
30
30
  }
31
31
  interface GoalFile {
32
32
  version: 1;
33
- /** The mission statement. */
33
+ /** The raw mission statement as entered by the user. */
34
34
  goal: string;
35
+ /**
36
+ * LLM-refined version of the goal — unambiguous, with concrete
37
+ * deliverables and acceptance criteria.
38
+ */
39
+ refinedGoal?: string | undefined;
40
+ /**
41
+ * Concrete, verifiable deliverables extracted from the refined goal.
42
+ */
43
+ deliverables?: string[] | undefined;
44
+ /**
45
+ * Estimated completion 0-100. Updated by the engine after each
46
+ * iteration. Null means "not yet assessed".
47
+ */
48
+ progress?: number | undefined;
49
+ /** Human-readable note explaining the current progress estimate. */
50
+ progressNote?: string | undefined;
51
+ /**
52
+ * Time-series of progress measurements for trend analysis.
53
+ * Last 200 entries retained. Use `recordProgress()` to append.
54
+ */
55
+ progressHistory?: ProgressSnapshot[] | undefined;
56
+ /**
57
+ * Computed trend from recent progress measurements.
58
+ * 'accelerating' | 'steady' | 'stalling' | undefined.
59
+ */
60
+ progressTrend?: 'accelerating' | 'steady' | 'stalling' | undefined;
35
61
  /** When the goal was first set or last replaced. */
36
62
  setAt: string;
37
63
  /** Updated on every iteration completion. */
@@ -41,23 +67,11 @@ interface GoalFile {
41
67
  /** Engine lifecycle state — 'running' means another process owns this goal. */
42
68
  engineState: 'idle' | 'running' | 'stopped';
43
69
  /**
44
- * Mission-level lifecycle. `active` is the default; `completed` is set
45
- * when the engine detects `[GOAL_COMPLETE]` in a successful iteration's
46
- * final text AND a verification pass agrees; `abandoned` is set by the
47
- * user (e.g. `/goal abandon`) or when the engine exceeds a configured
48
- * failure ceiling. Once not `active`, the engine refuses to run further
49
- * iterations against this goal — protects against accidental restarts
50
- * burning through API quota after the work is done.
51
- *
52
- * Optional for backward compatibility — pre-existing `goal.json` files
53
- * without this field load as `active`.
70
+ * Mission-level lifecycle.
54
71
  */
55
72
  goalState?: 'active' | 'paused' | 'completed' | 'abandoned' | undefined;
56
73
  /**
57
- * Per-todo attempt counter. Keyed by TodoItem id. Used by the engine
58
- * to skip a todo that has failed N times rather than spinning on it
59
- * forever. Persisted so attempt counts survive restarts (`/autonomy
60
- * stop` + resume should not reset progress against a stuck task).
74
+ * Per-todo attempt counter.
61
75
  */
62
76
  todoAttempts?: Record<string, number>;
63
77
  /** Bounded ring buffer of recent iterations (newest last). */
@@ -67,22 +81,23 @@ interface GoalFile {
67
81
  declare const MAX_JOURNAL_ENTRIES = 500;
68
82
  /**
69
83
  * Resolve the goal file path for a given project root.
70
- * Exposed so the engine and CLI use one canonical path.
71
- * Uses `~/.wrongstack/projects/<hash>/goal.json` .<hash>/`.
72
84
  */
73
85
  declare function goalFilePath(projectRoot: string): string;
74
86
  declare function loadGoal(filePath: string): Promise<GoalFile | null>;
75
87
  declare function saveGoal(filePath: string, goal: GoalFile): Promise<void>;
76
88
  declare function emptyGoal(goal: string): GoalFile;
89
+ /**
90
+ * Set progress estimate on a goal. Returns a new GoalFile.
91
+ * Clamps progress to 0-100.
92
+ */
93
+ declare function setProgress(goal: GoalFile, progress: number, note?: string): GoalFile;
77
94
  /**
78
95
  * Append a journal entry, bumping iteration counters and trimming the
79
96
  * ring buffer. Returns a new GoalFile — does not mutate the argument.
80
97
  */
81
98
  declare function appendJournal(goal: GoalFile, entry: Omit<JournalEntry, 'iteration' | 'at'>): GoalFile;
82
99
  /**
83
- * Aggregate cumulative cost + tokens across all journal entries. Entries
84
- * without telemetry are skipped (legacy entries from before the field
85
- * was added still load cleanly).
100
+ * Aggregate cumulative cost + tokens across all journal entries.
86
101
  */
87
102
  declare function summarizeUsage(goal: GoalFile): {
88
103
  totalCostUsd: number;
@@ -92,5 +107,32 @@ declare function summarizeUsage(goal: GoalFile): {
92
107
  };
93
108
  /** Format the goal + recent journal as a human-readable status block. */
94
109
  declare function formatGoal(goal: GoalFile, journalLimit?: number): string;
110
+ /** A single progress measurement at a point in time. */
111
+ interface ProgressSnapshot {
112
+ at: string;
113
+ progress: number;
114
+ note?: string | undefined;
115
+ }
116
+ /**
117
+ * Parse [PROGRESS: N%] from agent final text.
118
+ * Supports formats:
119
+ * [PROGRESS: 45%]
120
+ * [PROGRESS: 45%] — 3/5 deliverables done
121
+ * [progress: 100%]
122
+ * Returns null if no match.
123
+ */
124
+ declare function parseProgressFromText(text: string): {
125
+ progress: number;
126
+ note?: string;
127
+ } | null;
128
+ /**
129
+ * Record a progress measurement. Returns a new GoalFile with:
130
+ * - progress + progressNote updated
131
+ * - progressHistory appended (last 200 entries kept)
132
+ * - progress trend computed (accelerating/steady/stalling)
133
+ */
134
+ declare function recordProgress(goal: GoalFile, progress: number, note?: string): GoalFile;
135
+ /** Max progress history entries to retain. */
136
+ declare const MAX_PROGRESS_HISTORY = 200;
95
137
 
96
- export { type GoalFile as G, type JournalEntry as J, MAX_JOURNAL_ENTRIES as M, appendJournal as a, summarizeUsage as b, emptyGoal as e, formatGoal as f, goalFilePath as g, loadGoal as l, saveGoal as s };
138
+ export { type GoalFile as G, type JournalEntry as J, MAX_JOURNAL_ENTRIES as M, type ProgressSnapshot as P, MAX_PROGRESS_HISTORY as a, appendJournal as b, setProgress as c, summarizeUsage as d, emptyGoal as e, formatGoal as f, goalFilePath as g, loadGoal as l, parseProgressFromText as p, recordProgress as r, saveGoal as s };
@@ -1,7 +1,7 @@
1
- import { T as Token, a as Renderer, S as SystemPromptBuilder, H as HookRegistry } from './pipeline-C1Ad9OjI.js';
2
- import { E as EventBus, l as MemoryStore, B as BrainArbiter } from './brain-s9DyD_Vf.js';
1
+ import { T as Token, a as Renderer, S as SystemPromptBuilder, H as HookRegistry } from './pipeline-BqiA_UMr.js';
2
+ import { E as EventBus, l as MemoryStore, b as BrainArbiter } from './brain-Dfv4Y82E.js';
3
3
  import { C as Compactor } from './compactor-DXLxLcmU.js';
4
- import { d as ConfigLoader, c as ConfigStore } from './config-84VaZpH6.js';
4
+ import { f as ConfigLoader, e as ConfigStore } from './config-BSU-6vah.js';
5
5
  import { E as ErrorHandler, R as RetryPolicy } from './retry-policy-BcmuT_V0.js';
6
6
  import { I as InputReader } from './input-reader-E-ffP2ee.js';
7
7
  import { L as Logger } from './logger-B63L5bTg.js';
@@ -9,9 +9,9 @@ import { M as ModeStore } from './mode-ARA3HrkY.js';
9
9
  import { M as ModelsRegistry } from './models-registry-B6_KfS65.js';
10
10
  import { P as PathResolver } from './path-resolver-CPRj4bFY.js';
11
11
  import { P as PermissionPolicy, S as SecretScrubber } from './permission-BDv7z0mk.js';
12
- import { P as ProviderRunner } from './provider-runner-cqvlB_oS.js';
12
+ import { P as ProviderRunner } from './provider-runner-BUunikwY.js';
13
13
  import { c as TokenCounter, i as SessionStore } from './context-CNRYfhUv.js';
14
- import { S as SkillLoader } from './skill-BJxzIyyN.js';
14
+ import { S as SkillLoader } from './skill-Bj6Ezqb8.js';
15
15
 
16
16
  /**
17
17
  * Lifecycle of a single worktree handle.
@@ -1,9 +1,9 @@
1
1
  import { l as TextBlock, T as Tool, m as ToolUseBlock, C as Context, n as ToolResultBlock, R as Request, b as Response, P as Provider, g as ContentBlock, a0 as WrongStackError } from './context-CNRYfhUv.js';
2
2
  import { L as Logger } from './logger-B63L5bTg.js';
3
- import { B as BuildContext, H as HookRegistry, a as Renderer, P as Pipeline, C as Container } from './pipeline-C1Ad9OjI.js';
4
- import { H as HookEvent, u as ProviderConfig } from './config-84VaZpH6.js';
3
+ import { B as BuildContext, H as HookRegistry, a as Renderer, P as Pipeline, C as Container } from './pipeline-BqiA_UMr.js';
4
+ import { H as HookEvent, u as ProviderConfig } from './config-BSU-6vah.js';
5
5
  import { T as Tracer } from './observability-D-HZN_mF.js';
6
- import { E as EventBus } from './brain-s9DyD_Vf.js';
6
+ import { E as EventBus } from './brain-Dfv4Y82E.js';
7
7
  import { P as PermissionPolicy, S as SecretScrubber } from './permission-BDv7z0mk.js';
8
8
  import { W as WireFamily } from './models-registry-B6_KfS65.js';
9
9