Stamped system views
- Status
- as-built snapshot, with direction marked
- Layers
- all
- Source
- architecture section 3, section 3.5, section 5
These are the system views (SYS-00 to SYS-09) and the stamped-external views (EXT-01 to EXT-05), redrawn in house style. They replace the archify HTML set, which is now archived. Built and partial labels follow the archify pins (stamped-external a4c91bc; L1E 332ec0d, L1C d63ee46, L2 6c8d454, L3C 5c74aee, L4 708b1f4, L5 88fe58f, L6 82df09e). For the current as-built state read l4/30-as-built.md and l4/24-architecture-gaps.md; for the target shape read the architecture.
No integration is live at any customer plant. Verified savings to date: ₹0.
Legend for every view: yellow is governance or a contract gate, blue is a person or an agent, green is a return path or loop. A dotted arrow is a hop that is designed or deferred, not built.
SYS-00 End-to-end map#
How to read it.
- Data in: L1 wraps a plant reading in an envelope and L2 ingests it; contracts define every hop.
- Detect: L3 reads L2 and emits Finding 1.2.0; the hot path uses suppression then lane, not eval gates.
- Decide: the L4 runtime is built and runs, but its proposals land in StubCardSink; the hop to an L5 live card is missing (L5-G4), so no decision reaches an owner yet.
- Close: L5 workflow and M&V write the ledger; L6 polls L5 (the webhook is designed).
Build now: the L4 to L5 card hop. Later: the conceptual-layer view in architecture section 3.
View Mermaid source
flowchart TB
%% house-style: sys-00-end-to-end
l0["L0 Plant: OT meters (partial)"]
subgraph cloud["Stamped cloud: repo layers L1 to L6"]
direction LR
l1["L1 Connect: edge and cloud (partial)"]
l2["L2 Store: TimescaleDB (built)"]
l3["L3 Findings: on-demand runs (partial)"]
l4["L4 Decisions: runtime built, output stubbed"]
l5["L5 Closure: no /cards ingest (partial)"]
l6["L6 Control room: polls L5 (partial)"]
end
sink["StubCardSink: local only, emit off"]
con{{"Contracts SSOT: stamped-external"}}
l0 -->|"MQTT stamped/v1"| l1 -->|"envelope ingest"| l2 -->|"query-api reads"| l3 -->|"Finding 1.2.0"| l4
l4 -->|"proposal (today)"| sink
l4 -.->|"card proposal (designed, not live)"| l5
l5 -->|"closure and ledger"| l6
con -.-> l2 & l4
classDef govc fill:#fff4d6,stroke:#c99a2e,color:#000
classDef agentc fill:#e8f0ff,stroke:#5b7bd5,color:#000
classDef loopc fill:#eef7ee,stroke:#4f9a4f,color:#000
class con govc
SYS-01 Contract and boundary map#
How to read it.
- Envelope plus telemetry, context and bill schemas cross into L2 ingest.
- Finding 1.2.0 and the
l3-methodsOpenAPI carry L3 output to L4; the card proposal into L5 is designed only. - Transport is HTTP (OpenAPI) and MQTT (
TOPICS.md); there is no cross-layer database; L5 to L6 HMAC push is designed and L6 polls/v1/eventstoday.
Build now: the card proposal hop. Later: the ten contracts of architecture section 5.
View Mermaid source
flowchart TB
%% house-style: sys-01-contract-boundary
subgraph in["L1 to L2"]
direction LR
l1["L1 publish (partial)"] --> env{{"envelope (built)"}} --> l2["L2 /v1/ingest (built)"]
end
subgraph dec["L3 to L6"]
direction LR
l3["L3 core (partial)"] --> fin{{"Finding 1.2.0 (built)"}} --> l4["L4 runtime (built, stub out)"]
l4 -.-> card{{"card proposal (designed, no L5)"}} -.-> l5["L5 workflow (partial)"] --> l6["L6 BFF (polls)"]
end
l2 --> l3
classDef govc fill:#fff4d6,stroke:#c99a2e,color:#000
classDef agentc fill:#e8f0ff,stroke:#5b7bd5,color:#000
classDef loopc fill:#eef7ee,stroke:#4f9a4f,color:#000
class env,fin,card govc
SYS-02 Data batch to decision#
How to read it.
- The edge agent buffers in SQLite until the MQTT QoS1 ack, then marks rows sent.
- An L5 perception call or the CLI starts a detection run; the scheduler is built but not deployed.
- The relay into the L4 inbox is a CLI drain; default compose does not start the relay worker.
Build now: a deployed relay worker and the L5 card hop. Later: the fast-loop path in fast-loop/.
View Mermaid source
flowchart TB
%% house-style: sys-02-batch-runtime
subgraph edge["Edge to cloud"]
direction LR
ea["edge-agent: PLC poll, SQLite buffer (built)"] -->|"publish batch, MQTT QoS1"| c1["L1 cloud (partial)"] -->|"relay ingest"| s2["L2 ingest"]
end
subgraph det["Detection and decision"]
direction LR
d3["L3 detect run (partial)"] -->|"Finding out"| ob["L3 outbox relay (built)"]
ob -.->|"relay_once to inbox (CLI)"| r4["L4: inbox, PlantWorkQueue, worker, stages, DecisionTrace"]
r4 -->|"write proposal"| sk["StubCardSink (emit off)"]
end
s2 --> d3
back(["↩ backlog drains after an outage; unsent rows not expired in code"])
ea --- back
classDef govc fill:#fff4d6,stroke:#c99a2e,color:#000
classDef agentc fill:#e8f0ff,stroke:#5b7bd5,color:#000
classDef loopc fill:#eef7ee,stroke:#4f9a4f,color:#000
class back loopc
SYS-03 Ask question and discovery request#
How to read it.
- Ask is live and read-only; it never emits a card.
- A discovery request is queued as
ask_sweepand run by the worker; it finds nothing until Ask sendsscanner_context(L4-G11). - Open gaps: Ask reads cards and PSM from fixture ports (L4-G12); Ask and the runtime keep separate hard-stop lists (L4-G13); API and worker must share
L4_DATABASE_URL; memory is off unlessL4_MEMORY=hindsight.
Build now: scanner_context and one hard-stop list. Later: Ask over the Layer 2 store per architecture section 3.
View Mermaid source
flowchart TB
%% house-style: sys-03-ask-runtime
op(["Operator"])
subgraph l6["L6"]
direction LR
web["L6 web: SSE (partial)"] --> bff["L6 BFF: POST /analyst stream"]
end
subgraph l4["L4"]
direction LR
hub{{"AskHub: gate, route (SSE v2)"}} --> loop["ReAct loop over 35 read tools, per-claim verifier"]
loop -->|"ask_sweep, deduped per asset"| q["Work queue"] --> w["Runtime worker: sweep flags"]
end
op --> web
bff -->|"POST /v1/chat stream"| hub
ret(["↩ verified claims, then token, citation, done, back to the UI"])
loop --> ret --> web
classDef govc fill:#fff4d6,stroke:#c99a2e,color:#000
classDef agentc fill:#e8f0ff,stroke:#5b7bd5,color:#000
classDef loopc fill:#eef7ee,stroke:#4f9a4f,color:#000
class hub govc
class op,loop agentc
class ret loopc
SYS-04 Card closure and M&V#
How to read it.
- The owner marks a card done in L6; L5 records the workflow event.
- The L5 worker reads L2 evidence (fixture by default) and appends a ledger row on
ops_confirmedonly. - The ledger is not bill-verified; ADR-014 keeps the bill path deferred.
Build now: real L2 evidence reads. Later: ValueRecord and the 11 ClosureState values (architecture section 5).
View Mermaid source
flowchart TB
%% house-style: sys-04-closure-mv
own(["Owner"])
subgraph act["Owner acts"]
direction LR
ux["L6 UX: polls every 30 s"] -->|"workflow event"| api["L5 API: ack, done"]
end
subgraph clr["Clearance"]
direction LR
wk["L5 worker: clearance_poll"] -.->|"read window (fixture default)"| ev["L2 evidence (partial)"]
wk -->|"ops_confirmed"| led{{"Ledger append: not bill-verified"}}
end
own -->|"mark done"| ux
api --> wk
st(["↩ status poll back to L6"])
api --> st --> ux
classDef govc fill:#fff4d6,stroke:#c99a2e,color:#000
classDef agentc fill:#e8f0ff,stroke:#5b7bd5,color:#000
classDef loopc fill:#eef7ee,stroke:#4f9a4f,color:#000
class led govc
class own agentc
class st loopc
SYS-05 Operating loop across layers#
How to read it.
- A person gates at assign and at act.
can_emitis the L4 CardSink guard between recommend and assign, not an L3 detect gate.- The learn hop is designed; the evals Lab never auto-promotes to production; precision and PSI are eval-only.
Build now: assign through a live card. Later: the eight-step loop in architecture section 17.
View Mermaid source
flowchart TB
%% house-style: sys-05-operating-loop
subgraph loop["Product loop"]
direction LR
ing["Ingest: L1 to L2 (built)"] --> det["Detect: suppression then lane (partial)"] --> rec["Recommend: runtime (built)"]
rec -.->|"can_emit"| asg{{"Assign: no live L4 card (partial)"}} --> act{{"Act: UX (partial)"}} --> ver["Verify: ops_confirmed only (built)"]
end
lrn(["↩ Learn: L5 to L4 (designed)"])
ver -.-> lrn -.-> rec
classDef govc fill:#fff4d6,stroke:#c99a2e,color:#000
classDef agentc fill:#e8f0ff,stroke:#5b7bd5,color:#000
classDef loopc fill:#eef7ee,stroke:#4f9a4f,color:#000
class asg,act govc
class lrn loopc
SYS-06 Life of one plant condition#
How to read it.
- In L3 a candidate becomes an emitted Finding or stays
lab_only; certification shadow fails closed. - An L4 DecisionCase becomes an immutable proposal; the live-card hop is designed.
- Clearance appends to the ledger on
ops_confirmed.
Build now: the live-card hop. Later: the full ClosureState machine.
View Mermaid source
flowchart TB
%% house-style: sys-06-condition-lifecycle
subgraph l3["L3 Finding rail"]
direction LR
cand["Candidate (shadow)"] --> emit["Emitted Finding, or lab_only"]
end
subgraph l45["L4 and L5"]
direction LR
prop["Proposal: immutable"] -.->|"designed hop"| live["Live card"] --> clr{{"ops_confirmed: ledger append"}}
end
emit --> prop
classDef govc fill:#fff4d6,stroke:#c99a2e,color:#000
classDef agentc fill:#e8f0ff,stroke:#5b7bd5,color:#000
classDef loopc fill:#eef7ee,stroke:#4f9a4f,color:#000
class clr govc
SYS-07 Deployment and trust boundaries#
How to read it.
- Nothing connects inbound to the plant OT network; secrets stay in cloud vaults.
- L5 notify logic is WhatsApp first, SMS fallback, but the API wires FakeMeta and FakeSms, so no real messages leave L5.
- L6 verifies the Meta webhook HMAC; the inbound button mapping is a stub and the BFF still polls L5.
Build now: real senders behind one budget. Later: the Plant Box and its writer (architecture section 7).
View Mermaid source
flowchart TB
%% house-style: sys-07-deployment-trust
subgraph plant["Plant networks"]
direction LR
ot["Plant OT net (pilot)"] --- ea["edge-agent: outbound only"]
it["Plant IT net: context"]
end
subgraph sc["Stamped managed cloud"]
direction LR
vpc{{"Stamped cloud VPC: X-Service-Key"}} --> svc["L2 and L3 to L6 services"]
end
llm["LLM providers: L4 seam"]
wa["WhatsApp then SMS: fake clients on main"]
ea -->|"MQTT egress"| vpc
it -->|"context HTTP"| vpc
svc -->|"provider API keys"| llm
svc --> wa
classDef govc fill:#fff4d6,stroke:#c99a2e,color:#000
classDef agentc fill:#e8f0ff,stroke:#5b7bd5,color:#000
classDef loopc fill:#eef7ee,stroke:#4f9a4f,color:#000
class vpc govc
SYS-08 Built versus designed#
How to read it.
- Partial means the code exists but is not wired.
- Bill reconcile runs only against FixtureBillClient; no savings are verified against a real bill.
- The full gap list is
l4/24-architecture-gaps.md.
Build now: L5 /cards. Later: the bill path, if ADR-014 reopens.
View Mermaid source
flowchart TB
%% house-style: sys-08-built-vs-designed
subgraph built["Mostly built: on main with tests, not live"]
direction LR
ea["edge-agent"] --> l2["L2 store"]
cx["context-agent (L1E IT)"] -.-> l2
m3["L3 methods :8094"] --> r4["L4 runtime (memory partial)"]
end
subgraph des["Partial, designed or deferred"]
direction LR
ps["PathScheduler: built, not deployed (L3C-G5)"]
cp["L1C context poller: off"]
cards{{"L5 /cards ingest: designed"}}
bill{{"Bill verified: deferred, fixtures only"}}
hs["Hindsight memory: opt-in"]
end
l2 --> ps
r4 -.-> cards
classDef govc fill:#fff4d6,stroke:#c99a2e,color:#000
classDef agentc fill:#e8f0ff,stroke:#5b7bd5,color:#000
classDef loopc fill:#eef7ee,stroke:#4f9a4f,color:#000
class cards,bill govc
SYS-09 Evidence and money lineage#
How to read it.
- Evidence tiers are Measured, Confirmed, Modeled and Unknown.
- A rupee estimate comes only from an L3
calculator_ref; no layer invents rupees. - A realised row is appended only by L5 after
ops_confirmed; verified savings today are ₹0.
Build now: the live-card link. Later: ValueRecord with named evidence (architecture section 5).
View Mermaid source
flowchart TB
%% house-style: sys-09-money-lineage
subgraph est["Modeled estimate"]
direction LR
tel["Telemetry (L2)"] --> calc{{"L3 calculator_ref: only source of a rupee estimate"}}
tar["Tariff (L2)"] --> calc
calc --> fe["Finding estimate: Modeled tier"] --> c4["L4 card cites the ref"]
end
subgraph real["Realised ledger"]
direction LR
lc["Live card (partial)"] --> mv["L5 M&V worker"] --> led{{"Ledger append: L5 is the only writer"}}
end
c4 --> lc
l6(["↩ L6 shows the claim status sanitised"])
led --> l6
classDef govc fill:#fff4d6,stroke:#c99a2e,color:#000
classDef agentc fill:#e8f0ff,stroke:#5b7bd5,color:#000
classDef loopc fill:#eef7ee,stroke:#4f9a4f,color:#000
class calc,led govc
class l6 loopc
EXT-01 The stamped-external pack#
How to read it.
- The master document and ADRs set the rules;
technical/andcontracts/encode the stack and the wire shapes. - CI gates a merge before layer repos bump their
external/pin (ADR-009). - This repo is docs and contracts only.
Build now: keep CI green before every tag. Later: none.
View Mermaid source
flowchart TB
%% house-style: ext-01-ssot-pack
subgraph pack["stamped-external: docs and contracts, no runtime server"]
direction LR
md{{"Master document"}} --> adr["decisions/: ADRs"] --> tech["technical/: architecture and deep docs"]
tech --> con["contracts/: schemas, fixtures, OpenAPI, tools, TOPICS.md"]
tech --> ho["handoff/: cross-repo hops"]
ci{{"CI: contract-check.sh, identity lint, check_docs"}}
end
rep["Layer repos: external/ submodule pin"]
ci -->|"tag after green CI"| rep
classDef govc fill:#fff4d6,stroke:#c99a2e,color:#000
classDef agentc fill:#e8f0ff,stroke:#5b7bd5,color:#000
classDef loopc fill:#eef7ee,stroke:#4f9a4f,color:#000
class md,ci govc
EXT-02 How a contract changes#
How to read it.
- A schema mismatch starts a PR, with an ADR when the change is normative.
scripts/contracts/contract-check.shgates the merge; the tag triggers submodule bump PRs.- Consumers dual-read, then drop deprecated shapes, for example
prescription.json1.0.0 beside the card proposal.
Build now: dual-read for every breaking bump. Later: a CI state machine for removal.
View Mermaid source
flowchart TB
%% house-style: ext-02-contract-change
subgraph edit["Propose and edit"]
direction LR
pr["Author PR"] -->|"links ADR when normative"| adr["ADR note"] --> sch["Edit schema and CHANGELOG, semver bump"]
end
subgraph main["Validate on main"]
direction LR
chk{{"contract-check.sh"}} -->|"merge, tag"| tag["Tag release: VERSION and CHANGELOG"] --> bump["Layer repos bump external/"]
end
sch --> chk
dual(["↩ dual-read window, then drop the old parser"])
sch -.-> dual
classDef govc fill:#fff4d6,stroke:#c99a2e,color:#000
classDef agentc fill:#e8f0ff,stroke:#5b7bd5,color:#000
classDef loopc fill:#eef7ee,stroke:#4f9a4f,color:#000
class chk govc
class dual loopc
EXT-03 Contract catalog: producers and consumers#
How to read it.
- L2 ingest validates the envelope and telemetry and plant schemas (ADR-019).
- L4 consumes Finding and emits the card proposal;
prescription.json1.0.0 is dual-read. - Seven families plus OpenAPI, tools and
TOPICS.mdmake up the catalog:contracts/README.md.
Build now: L5 ingest of the card proposal. Later: the direction contracts of architecture section 5.
View Mermaid source
flowchart TB
%% house-style: ext-03-contract-catalog
subgraph fam1["L1 to L2 families"]
direction LR
l1["L1 connectors"] --> env{{"envelope/*"}} --> l2["L2 ingest (ADR-019)"]
end
subgraph fam2["Finding to card proposal"]
direction LR
l3["L3 intelligence"] --> fin{{"intelligence/*: Finding 1.2.0"}} --> l4["L4 runtime: tools"]
end
cons(["↩ L5 closure and L6 BFF consume DTOs from the catalog; never redefine them"])
l4 --> cons
classDef govc fill:#fff4d6,stroke:#c99a2e,color:#000
classDef agentc fill:#e8f0ff,stroke:#5b7bd5,color:#000
classDef loopc fill:#eef7ee,stroke:#4f9a4f,color:#000
class env,fin govc
class cons loopc
EXT-04 Authority order when docs disagree#
How to read it.
- On a meaning conflict the earlier node wins; the master document wins on identity.
- The architecture holds the technical shape; open choices live only in the decision board.
- Contracts are wire truth;
scripts/vision-identity-lint.ps1blocks withdrawn identity on PRs.
Build now: follow this order. Later: none.
View Mermaid source
flowchart TB
%% house-style: ext-04-authority-order
subgraph id["Identity"]
direction LR
md{{"Master document"}}
end
subgraph tech["Architecture"]
direction LR
arch["technical/STAMPED_ARCHITECTURE.md"] --> dec["technical/DECISIONS.md"] --> deep["technical/ deep docs"]
end
subgraph wire["Build"]
direction LR
ho["handoff/"] --> con["contracts/: wire truth"] --> lint{{"identity lint: PR gate"}}
end
md --> arch
deep --> ho
classDef govc fill:#fff4d6,stroke:#c99a2e,color:#000
classDef agentc fill:#e8f0ff,stroke:#5b7bd5,color:#000
classDef loopc fill:#eef7ee,stroke:#4f9a4f,color:#000
class md,lint govc
EXT-05 Contract version lifecycle#
How to read it.
- Draft plus fixtures must pass
contract-check.sh; the CHANGELOG records semver and the dual-read policy. - A new emit uses the new schema while the old file stays dual-read.
- Removal is policy only; no CI state machine enforces it yet.
Build now: record every deprecation in contracts/CHANGELOG.md. Later: automated removal.
View Mermaid source
flowchart TB
%% house-style: ext-05-contract-lifecycle
subgraph life["Lifecycle"]
direction LR
dr["Draft: PR"] --> rv{{"CI review: contract-check.sh"}} -->|"merge"| ac["Active: default"]
ac -.->|"dual-read"| dp["Deprecated"]
end
rm(["↩ removed after consumers drop parsers (policy in CHANGELOG, designed)"])
dp -.-> rm
classDef govc fill:#fff4d6,stroke:#c99a2e,color:#000
classDef agentc fill:#e8f0ff,stroke:#5b7bd5,color:#000
classDef loopc fill:#eef7ee,stroke:#4f9a4f,color:#000
class rv govc
class rm loopc
Page history: last 2 changes
- docs: keep agents out of archive; changelog; final check suite
fd7f122 - docs(technical): archive archify; add SYSTEM_VIEWS.md house diagrams; check_docs --min
1e190b6