footprintjs logo

The Flowchart Pattern.

How a whiteboard sketch becomes software that explains itself.

footprintjs · the self-explaining stack
IT STARTS ON A WHITEBOARD

Every system begins as a drawing.

Start
Validate
Decide
Approve
Reject
Boxes for steps. Arrows for what happens next.
ONE PICTURE, EVERY ROLE

A PM, an engineer, and a new hire all understand it.

Start
Validate
Decide
Approve
Reject
Product
Manager
Engineer
Support
New dev
No one needs to read the code to follow the logic.
THEN WE CODE IT

But the code doesn't look like the drawing.

Product
Manager
Engineer
Support
New dev
Start
Validate
Decide
Approve
Reject
approval.service.ts
function handle(req) {
  const ctx = load(req)
  let score = 0
  for (const r of RULES)
    if (r.match(ctx)) score += r.weight
  if (score >= T || !ctx.valid)
    return deny(reason(score))
  queue.push(ctx.id)
  return ok(sign(ctx))
}
The map and the territory drift apart.
SIX MONTHS LATER

“Why did it do that?”

Start
Validate
Decide
Approve
Reject
?
14:22:07.118 INFO load ctx id=8841
14:22:07.142 WARN rule miss r=7
14:22:07.143 INFO risk=7 limit=10
14:22:07.144 approve 8841 · why??
audit.log(8841, approve)
… 2,193 more lines
Product
Manager
Engineer
Support
New dev
The drawing is gone; the answer is buried in logs.
THE IDEA

What if the code were the flowchart?

Product
Manager
Engineer
Support
New dev
Start
Validate
Decide
Approve
Reject
review.flow
function start(ctx)
function validate(ctx)
function decide(ctx)
function approve(ctx)
function reject(ctx)
One artifact. Drawn and run.
BUILD IT THE WAY YOU DREW IT

The thing that runs is the thing you read.

Product
Manager
Engineer
Support
New dev
Startstart()
Validatevalidate()
Decidedecide()
Approveapprove()
Rejectreject()
review.flow
function start(ctx)
function validate(ctx)
function decide(ctx)
function approve(ctx)
function reject(ctx)
No translation, no drift.
COLLECT AS IT RUNS

Every run records itself.

Product
Manager
Engineer
Support
New dev
Startstart()
Validatevalidate()
Decidedecide()
Approveapprove()
Rejectreject()
footprint · run 4f2a
startctx 8841
validaterules ok
deciderisk 7 < 10
approvesigned
Captured as it happens — not reconstructed from logs after.
TRACE ANY ANSWER BACK

Walk back to the exact cause.

Product
Manager
Engineer
Support
New dev
Startstart()
Validatevalidate()
Decidedecide()
Approveapprove()
Rejectreject()
why approve 8841?
startctx 8841
validaterules ok
deciderisk 7 < 10
approvesigned
Ask “why did it do that?” and follow the footprints to the source.
ONE RECORD, YOUR VIEW

Everyone picks their lens.

Product
Manager
Engineer
Support
New dev
Startstart()
Validatevalidate()
Decidedecide()
Approveapprove()
Rejectreject()
MANAGER · metric
Approved4 steps · 1.8 ms
risk 7 · limit 10
PRODUCT · narrative
Request 8841 was approved because its risk score of 7 stayed under the limit of 10.
ENGINEER · flowchart
start
→
validate
→
decide
→
approve
One trustworthy record, many ways to read it.
BACKEND → AI AGENTS

The same pattern wraps an AI agent.

request
LLMreason()
Toolsact()
answer
agentfootprint · run a17c
llm“check policy 8841”
toollookupPolicy → allow
llm“allowed → approve”
toolapprove(8841)
The hardest “why did it do that?” — answered by construction.
ONE IDEA, A WHOLE STACK

Built on the pattern.

powers
renders
renders
replays
footprintjs
core engine
agentfootprint
agentic framework
Flow Lens
renders any flow
Lens
agent runs, visual
Story Lens
replays reasoning
Core engine → agentic framework → the UIs that show it.
footprintjs logo

The self-explaining stack.

From a backend pipeline to an AI agent — every run records why it did what it did.

footprintjs.github.io→
draw it · run it · explain it