footprintjs 0.10.0 → 0.10.2
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.
- package/AGENTS.md +125 -0
- package/CLAUDE.md +127 -0
- package/README.md +48 -0
- package/ai-instructions/claude-code/SKILL.md +465 -0
- package/ai-instructions/clinerules +79 -0
- package/ai-instructions/copilot-instructions.md +86 -0
- package/ai-instructions/cursor/footprint.md +80 -0
- package/ai-instructions/kiro/footprint.md +79 -0
- package/ai-instructions/setup.sh +140 -0
- package/ai-instructions/windsurfrules +79 -0
- package/dist/esm/lib/engine/narrative/CombinedNarrativeBuilder.js +43 -14
- package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.js +267 -0
- package/dist/esm/lib/engine/narrative/NarrativeFlowRecorder.js +25 -1
- package/dist/esm/lib/engine/narrative/index.js +2 -1
- package/dist/esm/lib/runner/FlowChartExecutor.js +33 -16
- package/dist/esm/lib/scope/recorders/NarrativeRecorder.js +6 -1
- package/dist/esm/types/lib/engine/narrative/CombinedNarrativeBuilder.d.ts +15 -2
- package/dist/esm/types/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +63 -0
- package/dist/esm/types/lib/engine/narrative/NarrativeFlowRecorder.d.ts +11 -0
- package/dist/esm/types/lib/engine/narrative/index.d.ts +2 -0
- package/dist/esm/types/lib/runner/FlowChartExecutor.d.ts +8 -1
- package/dist/esm/types/lib/scope/recorders/NarrativeRecorder.d.ts +5 -0
- package/dist/lib/engine/narrative/CombinedNarrativeBuilder.js +43 -14
- package/dist/lib/engine/narrative/CombinedNarrativeRecorder.js +271 -0
- package/dist/lib/engine/narrative/NarrativeFlowRecorder.js +25 -1
- package/dist/lib/engine/narrative/index.js +4 -2
- package/dist/lib/runner/FlowChartExecutor.js +33 -16
- package/dist/lib/scope/recorders/NarrativeRecorder.js +6 -1
- package/dist/types/lib/engine/narrative/CombinedNarrativeBuilder.d.ts +15 -2
- package/dist/types/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +63 -0
- package/dist/types/lib/engine/narrative/NarrativeFlowRecorder.d.ts +11 -0
- package/dist/types/lib/engine/narrative/index.d.ts +2 -0
- package/dist/types/lib/runner/FlowChartExecutor.d.ts +8 -1
- package/dist/types/lib/scope/recorders/NarrativeRecorder.d.ts +5 -0
- package/package.json +8 -2
package/AGENTS.md
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# footprint.js — AI Agent Instructions
|
|
2
|
+
|
|
3
|
+
> The flowchart pattern for backend code — self-explainable systems that AI can reason about.
|
|
4
|
+
|
|
5
|
+
## What This Library Does
|
|
6
|
+
|
|
7
|
+
footprint.js structures backend logic as a graph of named functions with transactional state. Every run auto-generates a causal trace showing what happened and why. An LLM reads the trace and explains decisions accurately — no hallucination.
|
|
8
|
+
|
|
9
|
+
## Core Principle
|
|
10
|
+
|
|
11
|
+
**Collect during traversal, never post-process.** All data collection (narrative, metrics, manifest) happens as side effects of the single DFS traversal pass. Never walk the tree again after execution.
|
|
12
|
+
|
|
13
|
+
## Architecture
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
src/lib/
|
|
17
|
+
├── memory/ → Transactional state (SharedMemory, StageContext, TransactionBuffer)
|
|
18
|
+
├── schema/ → Validation (Zod optional, duck-typed detection)
|
|
19
|
+
├── builder/ → Fluent DSL (FlowChartBuilder, flowChart())
|
|
20
|
+
├── scope/ → Per-stage facades + recorders + providers
|
|
21
|
+
├── engine/ → DFS traversal + narrative + handlers
|
|
22
|
+
├── runner/ → High-level executor (FlowChartExecutor)
|
|
23
|
+
└── contract/ → I/O schema + OpenAPI generation
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Two entry points:
|
|
27
|
+
- `import { ... } from 'footprintjs'` — public API
|
|
28
|
+
- `import { ... } from 'footprintjs/advanced'` — internals
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { flowChart, FlowChartExecutor } from 'footprintjs';
|
|
34
|
+
|
|
35
|
+
const chart = flowChart('ReceiveOrder', (scope) => {
|
|
36
|
+
scope.setValue('orderId', 'ORD-123');
|
|
37
|
+
scope.setValue('amount', 49.99);
|
|
38
|
+
}, 'receive-order', undefined, 'Receive the incoming order')
|
|
39
|
+
.addFunction('ProcessPayment', (scope) => {
|
|
40
|
+
const amount = scope.getValue('amount');
|
|
41
|
+
scope.setValue('paymentStatus', amount < 100 ? 'approved' : 'review');
|
|
42
|
+
}, 'process-payment', 'Charge customer')
|
|
43
|
+
.setEnableNarrative()
|
|
44
|
+
.build();
|
|
45
|
+
|
|
46
|
+
const executor = new FlowChartExecutor(chart);
|
|
47
|
+
await executor.run({ input: { orderId: 'ORD-123' } });
|
|
48
|
+
console.log(executor.getNarrative());
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Builder API
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
flowChart(name, fn, id, extractor?, description?) // start chain
|
|
55
|
+
.addFunction(name, fn, id, description?) // linear stage
|
|
56
|
+
.addDeciderFunction(name, fn, id, description?) // single-choice branch
|
|
57
|
+
.addFunctionBranch(branchId, name, fn) // branch option
|
|
58
|
+
.addSubFlowChartBranch(branchId, subflow) // subflow branch
|
|
59
|
+
.setDefault(branchId) // fallback
|
|
60
|
+
.end() // close decider
|
|
61
|
+
.addSelectorFunction(name, fn, id, description?) // multi-choice fan-out
|
|
62
|
+
.addListOfFunction([...], { failFast? }) // parallel fork
|
|
63
|
+
.addSubFlowChartNext(id, subflow, mount, opts?) // mount subflow inline
|
|
64
|
+
.loopTo(stageId) // back-edge loop
|
|
65
|
+
.setEnableNarrative() // enable narrative
|
|
66
|
+
.setInputSchema(schema) // Zod or JSON Schema
|
|
67
|
+
.build() // compile
|
|
68
|
+
.toSpec() // JSON structure
|
|
69
|
+
.toMermaid() // diagram
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Stage Function Signature
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
(scope: ScopeFacade, breakPipeline: () => void, streamCallback?: StreamCallback) => void | Promise<void>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## ScopeFacade (per-stage state access)
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
scope.getValue('key') // tracked read → appears in narrative
|
|
82
|
+
scope.setValue('key', value) // tracked write → appears in narrative
|
|
83
|
+
scope.updateValue('key', partial) // deep merge (tracked)
|
|
84
|
+
scope.deleteValue('key') // tracked delete
|
|
85
|
+
scope.getArgs<T>() // frozen readonly input (NOT tracked)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Executor
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
const executor = new FlowChartExecutor(chart);
|
|
92
|
+
await executor.run({ input, timeoutMs?, signal? });
|
|
93
|
+
|
|
94
|
+
executor.getNarrative() // string[] — combined flow + data
|
|
95
|
+
executor.getNarrativeEntries() // CombinedNarrativeEntry[] — structured
|
|
96
|
+
executor.getSnapshot() // full memory state
|
|
97
|
+
executor.attachFlowRecorder(r) // plug observer before run()
|
|
98
|
+
executor.setRedactionPolicy({ // PII protection
|
|
99
|
+
keys: ['ssn'], patterns: [/password/i]
|
|
100
|
+
})
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Two Observer Systems
|
|
104
|
+
|
|
105
|
+
**Scope Recorder** — fires DURING stage: `onRead`, `onWrite`, `onCommit`, `onStageStart/End`
|
|
106
|
+
**FlowRecorder** — fires AFTER stage: `onStageExecuted`, `onDecision`, `onFork`, `onNext`, `onLoop`, `onError`
|
|
107
|
+
|
|
108
|
+
8 built-in FlowRecorder strategies: Narrative, Adaptive, Windowed, RLE, Milestone, Progressive, Separate, Manifest, Silent.
|
|
109
|
+
|
|
110
|
+
`CombinedNarrativeRecorder` implements BOTH — auto-attached by `setEnableNarrative()`.
|
|
111
|
+
|
|
112
|
+
## Anti-Patterns
|
|
113
|
+
|
|
114
|
+
- Never post-process the tree — use recorders
|
|
115
|
+
- Never use deprecated `CombinedNarrativeBuilder`
|
|
116
|
+
- Don't use `getArgs()` for tracked data — use `getValue()`/`setValue()`
|
|
117
|
+
- Don't manually create `CombinedNarrativeRecorder` — `setEnableNarrative()` handles it
|
|
118
|
+
|
|
119
|
+
## Build
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
npm install footprintjs
|
|
123
|
+
npm run build # CJS + ESM dual output
|
|
124
|
+
npm test
|
|
125
|
+
```
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# footprint.js — AI Coding Instructions
|
|
2
|
+
|
|
3
|
+
This is the footprint.js library — the flowchart pattern for backend code. Self-explainable systems that AI can reason about.
|
|
4
|
+
|
|
5
|
+
## Core Principle
|
|
6
|
+
|
|
7
|
+
**Collect during traversal, never post-process.** All data collection (narrative, metrics, manifest, identity) happens as side effects of the single DFS traversal pass. Never walk the tree again after execution.
|
|
8
|
+
|
|
9
|
+
## Architecture — Library of Libraries
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
src/lib/
|
|
13
|
+
├── memory/ → Transactional state (SharedMemory, StageContext, TransactionBuffer, EventLog)
|
|
14
|
+
├── schema/ → Validation abstraction (Zod optional, duck-typed detection)
|
|
15
|
+
├── builder/ → Fluent DSL (FlowChartBuilder, flowChart(), DeciderList, SelectorFnList)
|
|
16
|
+
├── scope/ → Per-stage facades + recorders + providers (largest module)
|
|
17
|
+
├── engine/ → DFS traversal + narrative + 13 handlers
|
|
18
|
+
├── runner/ → High-level executor (FlowChartExecutor)
|
|
19
|
+
└── contract/ → I/O schema + OpenAPI generation
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Dependency DAG: `memory ← scope ← engine ← runner`, `schema ← engine`, `builder (standalone) → engine`, `contract ← schema`
|
|
23
|
+
|
|
24
|
+
Two entry points:
|
|
25
|
+
- `import { ... } from 'footprintjs'` — public API
|
|
26
|
+
- `import { ... } from 'footprintjs/advanced'` — internals
|
|
27
|
+
|
|
28
|
+
## Key API
|
|
29
|
+
|
|
30
|
+
### Builder
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { flowChart, FlowChartBuilder } from 'footprintjs';
|
|
34
|
+
|
|
35
|
+
// flowChart(name, fn, id, buildTimeExtractor?, description?)
|
|
36
|
+
const chart = flowChart('Stage1', fn1, 'stage-1', undefined, 'Description')
|
|
37
|
+
.addFunction('Stage2', fn2, 'stage-2', 'Description')
|
|
38
|
+
.addDeciderFunction('Decide', deciderFn, 'decide', 'Route based on risk')
|
|
39
|
+
.addFunctionBranch('high', 'Reject', rejectFn)
|
|
40
|
+
.addFunctionBranch('low', 'Approve', approveFn)
|
|
41
|
+
.setDefault('high')
|
|
42
|
+
.end()
|
|
43
|
+
.setEnableNarrative()
|
|
44
|
+
.build();
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Methods: `start()`, `addFunction()`, `addStreamingFunction()`, `addDeciderFunction()`, `addSelectorFunction()`, `addListOfFunction()`, `addSubFlowChart()`, `addSubFlowChartNext()`, `loopTo()`, `setEnableNarrative()`, `setInputSchema()`, `setOutputSchema()`, `setOutputMapper()`, `build()`, `toSpec()`, `toMermaid()`
|
|
48
|
+
|
|
49
|
+
### Stage Functions
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
type PipelineStageFunction = (
|
|
53
|
+
scope: ScopeFacade,
|
|
54
|
+
breakPipeline: () => void,
|
|
55
|
+
streamCallback?: StreamCallback,
|
|
56
|
+
) => Promise<void> | void;
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### ScopeFacade
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
scope.getValue('key') // tracked read (appears in narrative)
|
|
63
|
+
scope.setValue('key', value) // tracked write
|
|
64
|
+
scope.updateValue('key', partial) // deep merge
|
|
65
|
+
scope.deleteValue('key') // tracked delete
|
|
66
|
+
scope.getArgs<T>() // frozen readonly input (NOT tracked)
|
|
67
|
+
scope.attachRecorder(recorder) // plug observer
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**IMPORTANT:** `getValue`/`setValue` are tracked. `getArgs()` is NOT tracked and returns frozen input.
|
|
71
|
+
|
|
72
|
+
### Executor
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
const executor = new FlowChartExecutor(chart);
|
|
76
|
+
await executor.run({ input: data, timeoutMs: 5000, signal: abortSignal });
|
|
77
|
+
|
|
78
|
+
executor.getNarrative() // combined flow + data narrative
|
|
79
|
+
executor.getNarrativeEntries() // structured entries with type/depth/stageName
|
|
80
|
+
executor.getFlowNarrative() // flow-only (no data ops)
|
|
81
|
+
executor.getSnapshot() // full memory state
|
|
82
|
+
executor.attachFlowRecorder(r) // plug flow observer
|
|
83
|
+
executor.setRedactionPolicy({}) // PII protection
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Two Observer Systems
|
|
87
|
+
|
|
88
|
+
Both use `{ id, hooks } → dispatcher → error isolation → attach/detach`. Intentionally NOT unified.
|
|
89
|
+
|
|
90
|
+
**Scope Recorder** (data ops — fires DURING stage execution):
|
|
91
|
+
- `onRead`, `onWrite`, `onCommit`, `onError`, `onStageStart`, `onStageEnd`
|
|
92
|
+
- Built-in: `NarrativeRecorder`, `MetricRecorder`, `DebugRecorder`
|
|
93
|
+
|
|
94
|
+
**FlowRecorder** (control flow — fires AFTER stage execution):
|
|
95
|
+
- `onStageExecuted`, `onNext`, `onDecision`, `onFork`, `onSelected`, `onSubflowEntry/Exit`, `onLoop`, `onBreak`, `onError`
|
|
96
|
+
- Built-in: 8 strategies (Narrative, Adaptive, Windowed, RLE, Milestone, Progressive, Separate, Manifest, Silent)
|
|
97
|
+
|
|
98
|
+
**CombinedNarrativeRecorder** implements BOTH interfaces. Auto-attached by `setEnableNarrative()`.
|
|
99
|
+
|
|
100
|
+
## Event Ordering
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
1. Recorder.onStageStart — stage begins
|
|
104
|
+
2. Recorder.onRead/onWrite — DURING execution (buffered per-stage)
|
|
105
|
+
3. Recorder.onCommit — transaction flush
|
|
106
|
+
4. Recorder.onStageEnd — stage completes
|
|
107
|
+
5. FlowRecorder.onStageExecuted — CombinedNarrativeRecorder flushes buffered ops
|
|
108
|
+
6. FlowRecorder.onNext/onDecision/onFork — control flow continues
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Anti-Patterns
|
|
112
|
+
|
|
113
|
+
- Never post-process the tree — use recorders
|
|
114
|
+
- Never use deprecated `CombinedNarrativeBuilder` — use `CombinedNarrativeRecorder`
|
|
115
|
+
- Don't extract shared base for Recorder/FlowRecorder — two instances = coincidence
|
|
116
|
+
- Don't use `getArgs()` for tracked data — use `getValue()`/`setValue()`
|
|
117
|
+
- Don't manually create `CombinedNarrativeRecorder` — `setEnableNarrative()` handles it
|
|
118
|
+
|
|
119
|
+
## Build & Test
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
npm run build # tsc (CJS) + tsc -p tsconfig.esm.json (ESM)
|
|
123
|
+
npm test # full suite
|
|
124
|
+
npm run test:unit
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Dual output: CommonJS (`dist/`) + ESM (`dist/esm/`) + types (`dist/types/`)
|
package/README.md
CHANGED
|
@@ -537,6 +537,54 @@ src/lib/
|
|
|
537
537
|
|
|
538
538
|
---
|
|
539
539
|
|
|
540
|
+
## AI Coding Tool Support
|
|
541
|
+
|
|
542
|
+
FootPrint ships with built-in instructions for every major AI coding assistant. Your AI tool understands the library's API, patterns, and anti-patterns out of the box.
|
|
543
|
+
|
|
544
|
+
### Quick setup
|
|
545
|
+
|
|
546
|
+
```bash
|
|
547
|
+
# After installing footprintjs, run:
|
|
548
|
+
npx footprintjs-setup
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
This interactive installer copies the right instruction files for your tool(s):
|
|
552
|
+
|
|
553
|
+
| Tool | What gets installed | Format |
|
|
554
|
+
|------|-------------------|--------|
|
|
555
|
+
| **[Claude Code](https://claude.com/claude-code)** | `.claude/skills/footprint/SKILL.md` + `CLAUDE.md` | Interactive skill + project rules |
|
|
556
|
+
| **[OpenAI Codex](https://openai.com/index/codex/)** | `AGENTS.md` | Agent instructions |
|
|
557
|
+
| **[GitHub Copilot](https://github.com/features/copilot)** | `.github/copilot-instructions.md` | Custom instructions |
|
|
558
|
+
| **[Cursor](https://cursor.com)** | `.cursor/rules/footprint.md` | Project rules |
|
|
559
|
+
| **[Windsurf](https://windsurf.com)** | `.windsurfrules` | Project rules |
|
|
560
|
+
| **[Cline](https://github.com/cline/cline)** | `.clinerules` | Project rules |
|
|
561
|
+
| **[Kiro](https://kiro.dev)** | `.kiro/rules/footprint.md` | Project rules |
|
|
562
|
+
|
|
563
|
+
Or install manually:
|
|
564
|
+
|
|
565
|
+
```bash
|
|
566
|
+
# Claude Code skill
|
|
567
|
+
mkdir -p .claude/skills/footprint
|
|
568
|
+
cp node_modules/footprintjs/ai-instructions/claude-code/SKILL.md .claude/skills/footprint/
|
|
569
|
+
|
|
570
|
+
# Cursor rules
|
|
571
|
+
mkdir -p .cursor/rules
|
|
572
|
+
cp node_modules/footprintjs/ai-instructions/cursor/footprint.md .cursor/rules/
|
|
573
|
+
|
|
574
|
+
# Any other tool — files are in node_modules/footprintjs/ai-instructions/
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
Every file teaches the AI assistant:
|
|
578
|
+
- The **Builder**, **Executor**, and **ScopeFacade** APIs
|
|
579
|
+
- The **recorder system** (scope + flow, two observer layers)
|
|
580
|
+
- The **core principle**: collect during traversal, never post-process
|
|
581
|
+
- **Anti-patterns** to avoid (deprecated APIs, wrong state access patterns)
|
|
582
|
+
- **Event ordering** that makes inline narrative collection work
|
|
583
|
+
|
|
584
|
+
This means any AI coding tool can help you build flowchart pipelines correctly from day one.
|
|
585
|
+
|
|
586
|
+
---
|
|
587
|
+
|
|
540
588
|
## License
|
|
541
589
|
|
|
542
590
|
[MIT](./LICENSE) © [Sanjay Krishna Anbalagan](https://github.com/sanjay1909)
|