Skip to content
Merged
79 changes: 75 additions & 4 deletions dag/gunbc/compiler_frontend_program_interlock.dag
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ type NamespaceDeltaDisposition
| NewUnresolvedness
| NewPoolCoincidenceResolution
| AuthoredReferenceResolution
| DerivedGeneratorInputResolution
| UnexplainedSubjectMotion
| NotEvaluated

Expand All @@ -316,10 +317,17 @@ type NamespaceDeltaDisposition
// The partition the operator ruled is therefore recorded HERE, where it cannot
// be mistaken for an executing mechanism: the wall AUTO-ADMITS a same-declaration
// -identity rebind, a removal of genuinely unused subject membership, an
// explicitly evaluated zero delta, and an authored-reference resolution. Every
// other disposition -- a changed target, new ambiguity, new unresolvedness, new
// pool-coincidence resolution, unexplained subject motion, and NotEvaluated --
// REFUSES unless an exact operator-authored transition admission names it.
// explicitly evaluated zero delta, an authored-reference resolution, and a
// derived-generator-input resolution. Every other disposition -- a changed
// target, new ambiguity, new unresolvedness, new pool-coincidence resolution,
// unexplained subject motion, and NotEvaluated -- REFUSES unless an exact
// operator-authored transition admission names it.
//
// THE FIFTH MEMBER ARRIVED WITH THE 2026-09-08 SPLIT BELOW, and it is recorded
// in this sentence rather than only beside the arm that added it: this paragraph
// is where the partition is stated, so a new auto-admitted disposition recorded
// only at its own declaration would leave one authority answering the same
// question twice.
//
// AuthoredReferenceResolution WAS SPLIT OUT OF NewPoolCoincidenceResolution on
// 2026-08-27, by operator ruling relayed through swift-badger-524, after the
Expand All @@ -338,4 +346,67 @@ type NamespaceDeltaDisposition
// shared projection is wanted at that point, it belongs beside the wall that
// computes it, with the consumer that makes it load-bearing.

// DerivedGeneratorInputResolution IS THE THIRD STATE OF THAT SAME `0 -> 1`, SPLIT OUT
// on 2026-09-08 by operator ruling, and it is split for the reason the 2026-08-27
// split was: one symbol was carrying two states with opposite owners and opposite
// repairs. The discriminator the paragraph above names -- THE MODULE'S OWN SOURCE --
// presumes a module that HAS an author. A GENERATED module does not. gunbc#10822 made
// gunbc.recurring_failure_mode.roster derived: its content is produced by reading the
// row directory, so it has no author to consult, `authored_here` is false for every
// binding it will ever acquire, and every new row file was classified as a coincidence
// in the pool. The wall then refused the append that the generator exists to perform --
// measured across five lanes and seven changes, where every change adding a row MODULE
// refused and every change editing an existing row passed.
//
// THE ADMISSIBLE FACT IS NOT "THE MODULE IS GENERATED", AND THAT DISTINCTION IS THE
// WHOLE ARM. Admitting a category would auto-admit every binding any generated module
// ever acquires, on the one surface where a wrong binding has no human reader -- the
// state-space conflation this file warns about, committed in the opposite direction.
// What is admissible is a binding that is THE MECHANICAL IMAGE OF THE GENERATOR'S
// DECLARED INPUT RELATION: the derived roster's input is the row directory, so a
// binding to a module that is a member of that directory is the deterministic
// consequence of a file the change adds, and is decidable from the generator's own
// declared inputs rather than from a reader's judgement. A generated module acquiring a
// binding its generator's inputs do NOT explain remains NewPoolCoincidenceResolution
// and remains refused; that refusal is the arm's positive control, not a leftover.
//
// IT ANSWERS FOR ONE GENERATOR, AND THE PROSE ABOVE WOULD OTHERWISE READ AS THOUGH
// IT GENERALIZED. The realization opens by refusing every module that is not the
// failure-mode roster, so a SECOND derived module with declared inputs is refused by
// this wall exactly as the first one was, and the repair would be someone editing
// the predicate to name it. That is a hand-maintained membership list where each new
// member costs an edit -- the shape gunbc#10822 has just finished deleting one layer
// up -- and it is disclosed here rather than discovered by the next author, who would
// otherwise meet a refusal and read an authority claiming to be about generators'
// declared inputs in general.
//
// THE NARROWNESS IS NOT LAZINESS, AND THE REASON IS THE TRIGGER. A general arm needs
// a carrier where a generator DECLARES ITS INPUT RELATION, and none exists:
// gunbc.generated_artifact's GeneratedArtifact is a closed coproduct of artifact
// IDENTITIES and carries no inputs at all, so there is nothing for a general
// predicate to consult. Inventing that carrier inside a required-gate repair would be
// modelling a substrate concept to unblock a wall, which is the wrong order. So the
// next rung is that carrier: when a generator's declared input relation is modeled,
// this predicate reads it and stops naming a module. Until then the honest reading is
// ONE generator, decided from ITS OWN constants rather than from a literal spelled
// here -- which is why it is a narrow arm and not a special case.
//
// THE RESIDUAL RISK, STATED RATHER THAN LEFT FOR A READER TO FIND. This arm trusts
// the generator's DECLARED inputs, and what it actually checks is the declaration,
// not the generator's behaviour. If a generator's implementation ever drifts from
// what it declares -- reading a second directory, or emitting a binding no input
// explains -- the wall auto-admits against a stale premise and says nothing, because
// the premise is exactly what it is not in a position to re-derive. That is an
// honest boundary rather than a rung: it is the same class of fact as any other
// declared-and-not-enforced input relation, and the ceiling is a generator whose
// declared inputs ARE its inputs by construction. Until that exists, the mitigation
// is that the declaration and the implementation sit in one module, so drift is a
// same-file edit rather than an action at a distance.
//
// SO THE PARTITION THE OPERATOR RULED GAINS ONE AUTO-ADMITTED MEMBER and loses none.
// The membership arm already reached this answer for the same files -- an added row
// edge auto-admits as ExplicitlyEvaluatedZeroDelta, "reached by a name this module
// authors" -- so before this arm the two arms disagreed about ONE file, which is the
// tell that the disposition and not the population was wrong.

