footprintjs 10.2.0 → 10.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 (57) hide show
  1. package/dist/esm/index.d.ts +1 -0
  2. package/dist/esm/index.js +1 -1
  3. package/dist/esm/lib/attempt/category.d.ts +4 -2
  4. package/dist/esm/lib/attempt/category.js +18 -11
  5. package/dist/esm/lib/attempt/errorField.d.ts +2 -0
  6. package/dist/esm/lib/attempt/errorField.js +32 -0
  7. package/dist/esm/lib/capture/nativeCoverage.d.ts +56 -0
  8. package/dist/esm/lib/capture/nativeCoverage.js +102 -0
  9. package/dist/esm/lib/memory/StageContext.d.ts +5 -0
  10. package/dist/esm/lib/memory/StageContext.js +27 -6
  11. package/dist/esm/lib/memory/attention.d.ts +2 -0
  12. package/dist/esm/lib/memory/attention.js +12 -5
  13. package/dist/esm/lib/recorder/ControlDepRecorder.d.ts +12 -1
  14. package/dist/esm/lib/recorder/ControlDepRecorder.js +23 -1
  15. package/dist/esm/lib/recorder/snapshot.d.ts +1 -1
  16. package/dist/esm/lib/recorder/snapshot.js +7 -2
  17. package/dist/esm/lib/runner/ExecutionRuntime.d.ts +9 -0
  18. package/dist/esm/lib/runner/ExecutionRuntime.js +13 -1
  19. package/dist/esm/lib/runner/FlowChartExecutor.d.ts +2 -0
  20. package/dist/esm/lib/runner/FlowChartExecutor.js +31 -2
  21. package/dist/esm/lib/runner/attach.js +4 -2
  22. package/dist/esm/lib/runner/options.d.ts +3 -0
  23. package/dist/esm/lib/runner/options.js +5 -1
  24. package/dist/esm/lib/runner/snapshot.d.ts +3 -1
  25. package/dist/esm/lib/runner/snapshot.js +35 -4
  26. package/dist/esm/lib/scope/ScopeFacade.js +4 -2
  27. package/dist/esm/lib/scope/runtime.d.ts +2 -0
  28. package/dist/esm/lib/scope/runtime.js +9 -1
  29. package/dist/index.js +1 -1
  30. package/dist/lib/attempt/category.js +18 -11
  31. package/dist/lib/attempt/errorField.js +36 -0
  32. package/dist/lib/capture/nativeCoverage.js +107 -0
  33. package/dist/lib/memory/StageContext.js +27 -6
  34. package/dist/lib/memory/attention.js +12 -5
  35. package/dist/lib/recorder/ControlDepRecorder.js +23 -1
  36. package/dist/lib/recorder/snapshot.js +7 -2
  37. package/dist/lib/runner/ExecutionRuntime.js +13 -1
  38. package/dist/lib/runner/FlowChartExecutor.js +34 -5
  39. package/dist/lib/runner/attach.js +3 -1
  40. package/dist/lib/runner/options.js +5 -1
  41. package/dist/lib/runner/snapshot.js +35 -4
  42. package/dist/lib/scope/ScopeFacade.js +3 -1
  43. package/dist/lib/scope/runtime.js +12 -2
  44. package/dist/types/index.d.ts +1 -0
  45. package/dist/types/lib/attempt/category.d.ts +4 -2
  46. package/dist/types/lib/attempt/errorField.d.ts +2 -0
  47. package/dist/types/lib/capture/nativeCoverage.d.ts +56 -0
  48. package/dist/types/lib/memory/StageContext.d.ts +5 -0
  49. package/dist/types/lib/memory/attention.d.ts +2 -0
  50. package/dist/types/lib/recorder/ControlDepRecorder.d.ts +12 -1
  51. package/dist/types/lib/recorder/snapshot.d.ts +1 -1
  52. package/dist/types/lib/runner/ExecutionRuntime.d.ts +9 -0
  53. package/dist/types/lib/runner/FlowChartExecutor.d.ts +2 -0
  54. package/dist/types/lib/runner/options.d.ts +3 -0
  55. package/dist/types/lib/runner/snapshot.d.ts +3 -1
  56. package/dist/types/lib/scope/runtime.d.ts +2 -0
  57. package/package.json +1 -1
