Skip to content

feat(typed-domain-kernel): Tranche B interface/evidence package - #29

Open
s0fractal wants to merge 1 commit into
mainfrom
spec/typed-domain-kernel-b
Open

s0fractal wants to merge 1 commit into
mainfrom
spec/typed-domain-kernel-b

Conversation

@s0fractal

Copy link
Copy Markdown
Owner

Campaign 2, one frozen package for B1–B5/B7/B8. Interfaces and evidence only — no production domain, no translator, no runtime integration.

Frozen SHA: 0ed65d7494cac34a11742e5512eb7d26a1cdbddf

Three layers, one-way dependencies

layer 1  domain / capabilities / delta   B1 B3
layer 2  invariants / context            B4 B8
layer 3  laws / policy / version DAG     B2 B7 B5

B6 out of scope — it is the RFC's own open question (§20.19).

The seam

§6.2 rule 2 requires a policy to state "the minimum status each boundary requires". §6.2 defines no order on LawStatus. Part 03 repeats the phrase three times (§7.1 :397, :540, :678) without repairing it.

The text gives two relations — falsified below everything, asserted below the evidenced kinds at translation/irreversible boundaries — and never relates proved to tested. LawClaim.scope, LawClaim.precondition and tested.domain make that load-bearing rather than cosmetic:

a proved claim with scope: partial over a narrow precondition, versus a tested claim whose generation domain strictly contains that precondition. Neither dominates. Ranking proved first lets a boundary accept a proof about a region it does not operate in, over evidence about the region it does.

Executable at fixtures/countermodels/proved-narrower-than-tested.json.

This is the same shape Suitability.lean already proved as no_meet (finding C3) — a document saying "the lower of two" over an order with no meet. Which is exactly why this package does not invent a total order. statedBelow returns null for "the text does not order these" — a different answer from false, and the one a policy must act on. BoundaryPolicy states an accept set, which needs no order.

Lean: not included, and the condition for wanting it is stated

The theorem candidate is written out exactly. It decides between the two available repairs — state a partial order and prove every comparable pair has a GLB, or replace "minimum status" with an accept set. If the steward takes the second, there is nothing left to prove, and adding theorems for the first before that choice would be weight rather than evidence.

Five proof obligations

  1. LawStatus has no order, yet a minimum over it is required (the seam)
  2. InvariantDefinition has no field for the context surfaces §6.1.2 rule 1 requires it to declare — obligation exists, carrier does not
  3. DeltaDescriptor is required with its own content address and never given a shape
  4. the version-label projection is required (§6.2.1 rule 2) and never specified
  5. scope widening is neither permitted nor forbidden

Properties, labelled

Your warning generalised: the failure is deriving a property from a shape. Every property carries one of three labels — structural, requires a LawClaim, has a countermodel.

Four countermodels, executable:

claim countermodel
"proved beats tested" proof over a narrow precondition vs test over a wider domain
"a typed delta space composes associatively" clamped translation, with the arithmetic witness
"scope widening preserves the report" same predicate + state, two legal world snapshots, two reports
"a patch label is always admissible" the one conflict §6.2.1 rule 3 names

The countermodel category is non-empty on purpose. An empty one would mean nobody looked, not that the design is sound.

Fail-closed

Every refusal has a code; nothing falls through to an accept. Two conditions are deliberately not-assessed rather than refused — cost over budget, stale snapshot — because §6.1.2 rule 5 requires an outcome distinct from held, and collapsing it to a boolean is how a boundary comes to believe an invariant held when nobody checked it. ValidationReport is three-valued for that reason; the RFC never types it.

Full table in the README, plus closed member sets (asserted by a control) marking which are quoted from the RFC and which are proposed.

Checks

20 kernel controls
./t check READY — 602 tests, 368 chords valid

Reuses the full-digest convention and reference kinds from the fast-path debt-scope probe rather than reinventing them.

…5/B7/B8

Interfaces and evidence, not implementations. No production domain, no
translator, no runtime integration — the point is that the boundaries get
reviewed before anything rests on them.

Three layers, one-way dependencies: domain/capabilities/delta (B1 B3);
invariants/context (B4 B8); laws/policy/version DAG (B2 B7 B5). B6 is out of
scope and remains the RFC's own open question.

**The output that matters is five proof obligations** — places where the RFC
states a requirement whose terms it never defines, and where an implementer's
reasonable guess silently becomes a normative decision nobody made.

The first is the seam. §6.2 rule 2 requires a policy to state "the minimum
status each boundary requires", and §6.2 defines NO ORDER on LawStatus. Part 03
repeats the phrase three times without repairing it. The text relates falsified
and asserted to the rest and never relates `proved` to `tested` — and
LawClaim.scope, LawClaim.precondition and tested.domain make that gap
load-bearing: a proof over a narrow precondition and a test over a strictly
wider generation domain are incomparable, and ranking proved first would let a
boundary accept a proof about a region it does not operate in over evidence
about the region it does.

