Files
Aura/docs/design/contracts/c06-firing-policy.md
T
claude 8688a60ded docs(ledger): split the design ledger into an INDEX map, per-contract live files, and history sidecars
The single-file ledger had grown to 2968 lines / ~42k tokens, mixing
current design law with accreted history: 59 cycle-stamped realization
blocks, 18 [HISTORY] passages, 22 supersession markers, and the C10 /
C22 / C24 reframe sagas layered several supersessions deep. A
code-grounding audit (31 agents, adversarially verified) confirmed 11
defects stated as current truth: stale crate homes from the C28 #288
roster split (cost nodes, PositionManagement, PositionEvent, Session),
the renamed InputSpec->PortSpec, the pre-#241 project model in C16 and
the open-threads section, a stale HarnessKind retirement deferral in
C24, and three C28-internal inconsistencies.

New shape, per the ailang precedent:

- INDEX.md stays the sole addressable entry point: foundation, external
  components, a C-id-keyed contract map (one line per contract), and
  only the genuinely open architectural threads.
- contracts/cNN-<slug>.md carries each contract's current truth only:
  Guarantee / Forbids / Why with ratified refinements integrated, plus
  a code-anchored Current state. All confirmed defects are fixed here;
  crate anchors were re-verified against the tree.
- contracts/cNN-<slug>.history.md (18 sidecars) and INDEX.history.md
  preserve every superseded block verbatim, stamps and issue refs
  intact, under a frozen-record banner. Nothing was deleted: superseded
  design intent remains an addressable working-tree artifact, off the
  per-cycle audit walk.
- Ledger discipline is now stated in INDEX.md: live files are edited in
  place at cycle close, superseded text moves verbatim to the sidecar,
  and a supersession marker in a live file is itself an audit finding.

Every contract file was verified against its old text by an independent
zero-loss pass (statement-by-statement) plus a code-accuracy spot check;
C-ids and contract titles are unchanged, so existing C-id citations in
code, tests, and issues resolve as before.
2026-07-21 16:40:36 +02:00

43 lines
2.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# C6 — Firing policy A and B, per input group
**Guarantee.** A node declares, per input group, one of two firing policies:
**A** fire-on-any-fresh + hold (latest / as-of join — e.g. tick × held
daily-bias); **B** all-fresh barrier (synchronizing join — e.g. O/H/L/C from
four separate 15m sources: the candle is complete only when all four are fresh).
A single node may mix an A input and a B group, and it fires when **any** of its
input groups fires (OR over groups).
**Forbids.** A single global firing mode; forcing per-node-only granularity.
**Why.** Both are genuinely needed; RustAst, the retired predecessor, implemented
only B. Per-input-group granularity is required by the OHLC-plus-bias case where
one node needs both an A input and a B group at once.
## Current state
Firing is tagged per input — `Firing::{Any, Barrier(u8)}`
(`crates/aura-core/src/node.rs`) carried on each input's `PortSpec.firing`, not a
separate group object. Inputs sharing a `Barrier` id form a group; a mode-A input
is its own trivial group, so "per input group" and the per-input tag coincide.
The barrier's synchronization token is the cycle **timestamp**, not the
`cycle_id`: under C4 four same-timestamp sources are four distinct cycles, so a
`cycle_id`-equality barrier could never fire across them — the token has to be the
data timestamp of the push.
Firing is evaluated by `fires()` in `crates/aura-engine/src/harness.rs`: a mode-A
input fires the node when it is fresh this cycle (`fresh_at == cycle_id`), a stale
input contributing its held value; a barrier group fires when ≥1 member is fresh
this cycle **and** every member's last push carries the current cycle's timestamp.
The "≥1 fresh" guard is what stops a group completed in a prior cycle from
re-firing. This one rule fires both the multi-source bar and the within-source
diamond rejoin (C3), since every push in a cycle carries that cycle's timestamp.
## See also
- [C3](c03-single-merge.md) — the one-merge boundary; the within-source diamond rejoin the barrier also completes
- [C4](c04-cycle-granularity.md) — cycle/timestamp granularity that forces the barrier token to be a timestamp
- [C5](c05-freshness-gating.md) — freshness-gated recompute and sample-and-hold (mode A's hold semantics)
- [C8](c08-node-contract.md) — the node signature declares each input's firing group
> History: [c06-firing-policy.history.md](c06-firing-policy.history.md)