Version. v0.1
Date. 2026-07-30
Status. Read-only verification. Nothing committed, nothing edited in either source repo. Four questions answered against the specs as they sit on disk today, with file + section citations for every claim.
Sources read. ~/stele-agentic-id/spec/stele-agentic-id-spec_V12.md (V1, frozen), ~/stele-agentic-id/spec/v2/stele-agentic-id-v2-spec-draft-v0_4.md (V2, draft), plus the V1 seam artifacts verdict-interface.md, event-taxonomy.md, WIRE-FREEZE-v1_0.md; ~/grantha/design/GRANTHA_GRANT_CHECK_CONTRACT-v0_2.md and GRANTHA_POLICY_DSL_SCOPE-v0_1.md, with ~/grantha/discovery/GRANTHA_DISCOVERY_RECORD-v0_14.md and ~/grantha/governance/GRANTHA_RATIFICATION_LEDGER-v0_3.md for status.
Scope caution. This document reports what the specs say. It does not assess Loomworks against any contract, and it endorses no design. Where a spec is silent, that is reported as silence, not inferred.
| Specification | Version | Date | Status on disk |
|---|---|---|---|
| Stele Agentic ID V1 | V12 (supersedes V11; correction-only, no behavioral change) | 2026-07-13 (V12 change note) | Frozen. Wire formats frozen separately at v1.0, dated 2026-07-09, repo main at b9dea23 (WIRE-FREEZE-v1_0.md, Declaration) |
| Stele Agentic ID V2 | v0.4 spec draft (supersedes v0.3) | 2026-07-16 | Draft. Governing ratification artifact is the V2 Ratification Sheet v0.2, 2026-07-16 |
| GRANTHA | No single "spec" exists. The governing set is: Discovery Record v0.14, 2026-07-15; Grant-Check Contract v0.2, 2026-07-12; Policy DSL Scope v0.1, 2026-07-12; Ratification Ledger v0.3, 2026-07-15 | as listed | All four self-describe as uncommitted (design draft / governance record) |
Three status facts that qualify every GRANTHA answer below:
It roots in a creation event — and the creation event is durably recorded before the identity is usable — but verification does not read that record. The two halves of the model answer differently, and conflating them is the trap here.
V12 §Phase 1, REQ-013: registration "stores a new principal row with a UUIDv4 identifier, a bound Ed25519 public key, and nature autonomous." REQ-021 makes registration a witnessed event: "every register, rotate, revoke, and allocate operation appends an event to a durable WAL, written and flushed before the operation's response is returned."V12 §Phase 2, REQ-025: the mint operation "creates a derived credential by signature only: a new UUIDv4, a new Ed25519 keypair, chain extension from the issuing credential… a stamped counter." REQ-027: "The signing SDK appends each mint event to a durable WAL, written and flushed before the mint operation returns." The taxonomy names it: mint.issued — "a credential minted by signature" (event-taxonomy.md §event table).V12 §Scope states the Observance Law from the OQ-1 resolution: "minting authority is contingent on being observed; no witness, no mint." An unobserved creation is not a weak identity — it is not a creation. REQ-079 gives it teeth after the fact: a mint whose issuing key has no covering delegation record in any commitment is flagged OFF_BOOKS_MINT.
So there is no "identity by first assertion" path. There is no way to bootstrap a principal by simply asserting one; every principal traces to either a registry register (root) or a signed mint (derived), and both write a durable creation record before returning.
The chain walk does not consult the creation record. V12 REQ-036: "one signature verification per hop plus one statement signature verification, totaling depth plus one signature operations." The authority the walk terminates in is the current registry statement — status, key mode, registered operational credentials, allocated ranges, optional depth bound (REQ-011) — issued fresh with a 60-second TTL (REQ-017) and evaluated at verification time (REQ-039: "The effective depth bound is evaluated at verification time as the minimum of the current statement's depth_bound and 8").
The creation events live on the audit side: WAL → deterministic bundling → signed lean commitments → Reconciler (V12 §Scope, Domains 3 and 5). The Reconciler is what binds an identity back to its recorded birth (REQ-079, REQ-096), and it runs event-driven, after the fact — not in the verify path.
Net for agent construction. Construction is a first-class recorded event with a durability guarantee attached (REQ-027, REQ-021), which is what a construction-provenance claim needs. What it does not give you is a verifier that will confirm at check time that a given agent was constructed under given conditions — the verifier confirms signatures plus current root state. Binding a construction fact to a verification-time decision requires either the attested-mode co-signature (§2 below) or a Reconciler finding, and the Reconciler is detection, not prevention. V12 §Constraints says as much about the near neighbour: the sibling-overlap residual "is a Reconciler catch by design."
Only by collapsing it into an existing input. The verdict model has no birth-verification field, and its input set is closed by requirement.
Attested-mode minting is exactly signature-verified-at-birth, and it is in the frozen wire format:
V12 REQ-093: a witnessing environment in attested mode "additionally co-sign[s] each mint with its registered operational credential, the co-signature riding in the child's credential."V12 REQ-004 (credential schema, frozen per WIRE-FREEZE-v1_0 §1): witness_sig (nullable, present when minted in an attested-mode environment) and attestation_required (boolean, true when minted in an attested-mode environment).V12 REQ-094: in attested mode the verifier rejects a derived credential lacking a valid co-signature with UNWITNESSED_MINT.V12 REQ-100 closes the downgrade path fleet-wide: "a credential marked attestation_required that any verifier receives is rejected without a valid witness_sig regardless of that verifier's local mode."That is a durable, wire-carried, verifier-enforced birth attestation. It survives the freeze.
V12 REQ-068 is the binding constraint: "Verdict computation inputs exclude behavioral payload fields: the verdict function consumes credential validity, heartbeat recency, challenge outcomes, and detection events only," with the acceptance test asserting the input schema contains no field outside that set.verdict-interface.md §The four verdicts states the evidence predicates in the same four terms: chain to a live unrevoked root, counter within pre-allocation, current signed heartbeat / challenge-response.V12 REQ-065 maps them: VERIFIED for a valid chain with current heartbeats; STALE after two missed intervals; SUSPECT on failed challenge or counter-anomaly detection event; DEAD on expiry or revocation.So a birth attestation reaches a verdict along exactly two channels, both lossy:
witness_sig on an attestation_required credential fails the chain walk (REQ-100), so the credential is invalid and the verdict follows. The verdict says "not valid"; it does not say "not attested at birth."OFF_BOOKS_MINT (REQ-079, event-taxonomy.md §finding names) reaches the verdict function through the detection-event input and yields SUSPECT (REQ-065, and verdict-interface.md §SUSPECT names "an off-books mint" explicitly as evidence contradiction).
Both are present-tense collapses. The four-verdict vocabulary is fixed (REQ-058, verdict-interface.md), and no verdict distinguishes attested at birth from verifies right now. There is no positive verdict a consumer can read as "this agent's construction was signature-witnessed."
And the consumer side is open. verdict-interface.md §Consequence half — OPEN: "The consequence half is deliberately open… No placeholder consequence is invented here." V2 does not close it — V2 v0.4 §Exclusions: "No verdict-to-consequence binding (blocked on GRANTHA pending-state semantics; carried as Assumption A2)." So even a birth fact that does reach a verdict has no specified consequence mapping today.
Net. Signature-verified-at-birth is expressible as an enforcement (attested mode, and it is strong — REQ-100 is fleet-wide and fail-closed). It is not expressible as a distinct verdict input or output. Any construction-integrity claim built on the verdict channel is asking the verdict model to carry a distinction REQ-068 forbids it from carrying. Making it first-class means a new verdict input, which means reopening REQ-068 and the verdict interface — a V3-class change, not a V2 amendment (V2 v0.4 §Exclusions: "No wire changes: WIRE-FREEZE-v1_0 stands").
No — not per-delegation. Depth carries a single system-wide/per-root ceiling, evaluated at verification time from the root's current statement. A parent cannot impose a tighter generation limit on its own subtree. This is the sharpest negative finding in this verification, and it is sharper because the neighbouring mechanism (counter ranges) does nest.
V12 §Glossary: "Hop: one signature link in a credential chain; kind is operational or mint; depth counts every hop."V12 §Scope (ratified H1): "depth counts every signing hop including the operational hop; totals default 4, hard maximum 8."V12 REQ-006: "a credential's depth field equals chain length plus one, every hop's stamped depth equals its chain position plus one."V12 REQ-092: "A root's non-default depth bound is Operator-configurable at the registry within the protocol range 1 through 8, and issued statements carry it in the depth_bound field."V12 REQ-039: "The effective depth bound is evaluated at verification time as the minimum of the current statement's depth_bound and 8, with 4 used when the statement carries no depth_bound field."V12 REQ-038 enforces it fail-closed and before any signature work: chain length above the effective bound is rejected CHAIN_TOO_LONG, with the instrumented signature count at zero.Three properties fall out, and together they answer the question:
REQ-092) — not per-credential, not per-hop, not settable by an issuing agent.REQ-039), so it is late-bound and revisable by the Operator, and it applies uniformly to the whole tree under that root.depth field is an accounting value, not a limit. REQ-006 makes it derived — position plus one — and REQ-038 rejects any credential whose depth disagrees with its chain length. There is no writable headroom field, no max_further_depth, no remaining-generations counter anywhere in REQ-004's frozen schema.Counter authority does carry a per-delegation limit that nests and cannot widen:
V12 REQ-078: "a parent carves a child's counter sub-range from the unconsumed top of its own current range… the carved range and its issuing-key identity travel inside the child's credential as the delegated_range wire field."V12 REQ-096: "for every adjacent hop pair, hop[i].delegated_range is a subset of hop[i-1].delegated_range, and the topmost delegated hop is a subset of the root allocation; any non-subset is rejected with COUNTER_OUT_OF_RANGE. The Reconciler mirrors the same full-chain check."V12 REQ-095: a credential whose chain shows a derived issuer but which carries no delegated_range is rejected MALFORMED_CREDENTIAL.So the model already knows how to express a monotonically-narrowing, wire-carried, verifier-enforced, per-delegation limit — it just does it for counters and not for generations. A parent can bound how many agents its subtree may mint; it cannot bound how many generations deep they may go.
Net. A delegation-generation limit ("this construction may delegate at most two further generations, whatever the root allows") has no representation in V1 or V2. The available levers are the per-root depth_bound (Operator-set, tree-wide, 1–8) and the hard maximum of 8. Adding one would mean a new credential field with delegated_range-style subset enforcement — a wire change, and WIRE-FREEZE-v1_0 §Declaration makes that "a new signing-context version… never an in-place edit," with V2 v0.4 §Exclusions confirming the freeze stands through V2. The nearest in-model workaround is per-root separation: give each construction class its own registered root so the Operator-set depth_bound applies to it alone (REQ-092) — which trades a delegation primitive for a registration-topology convention, and one that no spec currently sanctions.
**The atom takes the shape without deformation. The strain is that almost none of the machinery needed to write or evaluate it is specified yet — and one exclusion sits uncomfortably close to the use case.**
GRANTHA_POLICY_DSL_SCOPE-v0_1 §1: grant = { holders, access-type, resource-scope, conditions }, with everything else the same atom at different scales — "a grant over a capability → a role," "a grant whose scope is the grant-issuing capability → administration."
The mapping is natural:
GRANTHA_EXPLORATION_PHYSICAL_AUTHORITY-v0_1 §2 — "Resource = a physical device; access-type = a physical verb… No new primitive needed to express physical authority."That much is clean. The strain is everything downstream of the shape.
GRANTHA_GRANT_CHECK_CONTRACT-v0_2 §2, the request table, on requested_scope: "Grammar [DEFERRED]: scope expressions are policy expressions, gated on the §4.1 fork. Until then the field is reserved, not specified." §9 carries it as an open item blocking "scope-narrowing-aware answers." You cannot today write "construction class C at ruleset ≥ v4" as a scope expression, because there is no expression language to write it in.POLICY_DSL_SCOPE-v0_1 §3.4: "Narrowing semantics: partial-scope representation and reversal. [DEFERRED] — asserted in I8, still unspecified; the DSL must represent a narrowed grant and its reversal, which is a scope-algebra question." §6 repeats it as an open call. A version pin whose whole point is graded tightening ("clamp this class back to the last-known-good ruleset") is precisely a narrowing operation, and narrowing has no representation. This is the strain point most specific to the use case.>=, ranges, "any of") appear in none of the tiers. POLICY_DSL_SCOPE §4 recommends "a layered predicate language" with (c) ⊂ (b) ⊂ (a) expressiveness, and §6 lists "DSL concrete grammar + examples" as the next design pass. Whether an ordering operator lands in tier (a) is unwritten.V12 REQ-004: capability_ref is "nullable, exactly 64 bytes when present." GRANTHA_GRANT_CHECK_CONTRACT-v0_2 §2: capability_ref is "opaque bytes, ≥ 64… Per the A4 interim floor. Ratification of the floor is still owed [OPERATOR-SHEET, carried]." The class-plus-version binding is therefore resolvable only by GRANTHA's authorizer; a Stele verifier sees 64 opaque bytes, and V12 REQ-015 confirms the registry checks only "the stamp's structural authenticity."GRANTHA_GRANT_CHECK_CONTRACT-v0_2 §3: "The verdict is effective scope, nothing else… No status enum, no pending / revoked / expired cause codes, no retry hints," with the cost stated plainly: "a benign consumer cannot distinguish denial from expiry from clamp." A construction refused because its ruleset version is out of policy looks identical to one refused because the grant was clamped. §3's [INTERPRETATION] note defends this deliberately — the cause code is "exactly the tell a clamped adversary wants" — so this is a priced cost, not an oversight, but it lands directly on operability for a version-gated construction flow.POLICY_DSL_SCOPE-v0_1 §3.1, on holder reference: "a Stele principal ref; human-or-autonomous only — never Stele's Loomworks kind enum." Read precisely: this constrains the holder slot, not resource-scope, so a construction class as resource is not excluded by it. But the sentence is the record's only stated position at the Loomworks/GRANTHA boundary, and it is a refusal to let a Loomworks-side type enum into the atom. Anyone proposing a Loomworks construction-class taxonomy as GRANTHA resource-scope should expect that line to be raised, and should have an answer for why resource-scope differs from holder-reference on the same reasoning. Also note Stele's own nature enum is deliberately two-valued and neutral (V12 REQ-001: PrincipalNature "with exactly two members: human and autonomous"), and V12 §Glossary/REQ-004 reserve credential kind for operational | mint — so no construction-class vocabulary exists on the Stele side to reference either.
GRANTHA_GRANT_CHECK_CONTRACT-v0_2 §5.5 (the live-only counter rule, itself marked [INTERPRETATION], proposed for ratification): "any operation class whose burst damage within P + W + S is unacceptable must carry a live-only counter — a rate, spend, or concurrency cap evaluated against local counters at the enforcement point on every operation." Agent construction at Stele's measured rates (V12 §NFRs: ≥3,500 full mints/sec/core, Cycle 3 measured 3,900–4,000) is a strong candidate for that classification. §5.3's constraint system — replication_p99 × margin < W ≤ L_containment − P − S — adds the note that "an empty box is a finding, not a tuning failure," and P, the propagation term, is listed in §9 as "Open record item, unowned, hot-path-critical."
Net. The grant shape is the right shape and takes construction-class-plus-ruleset-version without deformation. Calling it "without strain" would overstate it: the scope grammar is deferred, the narrowing algebra is deferred, version-ordering predicates are unscoped, the on-wire reference is opaque and its size floor unratified, the answer channel deliberately cannot report a version mismatch as such, and the whole GRANTHA set is uncommitted and reconstructed (Ratification Ledger v0.3 §1). What exists is a shape that will accept the requirement, not a mechanism that can serve it.
| # | Question | Answer |
|---|---|---|
| 1 | Creation event or first assertion? | Creation event, durably recorded before use, on both tiers (V12 REQ-013/021/025/027; Observance Law, §Scope). But the verify path is present-tense — it walks signatures to the current statement (REQ-036/039); creation records live on the audit/Reconciler side. |
| 2 | Verdict expresses signature-verified-at-birth? | Not as a distinct input. The mechanism is real and frozen (attested mode: REQ-093/094/100, witness_sig + attestation_required in REQ-004), but REQ-068 closes the verdict input set to four terms, so birth attestation collapses into "credential validity" or an OFF_BOOKS_MINT detection event. No verdict reads "attested at birth." |
| 3 | Hop depth carries delegation-generation limits? | No. One per-root Operator-set bound, evaluated at verify time from the statement, min(depth_bound, 8), default 4 (REQ-092/039/038). No per-delegation generation field exists — in pointed contrast to delegated_range, which does nest and cannot widen (REQ-078/095/096). Adding one is a wire change under a frozen format. |
| 4 | GRANTHA grant scopes construction class + ruleset version? | Shape yes, machinery no. The atom maps cleanly (class → resource-scope, version → carried condition; DSL Scope §1/§3.1/§3.3), but scope grammar is DEFERRED (Contract §2/§9), narrowing algebra is DEFERRED (DSL Scope §3.4), version-ordering predicates are unscoped, capability_ref is opaque and its floor unratified, and the answer channel cannot report a version mismatch as such (Contract §3). |
Cross-cutting. Questions 2 and 3 both terminate at the same wall: the change each would need is a change to a signed payload's field set, and WIRE-FREEZE-v1_0 §Declaration routes that to a new signing-context version, never an in-place edit — with V2 v0.4 §Exclusions confirming the freeze holds through V2. Neither is a V2-amendable item. Question 4 terminates at a different wall: not a freeze, but an absence — the GRANTHA policy language is scoped, not drafted (POLICY_DSL_SCOPE §6: "DSL concrete grammar + examples — next design pass").
Not done here. No Loomworks assessment against the Witness Environment Contract (that contract's §Not-run-now defers it explicitly until "Loomworks's auth framework grows agent identity"). No recommendations, no spec edits, no commits. Halting as instructed.
DUNIN7 · read-only spec verification · Stele Agentic ID V1 (V12) / V2 (v0.4) / GRANTHA design set Loomworks Agent Construction — Spec Verification — v0.1 — 2026-07-30