That is the same shape Suitability.lean already proved as `no_meet` (finding C3)
— "the lower of two levels" over an order with no meet. Which is why this
package does NOT invent a total order: an invented order is a normative decision
wearing an implementation's clothes. `statedBelow` returns null for "the text
does not order these", which is a different answer from false and is the one a
policy has to act on. BoundaryPolicy states an accept SET, which needs no order.

No Lean is included. The theorem candidate is stated exactly, and so is the
condition for wanting it: it decides between the two available repairs, and if
the steward takes the accept-set repair there is nothing left to prove. Adding
theorems for the other repair before that choice is made would be weight rather
than evidence.

The other four obligations: InvariantDefinition has no field for the context
surfaces §6.1.2 rule 1 requires it to declare; DeltaDescriptor is required with
its own content address and never given a shape; the version-label projection is
required and never specified; and scope widening is neither permitted nor
forbidden.

Properties are labelled structural / requires-a-LawClaim / has-a-countermodel,
because the general form of Codex's warning is deriving a property from a shape.
The countermodel category is non-empty on purpose — an empty one would mean
nobody looked, not that the design is sound. Four are executable: a proof
narrower than a test; clamped translations as a well-typed non-associative delta
space, with the arithmetic witness; scope widening producing two different
reports from two legal world snapshots; and the one version conflict §6.2.1
names.

Fail-closed everywhere, with a code per refusal and nothing falling through to
an accept. Two conditions are deliberately not-assessed rather than refused —
over budget and stale snapshot — because §6.1.2 rule 5 requires an outcome
distinct from held, and collapsing it to a boolean is how a boundary comes to
believe an invariant held when nobody checked it.

Reuses rather than reinvents: the full-digest convention and reference kinds come
from the fast-path debt-scope probe, which already types RFC-0003 references.

20 controls. ./t check READY, 602 tests.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRHMVB9rUYNggn4wLmc1An
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add Tranche B typed-domain interface and evidence package

✨ Enhancement 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Adds three-layer domain, invariant, law-policy, and version-DAG interfaces.
• Enforces fail-closed validation with explicit refusal and not-assessed outcomes.
• Documents five RFC proof obligations through fixtures, countermodels, and Deno controls.
Diagram

graph TD
  RFC["RFC Tranche B"] --> L1["Domain Layer"] --> L2["Invariant Layer"] --> L3["Law Layer"] --> V["Boundary Verdicts"]
  F["Evidence Fixtures"] --> T["Deno Controls"] --> L1
  T --> L2
  T --> L3
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Define a LawStatus partial order
  • ➕ Preserves the RFC's minimum-status wording
  • ➕ Could support threshold policies if required meets are proved
  • ➖ Requires a normative RFC decision outside this package
  • ➖ Proved and tested remain scope-dependent and may lack a greatest lower bound
2. Evaluate evidence predicates directly
  • ➕ Can compare scope, preconditions, and generation domains per boundary
  • ➕ Avoids reducing heterogeneous evidence to status labels
  • ➖ Introduces substantially more policy machinery
  • ➖ Requires domain-containment semantics the RFC does not currently define

Recommendation: Keep the PR's explicit accept-set policy for this interface/evidence stage. It avoids inventing an unsound total order, remains fail-closed, and leaves the steward a clear choice: ratify accept sets or define and prove a usable partial order before runtime integration.

Files changed (13) +1696 / -4

Enhancement (3) +938 / -0
layer1_domain.tsDefine domain, capability, and delta interfaces +264/-0

Define domain, capability, and delta interfaces

• Introduces content-addressed domain declarations, closed capability mappings, delta descriptors, three-valued validation reports, and coded registry admission checks. Enforces capability-method symmetry, required laws, typed geometric deltas, operation consistency, and full digests.

probes/typed-domain-kernel-v0/ts/layer1_domain.ts

layer2_invariant.tsDefine invariant context and evaluation admission +295/-0

Define invariant context and evaluation admission

• Introduces invariant definitions, scopes, cost classes, context surfaces, freshness, and evaluation types. Adds fail-closed checks for missing scope inputs, undeclared surfaces, unbounded fast paths, over-budget evaluation, and stale snapshots while recording the scope-widening obligation.

probes/typed-domain-kernel-v0/ts/layer2_invariant.ts

layer3_law.tsDefine law policies and version DAG validation +379/-0

Define law policies and version DAG validation

• Models law evidence without inventing an order between proved and tested, using explicit boundary accept sets instead. Adds coded law and composition decisions plus version DAG checks for roots, predecessors, cycles, and patch increments across law weakening.

probes/typed-domain-kernel-v0/ts/layer3_law.ts

Tests (1) +353 / -0
kernel_test.tsCover layered validators and evidence boundaries +353/-0

Cover layered validators and evidence boundaries

• Adds controls for domain admission, invariant evaluation, law policy, composition, version DAGs, and closed enumerations. Tests both successful admission and coded fail-closed outcomes, including the proved-versus-tested seam.

probes/typed-domain-kernel-v0/ts/kernel_test.ts

Documentation (3) +272 / -3
README.mdDocument the Tranche B interface and evidence package +268/-0