@@ -0,0 +1,56 @@
1
+ import type { LogAddress } from 'foottrace';
2
+ import type { TerminalFailureContext } from '../errors/terminalFailure.js';
3
+ export type CaptureChannelStatus = 'captured' | 'disabled' | 'partial' | 'failed' | 'unknown';
4
+ export type CaptureLimitation = 'tracked-state-only' | 'final-attempt-views' | 'read-sources-not-collected' | 'child-scopes-not-attested' | 'storage-not-attested' | 'resumed-segment' | 'redacted-export' | 'redaction-active' | 'custom-scope' | 'read-retention-failed' | 'commit-retention-failed' | 'attention-omitted' | 'recorder-snapshot-failed' | 'identity-omitted' | 'execution-broken' | 'modes-unavailable';
5
+ /** A producer acknowledgement, not engine inspection of a recorder's implementation. */
6
+ export interface RecorderCaptureAcknowledgement {
7
+ readonly version: 1;
8
+ readonly runId: string;
9
+ readonly control: 'captured' | 'partial' | 'unknown';
10
+ }
11
+ /** Engine observation of ONE root-log segment. Never a durable or whole-workflow completeness claim. */
12
+ export interface NativeCaptureNote {
13
+ readonly version: 1;
14
+ readonly runId: string;
15
+ readonly scope: 'root-log';
16
+ readonly logAddress: LogAddress;
17
+ /** Half-open offsets in this log. A same-executor resume starts at the previous end. */
18
+ readonly commits: {
19
+ readonly from: number;
20
+ readonly to: number;
21
+ };
22
+ readonly boundary: {
23
+ readonly status: 'running' | 'completed' | 'paused' | 'failed' | 'cancelled';
24
+ readonly failure?: TerminalFailureContext;
25
+ };
26
+ readonly modes: {
27
+ readonly readTracking: 'full' | 'summary' | 'off' | 'unknown';
28
+ readonly writeTracking: 'full' | 'summary' | 'off' | 'unknown';
29
+ readonly commitValues: 'full' | 'delta' | 'unknown';
30
+ readonly writeProvenance: 'off' | 'reads-prefix' | 'unknown';
31
+ };
32
+ readonly channels: {
33
+ readonly reads: CaptureChannelStatus;
34
+ readonly writes: CaptureChannelStatus;
35
+ readonly attention: CaptureChannelStatus;
36
+ readonly control: CaptureChannelStatus;
37
+ readonly readSources: 'not-collected';
38
+ };
39
+ readonly persistence: 'memory-only';
40
+ readonly limitations: readonly CaptureLimitation[];
41
+ }
42
+ /** @internal Bounded facts collected at native funnels; no values, key names, recorder discovery or tree walk. */
43
+ export declare class NativeCapture {
44
+ readonly runId: string;
45
+ readonly logAddress: LogAddress;
46
+ readonly from: number;
47
+ private readonly gaps;
48
+ private boundary;
49
+ private readonly modes;
50
+ constructor(runId: string, logAddress: LogAddress, from: number, modes: NativeCaptureNote['modes']);
51
+ limit(gap: CaptureLimitation): void;
52
+ end(status: NativeCaptureNote['boundary']['status'], failure?: TerminalFailureContext): void;
53
+ snapshot(to: number, control?: CaptureChannelStatus, redacted?: boolean): NativeCaptureNote;
54
+ }
55
+ /** Stored/recorder metadata is untrusted. Read data properties only, never getters or arbitrary strings. */
56
+ export declare function copyCaptureAcknowledgement(value: unknown): RecorderCaptureAcknowledgement | undefined;
@@ -14,6 +14,7 @@
14
14
  import type { CommitPhase, EmitSourcePosition, UntrackedSource } from 'foottrace';