data interlock_ruling_date: NonEmptyStr = "2026-08-26" as NonEmptyStr
2 changes: 1 addition & 1 deletion dag/gunbc/derived_row_roster_seed_growth.dag
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ data derived_row_roster_seed_growth_justification: SeedGrowthJustification = See
DeclarationRef { module_path: "v1_compiler.cli_run.rostered_row_join.file_roster_join_tests", decl_name: "roster_member_without_a_file_refuses", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.rostered_row_join.file_roster_join_tests", decl_name: "equal_file_and_roster_sets_are_silent", field: WholeDeclaration }
],
reason: "WHY RUST RATHER THAN .dag: the substrate has no directory enumeration sufficient to BIND each sibling `.dag` as a typed RecurringFailureMode value. Membership discovery exists (`v2.std.decl_index` `data_decl_type_facts`); value binding does not. Until that grounding lands, a checkout with no committed roster has no module for the three importers (`gunbc.design_ledgers`, `gunbc.ledger_row_coherence`, `test.claim.generated_artifact_merge_driver_real_execution_witness`) and the required parse join reports RosterModuleAbsent on the intended steady state. The host fold lists sibling files, writes gitignored roster.dag atomically, and refuses a shortened list. That is a §7 seed realization of a missing capability, not a scaffold: dissolution is grounded in gunbc.guarantee_stall.roster_re_enumerates_its_own_rows_stall (declaration-value binding), not in a sentence in the Rust module.\n\nThe file-versus-roster join arms are the other half of the same host: a skip in the writer must still refuse. They execute inside run_rostered_row_join on the required parse path (witnesses lane). file_roster_join_tests are the off-path REDs for those arms; they are enumerated because test items are still hand Rust.\n\nWHY ADMITTED AGAINST THE v1 FREEZE: gunbc.v1_maintenance_standing v1_seed_standing admits by PURPOSE. Removing the silent-drop constructor from the failure-mode ledger is an instrument tax every self-host lane was paying (merge hotspot). No new language behavior, no escape hatch, no emitted public surface.\n\nTHE BASE SIDE OF THE DERIVED ROSTER (gunbc#10856, three production items and three test items). is_derived_roster_path, roster_root_prefix and roster_from_path_listing exist because a DERIVED artifact has no base side in a diff and must not be inherited from the head. roster.dag is gitignored and written on the read path, so it can never appear in `git diff --name-status`, and namespace_wave_admission`s baseline -- reconstructed by carrying forward every head record the diff did not touch -- was therefore standing the HEAD`s generated roster up as the BASE`s. That made an ordinary row append read as a name resolving into a pool rather than an authored reference, because the roster`s two sides were the same bytes. They live HERE rather than beside their caller for the reason this module exists: roster_from_path_listing renders through render_roster, the same function the writer uses, so the roster`s bytes keep ONE authority whether the question is asked of a directory or of a base tree listing. They carry the same trigger as the rest of this population -- with declaration-value binding the derivation has no name-list at all, on either side, and these delete with the writer.\n\nRe-derive this list with tools.seed_growth_change_population rather than maintaining a count.",
reason: "WHY RUST RATHER THAN .dag: the substrate has no directory enumeration sufficient to BIND each sibling `.dag` as a typed RecurringFailureMode value. Membership discovery exists (`v2.std.decl_index` `data_decl_type_facts`); value binding does not. Until that grounding lands, a checkout with no committed roster has no module for the three importers (`gunbc.design_ledgers`, `gunbc.ledger_row_coherence`, `test.claim.generated_artifact_merge_driver_real_execution_witness`) and the required parse join reports RosterModuleAbsent on the intended steady state. The host fold lists sibling files, writes gitignored roster.dag atomically, and refuses a shortened list. That is a §7 seed realization of a missing capability, not a scaffold: dissolution is grounded in gunbc.guarantee_stall.roster_re_enumerates_its_own_rows_stall (declaration-value binding), not in a sentence in the Rust module.\n\nThe file-versus-roster join arms are the other half of the same host: a skip in the writer must still refuse. They execute inside run_rostered_row_join on the required parse path (witnesses lane). file_roster_join_tests are the off-path REDs for those arms; they are enumerated because test items are still hand Rust.\n\nWHY ADMITTED AGAINST THE v1 FREEZE: gunbc.v1_maintenance_standing v1_seed_standing admits by PURPOSE. Removing the silent-drop constructor from the failure-mode ledger is an instrument tax every self-host lane was paying (merge hotspot). No new language behavior, no escape hatch, no emitted public surface.\n\nTHE BASE SIDE OF THE DERIVED ROSTER (gunbc#10856, three production items and three test items). is_derived_roster_path, roster_root_prefix and roster_from_path_listing exist because a DERIVED artifact has no base side in a diff and must not be inherited from the head. roster.dag is gitignored and written on the read path, so it can never appear in `git diff --name-status`, and namespace_wave_admission`s baseline -- reconstructed by carrying forward every head record the diff did not touch -- was therefore standing the HEAD`s generated roster up as the BASE`s. That made an ordinary row append read as a name resolving into a pool rather than an authored reference, because the roster`s two sides were the same bytes. They live HERE rather than beside their caller for the reason this module exists: roster_from_path_listing renders through render_roster, the same function the writer uses, so the roster`s bytes keep ONE authority whether the question is asked of a directory or of a base tree listing. They carry the same trigger as the rest of this population -- with declaration-value binding the derivation has no name-list at all, on either side, and these delete with the writer.\n\nRe-derive this list with tools.seed_growth_change_population rather than maintaining a count.\n\nROSTER_MODULE WAS ADDED 2026-09-09 AND IT REMOVES A CONSUMER'S GUESS RATHER THAN ADDING CAPABILITY HERE. The wave-admission wall recovered this module's own roster module name by stripping `.dag` off ROSTER_BASENAME and substituting a default when the suffix was absent -- a fabricated plausible name on an AUTO-ADMISSION path, where the consequence of the guess is a comparison that silently succeeds against a name nobody declares rather than a refusal. The name belongs to the generator that emits the module, so it is declared here and consumed there: one constant added, one recovery and one default deleted, and no new host capability. It dissolves with this row's existing trigger, unchanged.",
owning_dissolution_lane: "v1-hand-queue-drain" as RoadmapNodeId,
trigger: "THE SUBJECT IS THESE DECLARATIONS, and they retire with declaration introspection sufficient to BIND a discovered data declaration as a typed value of its declared type — the same capability named by gunbc.guarantee_stall.roster_re_enumerates_its_own_rows_stall — at which point the host fold and the file-join arms DELETE because there is no authored or derived name-list to omit a row from. A differently named hand writer is not dissolution: it is this obligation under a new key. Registering roster.dag on gunbc.generated_artifact does not discharge this: that would restore heal/drift rewrite of a gitignored file. data_decl_type_facts already exists and does not discharge a trigger that names BINDING.",
current_boundary: "v1_compiler.cli_run.derived_row_roster is reached from run_required_wave_admission (is_derived_roster_path, roster_root_prefix and roster_from_path_listing, which is the phase`s base side and the only consumer of those three), collect_dag_files_result, collect_dag_files_tolerant (write errors ignored), main.rs collect_dag_files, compiler_tests collect_dag_recursive, and run_dag_parse_sweep (the loud required-CI writer). join_row_files_to_roster_members is reached only from join_recurring_failure_mode_files_to_roster inside run_rostered_row_join. The derived file is gitignored and is not a gunbc.generated_artifact. Docs gate main agrees only DesignRungDropsArtifact."
Expand Down
Loading
Loading