Document the Tranche B interface and evidence package

• Defines the package scope, three-layer dependency model, closed sets, fail-closed boundaries, countermodels, and five unresolved RFC proof obligations. Explicitly excludes production domains, translators, runtime integration, and B6.

probes/typed-domain-kernel-v0/README.md

x7B88_evidence_report.myc.mdRefresh external-surface evidence totals +1/-1

Refresh external-surface evidence totals

• Increments tracked and probe counts to include the typed-domain kernel experiment.

src/x7B88_evidence_report.myc.md

x8F88_external_surfaces.myc.mdRegister the typed-domain kernel surface +3/-2

Register the typed-domain kernel surface

• Adds the probe README to the experimental external-surface ledger and updates experimental and total counts.

src/x8F88_external_surfaces.myc.md

Other (6) +133 / -1
deno.jsoncRun typed-domain kernel controls in unit tests +1/-1

Run typed-domain kernel controls in unit tests

• Adds the new kernel test module to the workspace unit-test command so its interface and evidence controls run in CI.

deno.jsonc

delta-not-associative.jsonAdd non-associative typed delta countermodel +22/-0

Add non-associative typed delta countermodel

• Provides a clamped-translation witness showing that a typed delta descriptor does not imply associative composition.

probes/typed-domain-kernel-v0/fixtures/countermodels/delta-not-associative.json

patch-across-law-weakening.jsonAdd patch-label law-weakening countermodel +19/-0

Add patch-label law-weakening countermodel

• Models the RFC's named version conflict: a patch increment across a release that weakens a law.

probes/typed-domain-kernel-v0/fixtures/countermodels/patch-across-law-weakening.json

proved-narrower-than-tested.jsonDemonstrate proved and tested status incomparability +26/-0

Demonstrate proved and tested status incomparability

• Contrasts a narrow partial proof with tests over a wider domain, showing why a single minimum LawStatus is undefined without additional ordering semantics.

probes/typed-domain-kernel-v0/fixtures/countermodels/proved-narrower-than-tested.json

scope-widening-unpinned.jsonAdd unpinned scope-widening countermodel +22/-0

Add unpinned scope-widening countermodel

• Shows that identical state evaluation can change when its world snapshot comes from a different logical step, exposing unspecified widening semantics.

probes/typed-domain-kernel-v0/fixtures/countermodels/scope-widening-unpinned.json

domain-euclidean.jsonAdd admissible Euclidean domain declaration +43/-0

Add admissible Euclidean domain declaration

• Provides a content-addressed positive fixture whose capabilities, methods, delta descriptor, operations, invariants, and metric law agree.

probes/typed-domain-kernel-v0/fixtures/positive/domain-euclidean.json

@s0fractal

s0fractal commented Aug 26, 2026 •

Copy link
Copy Markdown
Owner Author

Joint gate round 1/2 on exact 0ed65d7494cac34a11742e5512eb7d26a1cdbddf: changes requested.

Positive: the three-layer scope is correct, all seven B items are mapped, the 20 shipped controls run, and keeping Lean out before a normative choice is correct.

P1 — the central no-meet claim is false for the implemented relation

Executed against statedBelow with reflexive closure:

{"lower_bounds":["asserted","falsified"],"greatest_lower_bounds":["asserted"]}

The package defines falsified < asserted < proved and falsified < asserted < tested; therefore proved ∧ tested = asserted. This is not the Suitability no_meet shape. The narrow-proof/wide-test fixture establishes that status kind alone does not determine contextual adequacy, but it does not remove the GLB of the four status kinds.

Required: withdraw the no-meet/theorem claim. Accept-sets may remain the proposed repair, justified because scope/precondition/generation-domain are not captured by a status threshold. If a contextual no-meet is claimed, first define the contextual relation and then prove/test that relation.

P1 — supplied context is not an observed read

InvariantEvaluation in the RFC requires worldSnapshot, authoritySnapshot and evaluatedAtLogicalStep. The kernel treats any supplied surface as one the predicate read, so a valid state-only definition is refused merely because the required evaluation envelope carries those snapshots:

state_only_with_required_context
→ {"ok":false,"code":"undeclared-surface-read",...}

Rule 1 prohibits undeclared reads, not available inputs. Required: separate provided surfaces from observed/authorized reads (for example an execution trace or observedReads), then enforce observed ⊆ declared and declared ⊆ provided. Do not use empty strings in the positive fixture to make mandatory context disappear.

The current “scope-widening” fixture also changes worldSnapshot, so differing reports are expected for differing declared inputs; it is not a countermodel to widening. Reframe any remaining gap as snapshot/logical-step binding, or supply an actual same-input widening counterexample.

P1 — law policy and composition say stronger things than they enforce

Executed:

tested_without_consumer_domain → {"admitted":true,"status":"tested"}
mixed_composition_status       → {"admitted":true,"status":"proved"}
  • BoundaryPolicy says requiresGenerationDomain is required when tested is accepted, but it is optional and decideLaw admits tested without it. Make the policy discriminated or refuse the missing consumer-side domain.
  • decideComposition says a composite status is not computed, then returns the left status and drops the right. A proved-left/tested-right pair becomes status:"proved". Return both admitted statuses or no composite status; never project one side as the composite evidence grade.
  • “incompatible laws” also remains undefined beyond scope mismatch; list precondition/domain compatibility as an explicit obligation instead of silently admitting it.

P1 — these are typed decision helpers, not yet fail-closed schema validators

validateDomain({}) throws TypeError: d.capabilities is not iterable. Fixtures are parsed as JSON and cast with as DomainDeclaration, so TypeScript supplies no runtime boundary.

The package promises executable schemas/validators and “nothing falls through”. Required: entrypoints that consume fixture/untrusted data must accept unknown, validate closed members and shapes, and return a coded refusal rather than throw; or narrow every claim and rename these as trusted typed decision functions. For a boundary package, the former is preferred. Apply the same rule to invariant, policy/status and release inputs.

P2 — evidence claims currently outrun the controls

  • The delta fixture demonstrates move(move(p,d1),d2) ≠ move(p,compose(d1,d2)): failure of an action/composition compatibility law, not associativity of a binary delta operation (which would require three delta operands).
  • The delta and scope fixtures are not executed by the suite; they are static strings.
  • The “cycle” test expects multiple-roots, so it never reaches the cycle refusal.
  • Two supposedly closed sets are guarded with >=, reopening the exact count drift class.

Required: execute all claimed countermodels, use a real rooted graph with a disconnected cycle to hit cycle, and assert exact refusal/member sets. Either provide a genuine three-delta non-associativity witness or rename the delta obligation to the action law actually falsified.

P2 — two additional normative choices are currently silent

  • COST_CLASSES.indexOf invents constant < linear < superlinear < unbounded; the RFC names the classes and gives special rules for unbounded, but does not define that full order.
  • composition compatibility beyond equal scope is unspecified.

Add both to the obligation map, or model boundary acceptance explicitly without claiming the RFC supplied those orders/relations.

Next response is final round 2/2. Keep the same closed package and delta-only report; no Lean and no production implementation.

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (10) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Claimed meet actually exists 🐞 Bug ≡ Correctness
Description
The theorem candidate says {proved, tested} has no greatest lower bound, but statedBelow places
asserted below both and falsified below asserted, making asserted their greatest lower
bound. This invalidates the package's central no-meet proof obligation and its claimed analogy to
Suitability.lean.
Code

probes/typed-domain-kernel-v0/README.md[R232-235]

+  (i)  the stated relation is a strict partial order;
+  (ii) `proved` and `tested` are incomparable in it;
+  (iii) therefore { proved, tested } has no greatest lower bound,
+        and "the minimum status" is undefined for any policy that must
Relevance

●●● Strong

Theorem text contradicts the implemented ordering, invalidating the package's central proof claim.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The implementation explicitly makes asserted lower than both evidenced statuses and falsified
lower than every status. Therefore the only lower bounds of proved and tested are ordered with
asserted greatest, contradicting the added theorem text.

probes/typed-domain-kernel-v0/ts/layer3_law.ts[70-76]
probes/typed-domain-kernel-v0/README.md[160-176]
probes/typed-domain-kernel-v0/README.md[228-236]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The documented no-GLB theorem contradicts the relation implemented by `statedBelow`: `asserted` is a greatest lower bound of `proved` and `tested`.

## Issue Context
Re-evaluate whether the actual ambiguity is lack of comparability/minimum rather than lack of a meet, and update the README, proof-obligation text, countermodel claims, and tests consistently.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/README.md[155-183]
- probes/typed-domain-kernel-v0/README.md[226-243]
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[55-100]
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[359-379]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Evaluation predicate is unbound 🐞 Bug ≡ Correctness
Description
admitEvaluation never verifies that e.predicate equals d.predicate, so a held report produced
by predicate B can be admitted as evidence for invariant A. The function runs its other checks and
returns success despite the RFC requiring reproducibility for the same predicate and snapshots.
Code

probes/typed-domain-kernel-v0/ts/layer2_invariant.ts[275]

+  return { ok: true };
Relevance

●●● Strong

Admission never verifies predicate match, allowing evidence for a different invariant to pass.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The definition and evaluation each carry a predicate reference, but the complete admission path
never compares them before returning {ok: true}.

probes/typed-domain-kernel-v0/ts/layer2_invariant.ts[60-65]
probes/typed-domain-kernel-v0/ts/layer2_invariant.ts[74-83]
probes/typed-domain-kernel-v0/ts/layer2_invariant.ts[182-275]
docs/rfc/0003-heterogeneous-state-protocol/02-typed-state-domains.md[218-222]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Reject an evaluation whose predicate address differs from the invariant definition's predicate address.