15
15
  import type { EventLog, SharedMemory } from 'foottrace/write';
16
16
  import type { AttemptContext, AttemptRecord, AttemptSummary, LateWrite } from '../attempt/types.js';
17
+ import type { NativeCapture } from '../capture/nativeCoverage.js';
17
18
  import type { StructuredErrorInfo } from '../errors/errorInfo.js';
18
19
  import { type TerminalFailureContext, NativeFailureState } from '../errors/terminalFailure.js';
19
20
  import { type DiagnosticChannel, DiagnosticCollector } from './DiagnosticCollector.js';
@@ -57,6 +58,8 @@ export declare class StageContext {
57
58
  private policy;
58
59
  /** The emitting frame's logical leg, never the mutable executor's current leg. */
59
60
  private emitRunId?;
61
+ /** The native root-log collector; copied to same-log frames, never child runtimes. */
62
+ capture?: NativeCapture;
60
63
  stageName: string;
61
64
  /** Unique stage identifier from the builder (matches spec node id). */
62
65
  stageId: string;
@@ -342,6 +345,7 @@ export declare class StageContext {
342
345
  * `'summary'` records a cheap marker, `'off'` records nothing.
343
346
  */
344
347
  getValue(path: string[], key?: string, description?: string): unknown;
348
+ private readRetainedValue;
345
349
  /**
346
350
  * How many tracked reads of this frame read a value the run's rule selects
347
351
  * (a key it masks whole, or one with secret fields). A boundary that maps
@@ -455,6 +459,7 @@ export declare class StageContext {
455
459
  * reads them post-run for the execution-tree snapshot.
456
460
  */
457
461
  commit(phase?: CommitPhase): void;
462
+ private commitRetained;
458
463
  /** Whether this frame has committed — a call's record arriving after it is late (P2, `ScopeFacade · call`). */
459
464
  get committed(): boolean;
460
465
  /**
@@ -3,11 +3,13 @@ import type { Attention } from 'foottrace';
3
3
  import type { AttemptRecord, AttemptSummary } from '../attempt/types.js';
4
4
  /** One execution's ownership, pending summary, marks and omission accounting stay in this helper. */
5
5
  export declare class StageAttention {
6
+ private readonly onOmitted?;
6
7
  private marks?;
7
8
  private omitted;
8
9
  private retryPossible;
9
10
  private summary?;
10
11
  private terminal?;
12
+ constructor(onOmitted?: (() => void) | undefined);
11
13
  /** A new execution starts fresh; an attempt discard never calls this. No collection is reconstructed. */
12
14
  begin(): void;
13
15
  /** Called only after the frame retained this attempt. Raw error, target and decision payloads are never read. */
@@ -89,6 +89,8 @@ export interface ControlDecisionRecord {
89
89
  ruleLabel?: string;
90
90
  }
91
91
  export interface ControlDepRecorderOptions {
92
+ /** Opt in to a same-run collection acknowledgement in the snapshot bundle. */
93
+ captureCoverage?: boolean;
92
94
  /** Recorder id. Defaults to `control-deps-N` (auto-incremented). */
93
95
  id?: string;
94
96
  }
@@ -115,7 +117,11 @@ export declare class ControlDepRecorder implements FlowRecorder {
115
117
  private readonly consumedSlots;
116
118
  /** Convention 4 — runId of the run currently being recorded. */
117
119
  private lastRunId?;
120
+ private readonly captureCoverage;
121
+ private captureRunId?;
122
+ private captureIntact;
118
123
  constructor(options?: ControlDepRecorderOptions);
124
+ onRunStart(event: import('../engine/narrative/types.js').FlowRunEvent): void;
119
125
  onDecision(event: FlowDecisionEvent): void;
120
126
  onAttempt(event: FlowAttemptEvent): void;
121
127
  onSelected(event: FlowSelectedEvent): void;
@@ -146,13 +152,18 @@ export declare class ControlDepRecorder implements FlowRecorder {
146
152
  * Parentless roots cannot have a governing control edge.
147
153
  */
148
154
  toSnapshot(): {
149
- name: string;
150
155
  data: {
151
156
  decisions: ControlDecisionRecord[];
152
157
  controlDeps: {
153
158
  [k: string]: ControlDependency;
154
159
  };
155
160
  };
161
+ capture?: {
162
+ version: 1;
163
+ runId: string;
164
+ control: "captured" | "partial";
165
+ } | undefined;
166
+ name: string;
156
167
  };
157
168
  /** Reset all state (also happens automatically on runId change). */
158
169
  clear(): void;
@@ -16,4 +16,4 @@ import type { RecorderSnapshot } from '../runner/ExecutionRuntime.js';
16
16
  /** What `toSnapshot()` returns: a snapshot row without the `id` the attach site owns. */
17
17
  export type RecorderBundle = Omit<RecorderSnapshot, 'id'>;
18
18
  /** Rebuild `bundle` as the snapshot row for the recorder attached under `id`. */
19
- export declare function copyBundle(id: string, bundle: RecorderBundle): RecorderSnapshot;
19
+ export declare function copyBundle(id: string, bundle: RecorderBundle, includeCapture?: boolean): RecorderSnapshot;
@@ -13,6 +13,8 @@ import type { CommitBundle, CommitValuesMode, LogAddress, LogOutcome, Meta } fro
13
13
  import type { RecordSink, WriteProvenanceMode } from 'foottrace/write';
14
14
  import { EventLog, SharedMemory } from 'foottrace/write';
15
15
  import type { RunCorrelation } from '../attempt/types.js';
16
+ import type { NativeCaptureNote, RecorderCaptureAcknowledgement } from '../capture/nativeCoverage.js';
17
+ import { NativeCapture } from '../capture/nativeCoverage.js';
16
18
  import type { StageSnapshot } from '../memory/frameTypes.js';
17
19
  import type { RunPolicy } from '../memory/runPolicy.js';
18
20
  import { StageContext } from '../memory/StageContext.js';
@@ -43,6 +45,8 @@ export interface RecorderSnapshot {
43
45
  * keep the values JSON-safe, since this rides the snapshot out to disk.
44
46
  */
45
47
  meta?: Readonly<Record<string, unknown>>;
48
+ /** Optional current-run capture acknowledgement from the recorder contract. */
49
+ capture?: RecorderCaptureAcknowledgement;
46
50
  }
47
51
  export type RuntimeSnapshot = {
48
52
  /**
@@ -57,6 +61,8 @@ export type RuntimeSnapshot = {
57
61
  * snapshot carries a DIFFERENT runId than the paused run's snapshot.
58
62
  */
59
63
  readonly runId: string;
64
+ /** Opt-in native observation; root log and current leg only, never durable storage. */
65
+ readonly capture?: NativeCaptureNote;
60
66
  /**
61
67
  * The run's correlation (10.1) — `env.traceparent`, or `env.traceId` + `env.operationId`, resolved once per
62
68
  * leg; the same frozen object every event of the leg carries (`TraversalContext.correlation`, a scope event's
@@ -161,6 +167,9 @@ export interface RuntimeRecord {
161
167
  readonly meta?: Meta;
162
168
  }
163
169
  export declare class ExecutionRuntime {
170
+ /** Present only for the current opted-in root leg. Never inherited by a subflow runtime. */
171
+ capture?: NativeCapture;
172
+ beginCapture(runId: string): NativeCapture;
164
173
  globalStore: SharedMemory;
165
174
  /**
166
175
  * Parallel redacted mirror of `globalStore`. Populated by every commit that
@@ -65,6 +65,7 @@ export declare class FlowChartExecutor<TOut = any, TScope = any> {
65
65
  * See docs/guides/execution-model.md.
66
66
  */
67
67
  private _isExecuting;
68
+ private captureSignal?;
68
69
  private failureState;
69
70
  /** Safe native context for the latest rejected leg; undefined before, during, after success or pause. */
70
71
  getFailureContext(): TerminalFailureContext | undefined;
@@ -188,6 +189,7 @@ export declare class FlowChartExecutor<TOut = any, TScope = any> {
188
189
  * the `RecordSinkError`.
189
190
  */
190
191
  private settleRecorded;
192
+ private finishCapture;
191
193
  /**
192
194
  * What a new root log opens with: names and numbers the run already serves — the run, the chart, the correlation,
193
195
  * the deadline, the declared budget, and the run a fresh-executor resume continues. Served by the record.
@@ -59,6 +59,8 @@ export interface FlowChartExecutorOptions<TScope = any> extends RunDials {
59
59
  * ```
60
60
  */
61
61
  sink?: RecordSinkOption;
62
+ /** Opt in to a versioned, memory-only root-log capture note on snapshots (#111 stage 1). */
63
+ captureCoverage?: boolean;
62
64
  /**
63
65
  * Custom error classifier for throttling detection. Return `true` if a fork
64
66
  * child's error represents a rate-limit or backpressure condition; the
@@ -87,6 +89,7 @@ export interface ExecutorArgs<TOut, TScope> {
87
89
  dials: RunDials;
88
90
  /** The record sink, resolved and checked at construction (10.1, P6). */
89
91
  sink?: ResolvedRecordSink;
92
+ captureCoverage?: boolean;
90
93
  }
91
94
  /**
92
95
  * Resolve either constructor form. The 2-param form is the options form with
@@ -5,7 +5,9 @@
5
5
  * served subflow results (each subflow's own mirror under `redact: true`), one
6
6
  * recorder row per recorder id, and the deferred tier's accounting.
7
7
  */
8
+ import type { FlowRecorder } from '../engine/narrative/types.js';
8
9
  import type { FlowchartTraverser } from '../engine/traversal/FlowchartTraverser.js';
10
+ import type { ScopeRecorder } from '../scope/types.js';
9
11
  import type { RunObservers } from './attach.js';
10
12
  import type { RecorderSnapshot, RecordSinkStats, RuntimeSnapshot } from './ExecutionRuntime.js';
11
13
  /**
@@ -38,4 +40,4 @@ export declare function servedSnapshot(traverser: FlowchartTraverser<any, any>,
38
40
  * recorder cannot smuggle an `id` of its own choosing into the snapshot (the
39
41
  * id is the executor's, and consumers index by it).
40
42
  */
41
- export declare function collectRecorderSnapshots(observers: RunObservers): RecorderSnapshot[];
43
+ export declare function collectRecorderSnapshots(observers: RunObservers, collected?: (recorder: ScopeRecorder | FlowRecorder, row: RecorderSnapshot) => void, includeCapture?: boolean): RecorderSnapshot[];
@@ -49,3 +49,5 @@ export declare function scopeRuntimeFor(scope: unknown): Readonly<ScopeRuntime>
49
49
  export declare function requireScopeRuntime(scope: unknown, message?: string): Readonly<ScopeRuntime>;
50
50
  /** @internal decide()/select() asked outside a stage: name THEM, not the custom-factory migration. */
51
51
  export declare function requireDecisionScopeRuntime(scope: unknown): Readonly<ScopeRuntime>;
52
+ export declare function registerNativeCaptureTarget(target: object, context: object): void;
53
+ export declare function hasNativeCaptureTarget(target: object, context: object): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "footprintjs",
3
- "version": "10.2.0",
3
+ "version": "10.3.0",
4
4
  "description": "Explainable backend flows — automatic causal traces, decision evidence, and MCP tool generation for AI agents",
5
5
  "license": "MIT",
6
6
  "author": "Sanjay Krishna Anbalagan",