## Issue Context
Both values are independently supplied to `admitEvaluation`; success currently does not establish that the report belongs to the invariant being admitted.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/layer2_invariant.ts[182-191]
- probes/typed-domain-kernel-v0/ts/layer2_invariant.ts[258-275]
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[99-120]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Missing freshness passes admission 🐞 Bug ≡ Correctness
Description
When a boundary supplies freshness but omits snapshotLogicalStepsBehind, the conjunction skips
the stale check and admitEvaluation returns {ok: true}. A snapshot whose freshness cannot be
measured has not been shown current and must not pass a fail-closed boundary.
Code

probes/typed-domain-kernel-v0/ts/layer2_invariant.ts[R259-262]

+  if (
+    boundary.freshness &&
+    boundary.snapshotLogicalStepsBehind !== undefined &&
+    boundary.snapshotLogicalStepsBehind > boundary.freshness.maxLogicalStepsBehind
Relevance

●●● Strong

Freshness check skipped when age is undefined, bypassing the fail-closed staleness boundary.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The RFC requires boundaries to declare freshness and stale snapshots to be not assessed; the
implementation only acts when the optional age is defined, even though snapshot-missing is an
exported outcome.

docs/rfc/0003-heterogeneous-state-protocol/02-typed-state-domains.md[227-230]
probes/typed-domain-kernel-v0/ts/layer1_domain.ts[106-113]
probes/typed-domain-kernel-v0/ts/layer2_invariant.ts[258-275]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Return `notAssessed: "snapshot-missing"` when a freshness requirement exists but no snapshot age is supplied.

## Issue Context
The reason is already present in `NOT_ASSESSED_REASONS`; the current condition only handles a known age that exceeds the limit.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/layer1_domain.ts[106-113]
- probes/typed-domain-kernel-v0/ts/layer2_invariant.ts[258-275]
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[167-181]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View high (2)
4. Short law references admitted 🐞 Bug ≡ Correctness
Description
For tested claims, decideLaw checks only that generator and domain are nonempty, so values
such as "x" pass despite both fields being content-addressed references. Proved evidence/checkers,
tested evidence, falsified counterexamples, preconditions, and policy generation domains likewise
receive no full-digest validation.
Code

probes/typed-domain-kernel-v0/ts/layer3_law.ts[R202-206]

+  if (kind === "tested") {
+    // §6.2 rule 3, enforced at the consumer. The producing side declaring a
+    // generator is not enough: a boundary must be able to say which generation
+    // domains it will take, or "tested" is a word.
+    if (!claim.status.generator || !claim.status.domain) {
Relevance

●●● Strong

Truthiness-only checks accept non-content-addressed references, contradicting the full-digest
validation claim.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
ContentAddress is enforced by a single regex in layer 1 and the README claims every reference is
checked, but layer 3 never imports or calls that validator and accepts any truthy generator/domain
strings.

probes/typed-domain-kernel-v0/ts/layer1_domain.ts[20-26]
probes/typed-domain-kernel-v0/README.md[121-125]
probes/typed-domain-kernel-v0/ts/layer3_law.ts[23-49]
probes/typed-domain-kernel-v0/ts/layer3_law.ts[202-226]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Apply `isContentAddress` to every reference-bearing law claim and policy field before making an admission decision.

## Issue Context
The package states that every reference is a full digest, but nonempty short handles currently pass layer 3.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[16-49]
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[119-126]
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[145-226]
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[220-264]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Composition status depends on side 🐞 Bug ≡ Correctness
Description
decideComposition says it does not compute a composite status but returns the left claim's status
in the normal LawDecision field. Composing an admitted proved claim with an admitted tested
claim therefore reports proved, while reversing the operands reports tested, exposing an
order-dependent and unsupported result.
Code

probes/typed-domain-kernel-v0/ts/layer3_law.ts[R256-259]

+  // Both admitted and scopes agree. The composite's status is NOT computed:
+  // that would require the order §6.2 does not state. A caller that needs one
+  // must consult both, which is what returning the pair-checked decision means.
+  return { admitted: true, status: l.status };
Relevance

●● Moderate

Order-dependent result is a real defect but touches subjective composition semantics.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The success variant defines status as a singular result, while the composition implementation
explicitly declines to compute one and nevertheless fills it from l.status.

probes/typed-domain-kernel-v0/ts/layer3_law.ts[128-130]
probes/typed-domain-kernel-v0/ts/layer3_law.ts[242-259]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Make composition success avoid presenting the left operand's status as a composite status.

## Issue Context
Use a distinct composition decision type that either carries both checked statuses/claims or omits status entirely; add mixed-status operand-order tests.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[128-130]
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[237-260]
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[266-282]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

6. Delta composition reference unchecked 🐞 Bug ≡ Correctness
Description
DeltaDescriptor.composition is declared as a ContentAddress, but validateDomain omits it from
the reference list, so a geometric domain with composition: "deadbeef" is admitted. This directly
contradicts the package's claim that every reference is checked as a full digest.
Code

probes/typed-domain-kernel-v0/ts/layer1_domain.ts[R78-82]

+  /** Laws of delta composition, if the domain composes deltas at all.
+   *  DELIBERATELY OPTIONAL and deliberately not defaulted to associative:
+   *  typedness does not confer associativity, and assuming it is exactly the
+   *  move §6.2 exists to prevent. Absent means "no claim", not "no law". */
+  composition?: ContentAddress;
Relevance

●●● Strong

Validator omits an optional content-addressed field from its checked-reference list, contradicting
README claim.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The field is typed as a content address, while the validator adds only the descriptor address and
validator predicate to its checked references.

probes/typed-domain-kernel-v0/ts/layer1_domain.ts[67-83]
probes/typed-domain-kernel-v0/ts/layer1_domain.ts[233-261]
probes/typed-domain-kernel-v0/README.md[121-125]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Include `deltaDescriptor.composition` in `validateDomain`'s content-address checks when present.

## Issue Context
The optional field remains a reference even when no composition law is required.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/layer1_domain.ts[67-83]
- probes/typed-domain-kernel-v0/ts/layer1_domain.ts[233-261]
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[69-93]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Test-domain constraint is optional 🐞 Bug ≡ Correctness
Description
requiresGenerationDomain is documented as required whenever a policy accepts tested, but the
optional field and guarded comparison let such a policy admit every nonempty generation domain. The
default test policy exercises exactly this unconstrained configuration, so the consuming-side
requirement is not enforced.
Code

probes/typed-domain-kernel-v0/ts/layer3_law.ts[R122-125]

+  /** Required when `tested` is accepted: the generation domain a boundary will
+   *  take. Without it, §6.2 rule 3's "a test whose generation domain is unstated
+   *  is `asserted` with extra steps" is unenforceable on the CONSUMING side. */
+  requiresGenerationDomain?: PredicateRef;
Relevance

●●● Strong

Documented required field is optional and unenforced, contradicting stated consuming-side
requirement.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The field comment calls it required, but the type marks it optional and decideLaw compares domains
only if the field happens to exist.

probes/typed-domain-kernel-v0/ts/layer3_law.ts[119-126]
probes/typed-domain-kernel-v0/ts/layer3_law.ts[202-224]
probes/typed-domain-kernel-v0/ts/kernel_test.ts[193-197]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Reject or make unrepresentable a policy that accepts `tested` without `requiresGenerationDomain`.

## Issue Context
Use a discriminated policy type and retain a runtime check for JSON-derived values.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[115-126]
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[155-161]
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[202-224]
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[193-197]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Duplicate releases collapse silently 🐞 Bug ≡ Correctness
Description
validateVersionDag constructs a map without checking duplicate addresses, so two distinct non-root
release records with the same content address collapse to one node and can still produce `{ok:
true}`. The accepted input is not an unambiguous content-addressed version DAG.
Code

probes/typed-domain-kernel-v0/ts/layer3_law.ts[R294-295]

+  const byAddress = new Map(releases.map((r) => [r.address, r]));
+  const roots = releases.filter((r) => r.predecessor === null);
Relevance

●●● Strong

Map construction silently collapses duplicate addresses, allowing ambiguous DAG input to pass.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
JavaScript Map construction overwrites an earlier entry with the same key, and no later root,
predecessor, or cycle check compares map size with the release list or otherwise rejects duplicates.

probes/typed-domain-kernel-v0/ts/layer3_law.ts[290-329]
probes/typed-domain-kernel-v0/ts/kernel_test.ts[284-309]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Detect duplicate release addresses before constructing the DAG map and return a dedicated refusal.

## Issue Context
Do not allow later records to overwrite earlier records silently; cover duplicates with identical and conflicting metadata.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[272-279]
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[290-311]
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[284-309]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (1)
9. Malformed declarations throw 🐞 Bug ☼ Reliability
Description
validateDomain directly iterates and indexes fields such as capabilities, implements, and
laws, so JSON-derived inputs with missing/null fields throw instead of returning a coded refusal.
That breaks the package's fail-closed validator contract at the exact runtime boundary where tests
already use JSON.parse plus a TypeScript cast.
Code

probes/typed-domain-kernel-v0/ts/layer1_domain.ts[R162-164]

+  for (const c of d.capabilities) {
+    if (!(CAPABILITIES as readonly string[]).includes(c)) {
+      return no("unknown-capability", `${c} is not a capability of this kernel`);
Relevance

●● Moderate

Malformed input could throw; similar hardening requests were recently rejected in this repo.

PR-#17
PR-#19

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The fixture loader parses untyped JSON and casts it, while the validator assumes arrays and objects
exist; for example capabilities: null fails in the added loop before any verdict can be returned.

probes/typed-domain-kernel-v0/ts/kernel_test.ts[35-46]
probes/typed-domain-kernel-v0/ts/layer1_domain.ts[154-168]
probes/typed-domain-kernel-v0/ts/layer1_domain.ts[208-240]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Validate the runtime shape of domain declarations before iterating or indexing their members.

## Issue Context
TypeScript types do not validate parsed JSON. Return structured refusal codes for missing, null, wrongly typed, or malformed fields rather than throwing.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/layer1_domain.ts[137-160]
- probes/typed-domain-kernel-v0/ts/layer1_domain.ts[162-240]
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[35-46]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

10. Trace control can pass falsely 🐞 Bug ⚙ Maintainability
Description
The trace-scope control checks the refusal code only when a code field exists, so it also passes
if admitEvaluation regresses to {ok: true}. This makes one of the package's claimed executable
controls non-discriminating.
Code

probes/typed-domain-kernel-v0/ts/kernel_test.ts[R142-146]

+  const r = admitEvaluation(
+    inv({ scope: "trace", reads: ["state", "trace"] }),
+    evaluation(),
+  );
+  if ("code" in r) assertEquals(r.code, "missing-trace-for-trace-scope");
Relevance

●●● Strong

Conditional assertion allows success to pass silently, weakening the executable control.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The transition branch explicitly asserts rejection, while the trace branch's conditional assertion
executes only on a refusal and otherwise does nothing.

probes/typed-domain-kernel-v0/ts/kernel_test.ts[134-147]
probes/typed-domain-kernel-v0/ts/layer2_invariant.ts[201-207]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Add the same explicit `ok === false` assertion used by the transition branch before checking the trace refusal code.

## Issue Context
The test must fail if the validator unexpectedly admits the trace evaluation.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[134-147]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
Review mode: ⚖️ Balanced

Grey Divider

Tip of the day
💡 Did you know, you can ask Qodo to dismiss a finding you disagree with, with your reason on record

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment on lines +232 to +235
(i) the stated relation is a strict partial order;
(ii) `proved` and `tested` are incomparable in it;
(iii) therefore { proved, tested } has no greatest lower bound,
and "the minimum status" is undefined for any policy that must

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Claimed meet actually exists 🐞 Bug ≡ Correctness

The theorem candidate says {proved, tested} has no greatest lower bound, but statedBelow places
asserted below both and falsified below asserted, making asserted their greatest lower
bound. This invalidates the package's central no-meet proof obligation and its claimed analogy to
Suitability.lean.
Agent Prompt
## Issue description
The documented no-GLB theorem contradicts the relation implemented by `statedBelow`: `asserted` is a greatest lower bound of `proved` and `tested`.

## Issue Context
Re-evaluate whether the actual ambiguity is lack of comparability/minimum rather than lack of a meet, and update the README, proof-obligation text, countermodel claims, and tests consistently.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/README.md[155-183]
- probes/typed-domain-kernel-v0/README.md[226-243]
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[55-100]
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[359-379]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

};
}

return { ok: true };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Evaluation predicate is unbound 🐞 Bug ≡ Correctness

admitEvaluation never verifies that e.predicate equals d.predicate, so a held report produced
by predicate B can be admitted as evidence for invariant A. The function runs its other checks and
returns success despite the RFC requiring reproducibility for the same predicate and snapshots.
Agent Prompt
## Issue description
Reject an evaluation whose predicate address differs from the invariant definition's predicate address.

## Issue Context
Both values are independently supplied to `admitEvaluation`; success currently does not establish that the report belongs to the invariant being admitted.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/layer2_invariant.ts[182-191]
- probes/typed-domain-kernel-v0/ts/layer2_invariant.ts[258-275]
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[99-120]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +259 to +262
if (
boundary.freshness &&
boundary.snapshotLogicalStepsBehind !== undefined &&
boundary.snapshotLogicalStepsBehind > boundary.freshness.maxLogicalStepsBehind

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Missing freshness passes admission 🐞 Bug ≡ Correctness

When a boundary supplies freshness but omits snapshotLogicalStepsBehind, the conjunction skips
the stale check and admitEvaluation returns {ok: true}. A snapshot whose freshness cannot be
measured has not been shown current and must not pass a fail-closed boundary.
Agent Prompt
## Issue description
Return `notAssessed: "snapshot-missing"` when a freshness requirement exists but no snapshot age is supplied.

## Issue Context
The reason is already present in `NOT_ASSESSED_REASONS`; the current condition only handles a known age that exceeds the limit.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/layer1_domain.ts[106-113]
- probes/typed-domain-kernel-v0/ts/layer2_invariant.ts[258-275]
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[167-181]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +256 to +259
// Both admitted and scopes agree. The composite's status is NOT computed:
// that would require the order §6.2 does not state. A caller that needs one
// must consult both, which is what returning the pair-checked decision means.
return { admitted: true, status: l.status };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

4. Composition status depends on side 🐞 Bug ≡ Correctness

decideComposition says it does not compute a composite status but returns the left claim's status
in the normal LawDecision field. Composing an admitted proved claim with an admitted tested
claim therefore reports proved, while reversing the operands reports tested, exposing an
order-dependent and unsupported result.
Agent Prompt
## Issue description
Make composition success avoid presenting the left operand's status as a composite status.

## Issue Context
Use a distinct composition decision type that either carries both checked statuses/claims or omits status entirely; add mixed-status operand-order tests.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[128-130]
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[237-260]
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[266-282]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +202 to +206
if (kind === "tested") {
// §6.2 rule 3, enforced at the consumer. The producing side declaring a
// generator is not enough: a boundary must be able to say which generation
// domains it will take, or "tested" is a word.
if (!claim.status.generator || !claim.status.domain) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

5. Short law references admitted 🐞 Bug ≡ Correctness

For tested claims, decideLaw checks only that generator and domain are nonempty, so values
such as "x" pass despite both fields being content-addressed references. Proved evidence/checkers,
tested evidence, falsified counterexamples, preconditions, and policy generation domains likewise
receive no full-digest validation.
Agent Prompt
## Issue description
Apply `isContentAddress` to every reference-bearing law claim and policy field before making an admission decision.

## Issue Context
The package states that every reference is a full digest, but nonempty short handles currently pass layer 3.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[16-49]
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[119-126]
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[145-226]
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[220-264]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +78 to +82
/** Laws of delta composition, if the domain composes deltas at all.
* DELIBERATELY OPTIONAL and deliberately not defaulted to associative:
* typedness does not confer associativity, and assuming it is exactly the
* move §6.2 exists to prevent. Absent means "no claim", not "no law". */
composition?: ContentAddress;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

6. Delta composition reference unchecked 🐞 Bug ≡ Correctness

DeltaDescriptor.composition is declared as a ContentAddress, but validateDomain omits it from
the reference list, so a geometric domain with composition: "deadbeef" is admitted. This directly
contradicts the package's claim that every reference is checked as a full digest.
Agent Prompt
## Issue description
Include `deltaDescriptor.composition` in `validateDomain`'s content-address checks when present.

## Issue Context
The optional field remains a reference even when no composition law is required.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/layer1_domain.ts[67-83]
- probes/typed-domain-kernel-v0/ts/layer1_domain.ts[233-261]
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[69-93]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +122 to +125
/** Required when `tested` is accepted: the generation domain a boundary will
* take. Without it, §6.2 rule 3's "a test whose generation domain is unstated
* is `asserted` with extra steps" is unenforceable on the CONSUMING side. */
requiresGenerationDomain?: PredicateRef;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

7. Test-domain constraint is optional 🐞 Bug ≡ Correctness

requiresGenerationDomain is documented as required whenever a policy accepts tested, but the
optional field and guarded comparison let such a policy admit every nonempty generation domain. The
default test policy exercises exactly this unconstrained configuration, so the consuming-side
requirement is not enforced.
Agent Prompt
## Issue description
Reject or make unrepresentable a policy that accepts `tested` without `requiresGenerationDomain`.

## Issue Context
Use a discriminated policy type and retain a runtime check for JSON-derived values.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[115-126]
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[155-161]
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[202-224]
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[193-197]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +294 to +295
const byAddress = new Map(releases.map((r) => [r.address, r]));
const roots = releases.filter((r) => r.predecessor === null);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

8. Duplicate releases collapse silently 🐞 Bug ≡ Correctness

validateVersionDag constructs a map without checking duplicate addresses, so two distinct non-root
release records with the same content address collapse to one node and can still produce `{ok:
true}`. The accepted input is not an unambiguous content-addressed version DAG.
Agent Prompt
## Issue description
Detect duplicate release addresses before constructing the DAG map and return a dedicated refusal.

## Issue Context
Do not allow later records to overwrite earlier records silently; cover duplicates with identical and conflicting metadata.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[272-279]
- probes/typed-domain-kernel-v0/ts/layer3_law.ts[290-311]
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[284-309]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +162 to +164
for (const c of d.capabilities) {
if (!(CAPABILITIES as readonly string[]).includes(c)) {
return no("unknown-capability", `${c} is not a capability of this kernel`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

9. Malformed declarations throw 🐞 Bug ☼ Reliability

validateDomain directly iterates and indexes fields such as capabilities, implements, and
laws, so JSON-derived inputs with missing/null fields throw instead of returning a coded refusal.
That breaks the package's fail-closed validator contract at the exact runtime boundary where tests
already use JSON.parse plus a TypeScript cast.
Agent Prompt
## Issue description
Validate the runtime shape of domain declarations before iterating or indexing their members.

## Issue Context
TypeScript types do not validate parsed JSON. Return structured refusal codes for missing, null, wrongly typed, or malformed fields rather than throwing.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/layer1_domain.ts[137-160]
- probes/typed-domain-kernel-v0/ts/layer1_domain.ts[162-240]
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[35-46]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +142 to +146
const r = admitEvaluation(
inv({ scope: "trace", reads: ["state", "trace"] }),
evaluation(),
);
if ("code" in r) assertEquals(r.code, "missing-trace-for-trace-scope");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Informational

10. Trace control can pass falsely 🐞 Bug ⚙ Maintainability

The trace-scope control checks the refusal code only when a code field exists, so it also passes
if admitEvaluation regresses to {ok: true}. This makes one of the package's claimed executable
controls non-discriminating.
Agent Prompt
## Issue description
Add the same explicit `ok === false` assertion used by the transition branch before checking the trace refusal code.

## Issue Context
The test must fail if the validator unexpectedly admits the trace evaluation.

## Fix Focus Areas
- probes/typed-domain-kernel-v0/ts/kernel_test.ts[134-147]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant