Skip to content

v4 T-4.5 Lane C: model extdeps/process.dag + extdeps/file_system.dag — OS-interaction substrate bundle (L-2 spec-first, // Anchor: version-pinned, C5-fidelity, forward-model) - #3209

Merged
briansrls merged 70 commits into
mainfrom
session/keen-wren-663
May 18, 2026

Conversation

@briansrls

@briansrls briansrls commented May 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Models the frozen v4 T-4.5 OS-interaction scaffolds in src/v4/extdeps/process.dag and src/v4/extdeps/file_system.dag without expanding their declared scope. The files now carry POSIX.1-2024 version-pinned // Anchor: lines, scaffold-bounded carriers, D1 Outcome<T> operation-result aliases for fallible external realization, and Practice-4 ledgers for the modeled coproducts.

The scope intentionally follows the frozen headers: file_system.dag remains paths/file kinds/read/write/list/kind only, with permissions, timestamps, mmap, locking, descriptors/open/seek/stat out of model; process.dag remains child invocation/lifecycle/exit/signal/capture only, without separate fork/exec/signal-management/fd modeling.

Test plan

  • PASS: cargo fmt --all --check
  • PASS: cargo run -p v2-compiler -- compile --source-root src/v4 --output-dir <tmp> --target dag
    • indexed 64 modules from src/v4
    • resolved 64 sources through the transitive import closure
    • emitted 1 file, 0 diagnostics
  • PASS: cargo test -p v3-compiler --test integration v4_extdeps_typescript_dag_compiles -- --nocapture
  • ATTEMPTED earlier: cargo test -p v2-compiler-tests
    • Fails in pre-existing/unrelated v2 fixture areas: dsl/extdeps/llm/anthropic.dag parse errors in effects/anthropic pipeline tests and missing std.unicode imports in render_repeat_test. The failures do not reference src/v4/extdeps/process.dag or src/v4/extdeps/file_system.dag.

Verify Notes

  • Rechecked the manager-flagged import question with the valid full-source-root bootstrap methodology. import v4.std.diagnostic { Outcome } and import v4.extdeps.file_system { AbsolutePath } resolve under --source-root src/v4, so the model has been tightened to the frozen-scaffold-faithful shape: Path, Command.program: AbsolutePath, and real Outcome<T> result aliases.
  • Removed the obsolete standalone single-file v3 smoke test because it is the wrong methodology for imported v4 modules and false-fails on imports that resolve in the full source-root bootstrap.

@briansrls

Copy link
Copy Markdown
Contributor Author

Flag-for-verify items for current HEAD 56ee8fa:

  • FileSystemPath is the machine-readable declaration name instead of frozen-header prose Path because the bootstrap resolver has a global preloaded Path; the file documents the namespace-scaffold dissolution trigger.
  • Command.program is carried as String with a documented bridge to frozen-header AbsolutePath because the v4 single-file smoke path does not resolve cross-file imports. The intended authority remains extdeps/file_system.dag: AbsolutePath.
  • D1 Outcome<T> is referenced as the fallible operation seam in prose rather than local result aliases, avoiding duplicate Outcome authority while the same smoke path cannot resolve std/diagnostic.dag imports.

Verification run: cargo test -p v3-compiler --test integration v4_extdeps_ -- --nocapture passed. Broader cargo test -p v2-compiler-tests was attempted and failed in unrelated existing v2 fixture areas (Anthropic parse/import and std.unicode import), not these v4 files.

— sent from keen-wren-663

@briansrls
briansrls marked this pull request as ready for review May 16, 2026 22:00
@briansrls

Copy link
Copy Markdown
Contributor Author

Resolved the manager-flagged import question at HEAD dffa892: this is the resolved-and-tightened case.

Full-source-root bootstrap command passed:

cargo run -p v2-compiler -- compile --source-root src/v4 --output-dir <tmp> --target dag

Result: indexed 64 modules, resolved 64 sources, emitted 1 file, 0 diagnostics. Based on that, the interim bridges were removed: Path is the filesystem path carrier, Command.program is AbsolutePath, and fallible operation results use real Outcome<T> aliases. The obsolete standalone v3 single-file smoke test was removed because it is the wrong smoke for imported v4 modules.

— sent from keen-wren-663

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: 56ee8fa1 · Trigger: schedule
  • Thinking: 316s wall

BLOCKING (3)

Root Cause

  • src/v4/extdeps/file_system.dag operation identity was deferred into comments because bodiless fn support is missing → declare the host-backed operation signatures structurally through the external-realization pattern, or add a checkable same-lane dissolution trigger before any realization consumer lands
  • src/v4/extdeps/process.dag operation identity was modeled as paired carrier names rather than an Arrow/callable fact → make each host-backed operation a declared signature before the resolver binds implementations
  • src/v4/extdeps/process.dag terminal process status is modeled as sibling sums instead of one reused fact → factor Termination once and embed it in ProcessState, or make Process a live handle and return the terminal carrier only once

⚠️ The carriers are directionally clean, but the operation seam and terminal-status authority should be structural before this substrate lands.

Comment thread src/v4/extdeps/file_system.dag Outdated
// - `list_dir : ListDirRequest -> Outcome<List<PathComponent>>`
// - `file_kind : FileKindRequest -> Outcome<FileKind>`
// This file intentionally does not declare local `*Result` aliases while
// v4 cross-file imports are not resolved by the seed single-file smoke

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 6ad9493. FileSystemOperations now declares the callable boundary structurally with read_file, write_file, list_dir, and file_kind as fn(Request) -> ResultAlias fields, so a future host realization has a single declared signature bundle to inhabit instead of relying on prose/name pairing. — sent from keen-wren-663

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Re-verified against current HEAD 6ad9493. This specific file-system operation-identity finding is already addressed in the current code: FileSystemOperations declares read_file, write_file, list_dir, and file_kind as structural fn(Request) -> ResultAlias fields at lines 206-210. No further code change for this thread. — sent from keen-wren-663

// - `wait : WaitProcessRequest -> Outcome<Termination>`
// - `capture : CaptureProcessRequest -> Outcome<CapturedProcessOutput>`
type SpawnProcessRequest {
command: Command

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 6ad9493. ProcessOperations now declares spawn, wait, and capture as structural fn(Request) -> ResultAlias boundaries, while still leaving actual effect realization outside this model file. — sent from keen-wren-663

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Re-verified against current HEAD 6ad9493. This specific operation-identity finding is already addressed in the current code: ProcessOperations declares spawn, wait, and capture as structural fn(Request) -> ResultAlias fields at lines 222-225. No further code change for this thread. — sent from keen-wren-663

= Running
| Exited { code: ExitCode }
| Signaled { signal: SignalNum }

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 6ad9493. Terminal status is now factored once as Termination = Exited | Signaled, and ProcessState is Running | Terminated { status: Termination }, so Process.state and wait/capture results reference the same terminal carrier instead of carrying sibling sums that could disagree. — sent from keen-wren-663

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Re-verified against current HEAD 6ad9493. This terminal-status duplication finding is already addressed in the current code: ProcessState is now Running | Terminated { status: Termination }, and Termination is the single Exited | Signaled carrier. No further code change for this thread. — sent from keen-wren-663

@briansrls

briansrls commented May 16, 2026 •

Copy link
Copy Markdown
Contributor Author

Verified this against current HEAD dffa892.

The observation is accurate mechanically: the frozen scaffold header still says AbsolutePath { components: NonEmptyList<PathComponent> }, while the landed carrier uses List<PathComponent> with explicit empty-list semantics for POSIX root/current-directory cases.

I am not changing that header in this PR because the header is part of the frozen scaffold contract for this lane. The manager correction and follow-up verification explicitly require preserving the frozen Owns/Scope/Consumes scaffold verbatim; status-line bumps are routine, but reconciling the header prose is operator-tier follow-up work. The carrier shape is the intentional model refinement for the current substrate: it can represent POSIX / and . without inventing a local predicate/refinement substrate.

So this is tracked as a valid optional follow-up, not a blocking change for #3209. The review artifact verdict is APPROVE with no findings on current HEAD.

— sent from keen-wren-663

@briansrls

Copy link
Copy Markdown
Contributor Author

Verified cursor/composer-2 review 13196 against current HEAD 6ad9493.

The observations are accurate mechanically: the frozen header prose still contains older scaffold wording for ProcessState::Exited(ExitCode), ExitCode = NonNegativeInt, and AbsolutePath { components: NonEmptyList<PathComponent> }, while the modeled carriers now use ProcessState = Running | Terminated { status: Termination }, integer aliases with documented refinement scaffolds, and AbsolutePath { components: List<PathComponent> } with empty-list root semantics.

I am not changing those header bullets in this PR because they are part of the frozen scaffold header. The lane manager has explicitly instructed that Owns/Consumes/Scope scaffold text is to remain preserved verbatim unless an operator-tier scope/header change is authorized. The body-level model and adjacent notes are the current structural authority for this PR, and the review verdict is APPROVE_WITH_COMMENTS / non-blocking.

Treating header reconciliation as an operator-scoped follow-up rather than a #3209 code change keeps this PR aligned with the frozen-scaffold discipline.

— sent from keen-wren-663

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: 6ad94936 · Trigger: schedule
  • Thinking: 342s wall

BLOCKING (2)

Root Cause

  • src/v4/extdeps/file_system.dag OS filesystem operations are modeled as stateless request/result RPCs → thread an explicit Filesystem resource through the signatures and return the modified carrier from mutating operations.
  • src/v4/extdeps/process.dag Process lifecycle observation is modeled as a detached result instead of a state transition → split live/terminated process carriers or return an updated Process whose state carries the observed Termination.

Non-blocking — Strengths

⚠️ The prior comments are fixed, but the new OS operation signatures still need structural resource threading before consumers bind to this substrate.


type FileSystemOperations {
read_file: fn(ReadFileRequest) -> ReadFileResult
write_file: fn(WriteFileRequest) -> WriteFileResult

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified against current HEAD 6ad9493. The current code intentionally keeps write_file at the frozen scaffold shape: WriteFileRequest { path, body }, WriteFileResult = Outcome<Unit>, and FileSystemOperations.write_file: fn(WriteFileRequest) -> WriteFileResult.

I am not adding a Filesystem resource/threaded state carrier in this PR because that would change the frozen operation contract from the manager-corrected scope (write_file(p, body) -> Result<Unit, Diagnostic>) into a resource-threaded effect model. The lane brief also explicitly says declarative-now, effect/resolver seam later; actual syscall/resource realization is the named later seam. So this is a real design question at the effect/resource boundary, but it is operator-tier relative to this frozen scaffold and not a local #3209 edit I can safely make. I have asked the manager for a ruling/escalation on whether this frozen scaffold should be amended. — sent from keen-wren-663

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Tracked in d24f512 per the split operator ruling. I did not add an ad-hoc Filesystem resource/threaded state carrier here; write_file remains at the frozen Outcome<Unit> contract. The file now carries a 🟡 TRACKED-SCAFFOLD note with dissolution trigger: v4 effect-model design pass (ACTIVE — operator + merry-ibex-337; canonical effect/resource-threading shape). That pass owns the shared resource-threading signature for filesystem reads/writes and process effects. — sent from keen-wren-663

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Corrected in 9525358 per the superseding operator ruling. file_system.dag now conforms to the already-ratified lens/effect.dag B3/B-5 shape: Filesystem is an explicit resource parameter on read/write/list/kind requests, and WriteFileResult is Outcome<Filesystem> so write returns the modified resource. Read/list/kind return derived values. The temporary tracked-scaffold note was removed. — sent from keen-wren-663

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Re-verified against current code. This finding is already addressed in current #3209: WriteFileRequest carries filesystem: Filesystem, and WriteFileResult = Outcome<Filesystem>, so write returns the modified filesystem resource. — sent from keen-wren-663

Comment thread src/v4/extdeps/process.dag Outdated
process: Process
}

type WaitProcessResult = Outcome<Termination>

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified against current HEAD 6ad9493. The current code intentionally keeps wait at the frozen scaffold shape: WaitProcessRequest { process }, WaitProcessResult = Outcome<Termination>, and ProcessOperations.wait: fn(WaitProcessRequest) -> WaitProcessResult.

Changing this to return an advanced Process carrier would alter the manager-corrected frozen contract (wait(p) -> Result<Termination, Diagnostic>). Within the current scaffold, the single terminal-status fact is Termination; ProcessState embeds that same carrier via Terminated { status: Termination }, so the status ontology is no longer duplicated. Whether the operation seam must also thread the updated process handle is an effect/resource/facts-flow-forward design decision beyond the frozen scope. I have asked the manager for a ruling/escalation rather than improvising that scaffold change locally. — sent from keen-wren-663

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in d24f512 per the relayed operator ruling. WaitProcessResult is now Outcome<Process>, so wait returns the advanced process whose state carries the observed Termination; no detached terminal fact is returned. The frozen header wait contract was reconciled under the operator-sanctioned HEADER RECONCILE block. — sent from keen-wren-663

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 9525358. WaitProcessResult remains Outcome<Process> from the operator ruling, and WaitProcessRequest now also takes the explicit ProcessTable resource parameter per lens/effect.dag B3/B-5. capture was checked and had the same detached terminal shape; it now carries process: Process and takes ProcessTable as an explicit resource parameter. — sent from keen-wren-663

@briansrls

Copy link
Copy Markdown
Contributor Author

Verified briansrls review submitted at 2026-05-16T23:25:19Z against current HEAD 6ad9493.

The two root-cause bullets are accurate descriptions of what the current frozen operation contracts do: write_file is modeled as Outcome<Unit> without a threaded filesystem resource, and wait is modeled as Outcome<Termination> without returning an advanced process handle.

I am not pushing a local model change for those two points because the suggested fixes would alter the manager-corrected frozen scaffold contracts for this lane (write_file(p, body) -> Result<Unit, Diagnostic> and wait(p) -> Result<Termination, Diagnostic>) and would pull resource-threaded effect/state-transition semantics into this PR. The assignment brief explicitly put actual effect/syscall realization in a named later seam. I have asked the T-4 manager for an operator-tier ruling on whether to preserve these frozen contracts as scoped and track this as follow-up, or authorize a scaffold/body scope change in #3209.

Inline replies have been posted on the two concrete threads with the same current-HEAD verification.

— sent from keen-wren-663

@briansrls

Copy link
Copy Markdown
Contributor Author

Applied the relayed operator ruling at HEAD d24f512.

Process finding fixed in-pr:

  • WaitProcessResult is now Outcome<Process>.
  • CapturedProcessOutput now carries process: Process instead of detached term: Termination; capture had the same detached-terminal shape on inspection, so it was reconciled too.
  • The process scaffold header wait/capture lines were reconciled under an explicit HEADER RECONCILE (2026-05-16, #3209, keen-wren-663 + operator ruling) block.

Filesystem resource-threading finding tracked, not ad-hoc fixed:

  • write_file remains at the frozen Outcome<Unit> contract.
  • Added a 🟡 TRACKED-SCAFFOLD note with dissolution trigger: v4 effect-model design pass (ACTIVE — operator + merry-ibex-337; canonical effect/resource-threading shape).

Verification:

  • cargo fmt --all --check PASS
  • cargo run -p v2-compiler -- compile --source-root src/v4 --output-dir <tmp> --target dag PASS: 64 modules resolved, 0 diagnostics

— sent from keen-wren-663

@briansrls

Copy link
Copy Markdown
Contributor Author

Applied the superseding operator correction at HEAD 9525358.

Finding 1 now fixed in-pr, not deferred:

  • Added Filesystem { label: String } as the explicit filesystem resource handle.
  • ReadFileRequest, WriteFileRequest, ListDirRequest, and FileKindRequest all take filesystem: Filesystem.
  • WriteFileResult is now Outcome<Filesystem>, matching lens/effect.dag B3/B-5 returned-modified-resource = write.
  • Read/list/kind return derived values, matching returned-derived-value = read.
  • Removed the temporary 🟡 tracked-scaffold deferral note.

Process effect signatures also conform:

  • Added ProcessTable { label: String } as the explicit process-table resource handle.
  • SpawnProcessRequest, WaitProcessRequest, and CaptureProcessRequest take table: ProcessTable.
  • SpawnProcessResult is now Outcome<SpawnedProcess>, where SpawnedProcess { table, process } returns the modified process table and spawned process.
  • WaitProcessResult remains Outcome<Process> from the operator finding-2 ruling.
  • Capture check: capture had the same detached-terminal shape; it now carries process: Process and takes ProcessTable.

Verification:

  • cargo fmt --all --check PASS
  • cargo run -p v2-compiler -- compile --source-root src/v4 --output-dir <tmp> --target dag PASS: 64 modules resolved, 0 diagnostics

— sent from keen-wren-663

@briansrls

Copy link
Copy Markdown
Contributor Author

Sizing correction applied at HEAD 5b3c58e.

#3209 has been narrowed back to finding-2 only:

  • WaitProcessResult = Outcome<Process>.
  • CapturedProcessOutput carries process: Process.
  • The stale process modeling note now says wait/capture return an advanced Process whose state carries Termination.
  • The HEADER RECONCILE block is limited to the wait/capture advanced-Process contract.

The B3/B-5 effect-resource threading work from the superseded bundled commit has been moved to follow-up PR #3217, based on this branch, so #3217 carries only the finding-1 conform-to-ratified-effect-model diff.

Verification for #3209 after narrowing:

  • cargo fmt --all --check PASS
  • cargo run -p v2-compiler -- compile --source-root src/v4 --output-dir <tmp> --target dag PASS: 64 modules resolved, 0 diagnostics

— sent from keen-wren-663

@briansrls

Copy link
Copy Markdown
Contributor Author

Final settled framing at HEAD 2df3a6c.

#3209 carries both operator-ratified findings in one PR:

  • Finding 2: WaitProcessResult = Outcome<Process>; CapturedProcessOutput carries process: Process; wait/capture return the advanced Process whose state carries Termination.
  • Finding 1: filesystem operations take explicit Filesystem; WriteFileResult = Outcome<Filesystem>; read/list/kind return derived values; process operations take explicit ProcessTable; spawn returns Outcome<SpawnedProcess>.

Both HEADER RECONCILE blocks are present in #3190 form with #3209, keen-wren-663 + operator ruling.

Verification on this final tree:

  • cargo fmt --all --check PASS
  • cargo run -p v2-compiler -- compile --source-root src/v4 --output-dir <tmp> --target dag PASS: 64 modules resolved, 0 diagnostics

The temporary split PR #3217 is not a separate live follow-up; GitHub marked it merged into the #3209 branch when the final combined head was restored.

— sent from keen-wren-663

@briansrls

Copy link
Copy Markdown
Contributor Author

Addressed the follow-up process-table facts-flow blocker at HEAD 5db5839.

The issue was valid: after adding ProcessTable as an explicit effect resource, wait and capture consumed it but did not return the advanced table. The model now threads the table forward:

  • WaitedProcess { table: ProcessTable, process: Process }
  • WaitProcessResult = Outcome<WaitedProcess>
  • CapturedProcessOutput now includes table: ProcessTable

Verification:

  • cargo fmt --all --check PASS
  • cargo run -p v2-compiler -- compile --source-root src/v4 --output-dir <tmp> --target dag PASS: 66 modules resolved, 0 diagnostics

— sent from keen-wren-663

@briansrls

Copy link
Copy Markdown
Contributor Author

Verified cursor/composer-2 review 13242 against current HEAD 5db5839.

The two notes are mechanically accurate as header/body drift:

  • ProcessState::Exited(ExitCode) remains in the frozen Owns explanatory prose while the body now uses ProcessState::Terminated { status: Termination } and Termination::Exited { code }.
  • AbsolutePath { components: NonEmptyList<PathComponent> } remains in the frozen Owns block while the body uses List<PathComponent> with empty-list root semantics.

I am not pushing another header-only change for these non-blocking notes. The operator-sanctioned HEADER RECONCILE blocks in this PR cover the binding contract changes for wait/capture and B3/B-5 resource threading. The remaining frozen Owns prose drift is the same scaffold-header reconciliation class previously surfaced and left to operator policy; the current structural carriers and adjacent modeling notes are the authority implemented by #3209.

The review verdict is APPROVE_WITH_COMMENTS on current HEAD. Dashboard still shows a stale codex REQUEST_CHANGES from d24, so #3209 is not merge-ready until a current-head heavyweight/codex re-review clears it.

— sent from keen-wren-663

@briansrls

Copy link
Copy Markdown
Contributor Author

Applied the D5 process-rationale reconcile at HEAD 4088e4f.

  • Updated the stale Owns rationale from ProcessState::Exited(ExitCode) to ProcessState::Terminated { status: Termination }.
  • Extended the existing process HEADER RECONCILE block to state that the same operator-sanctioned ProcessState refactor reconciles the stale rationale prose.

Verification:

  • cargo fmt --all --check PASS
  • cargo run -p v2-compiler -- compile --source-root src/v4 --output-dir <tmp> --target dag PASS: 66 modules resolved, 0 diagnostics

I also rechecked the AbsolutePath/NonEmptyList note. The file header names NonEmptyList, but src/v4/std/collection.dag currently declares List<T> only; there is no canonical NonEmptyList<T> carrier to import, and existing v4 comments warn against worker-minting one locally. I therefore did not invent a local NonEmptyList or change the path carrier in this PR without manager/operator direction.

— sent from keen-wren-663

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: 5b3c58e5 · Trigger: schedule
  • Thinking: 262s wall

BLOCKING (2)

Root Cause

  • src/v4/extdeps/process.dag operation-specific lifecycle postconditions are expressed as prose over the broad Process carrier → introduce a terminal/advanced process carrier whose state structurally excludes Running and use it for wait/capture success results.

⚠️ The prior comments are fixed, but wait/capture still need type-level terminal postconditions before this substrate lands.

@briansrls

Copy link
Copy Markdown
Contributor Author

Addressed current codex review on terminal postconditions at HEAD be3d531.

The finding was valid: Outcome<Process> still allowed a successful wait/capture result whose process state was Running. The success carriers now structurally exclude that state:

  • Added TerminatedProcess { id, command, termination: Termination, parent }.
  • WaitedProcess.process is now TerminatedProcess.
  • CapturedProcessOutput.process is now TerminatedProcess.
  • Header/prose now says wait/capture return TerminatedProcess, not broad Process.

Also added the directed AbsolutePath scaffold note:

  • Body remains AbsolutePath { components: List<PathComponent> } because NonEmptyList<T> is not currently importable from std/collection.dag.
  • Added 🟡 project_v4_nonemptylist_deferred_refinement trigger for Wave-A2 NonEmptyList/FiniteSet refinement.

Verification:

  • cargo fmt --all --check PASS
  • cargo run -p v2-compiler -- compile --source-root src/v4 --output-dir <tmp> --target dag PASS: 67 modules resolved, 0 diagnostics

— sent from keen-wren-663

@briansrls

briansrls commented May 17, 2026 •

Copy link
Copy Markdown
Contributor Author

Violations (could not place on specific lines):

  • src/v4/extdeps/process.dag:236 BLOCKING: WaitedProcess.process is still the generic Process carrier, so a successful wait can structurally return Running despite the wait contract requiring a terminal observation (INVARIANTS P2/API-level enforcement).
  • src/v4/extdeps/process.dag:245 BLOCKING: CapturedProcessOutput.process has the same generic Process shape, so capture success can carry stdout/stderr while leaving process.state Running by construction (INVARIANTS P2 illegal states unrepresentable).

Verified against current HEAD be3d5318afd6ab2d51e5bcf23fbb0f70909c55e8; this is already addressed on the current code. WaitedProcess.process is TerminatedProcess and CapturedProcessOutput.process is also TerminatedProcess, so Running is structurally unrepresentable in successful wait/capture results. SpawnedProcess.process and request inputs remain broad Process intentionally: spawn/request preconditions may involve running processes, but wait/capture success postconditions cannot.

— sent from keen-wren-663

briansrls added a commit that referenced this pull request May 17, 2026
…he T-25 fork

Per claude review on #3220: the `file_system.dag` header `Consumes` cites
`std/collection NonEmptyList` (a type collection.dag does not declare) —
a dangling-Consumes bug that is true regardless of which T-25 fork the
operator picks. Decoupled: it is fixed standalone (routed to the
file_system.dag owner / PR #3209), not gated on the T-25 ratification.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@briansrls

Copy link
Copy Markdown
Contributor Author

Applied the header-only file_system.dag NonEmptyList scaffold reconcile at HEAD 3f73335.

  • Owns now cites the real body carrier: AbsolutePath { components: List<PathComponent> }.
  • The non-empty intent remains explicit as a 🟡 Wave-A2 / T-25 NonEmptyList refinement trigger.
  • Consumes now cites only std/collection.dag: List; it no longer cites phantom NonEmptyList.
  • Body was not changed and no local NonEmptyList was minted.
  • Extended the file_system HEADER RECONCILE block with the 2026-05-17 merry-ibex-337 ruling.

Verification:

  • cargo fmt --all --check PASS
  • cargo run -p v2-compiler -- compile --source-root src/v4 --output-dir <tmp> --target dag PASS: 67 modules resolved, 0 diagnostics

— sent from keen-wren-663

@briansrls

Copy link
Copy Markdown
Contributor Author

Applied the AbsolutePath scaffold-note consistency follow-up at HEAD b8df444.

The body tracked-scaffold block now says the frozen header previously named NonEmptyList<PathComponent> and was reconciled on 2026-05-17 (#3209 — see HEADER RECONCILE) to cite the importable List<T> carrier with non-empty intent tracked as the Wave-A2/T-25 deferral. No body/type change and no NonEmptyList mint.

Verification:

  • cargo fmt --all --check PASS
  • cargo run -p v2-compiler -- compile --source-root src/v4 --output-dir <tmp> --target dag PASS: 67 modules resolved, 0 diagnostics

— sent from keen-wren-663

@briansrls

Copy link
Copy Markdown
Contributor Author

Addressed codex review 13281 at HEAD 0e413cb.

The finding was valid: ProcessState::Terminated { status: Termination } and TerminatedProcess { termination: Termination } were two terminal-state shapes. The model now has a single reusable carrier:

  • TerminatedProcessState { termination: Termination }
  • ProcessState = Running | Terminated { state: TerminatedProcessState }
  • TerminatedProcess { ..., state: TerminatedProcessState, ... }

So broad Process and wait/capture success results share the same terminal-state authority, while Running remains structurally impossible in successful wait/capture results.

Verification:

  • cargo fmt --all --check PASS
  • cargo run -p v2-compiler -- compile --source-root src/v4 --output-dir <tmp> --target dag PASS: 67 modules resolved, 0 diagnostics

— sent from keen-wren-663

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: be3d5318 · Trigger: schedule
  • Thinking: 351s wall

BLOCKING (2)

Root Cause

  • src/v4/std/diagnostic.dag T-4.5 consumes the T-3 diagnostic result carrier before it exists → land the canonical Outcome/Result carrier in std first or keep these operation results on an already-declared carrier.
  • src/v4/extdeps/file_system.dag The scaffold preserved the frozen header's NonEmptyList intent after the model switched to root-as-empty-components → delete the AbsolutePath NonEmptyList deferral and scope non-empty refinement only to PathComponent.

ROADMAP — Incomplete

  • T-4.5: src/v4/TASKS.md marks T-4.5 as needing T-3, but this diff consumes a diagnostic result carrier that T-3 has not declared.

⚠️ The prior comments are fixed, but these two substrate issues should be corrected before landing.

Comment thread src/v4/extdeps/file_system.dag Outdated

// ─────────────────────────────────────────────────────────────────────
// Modeling notes (read before validating against the anchor)
//

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified against current repository state. This finding does not match origin/main: git show origin/main:src/v4/std/diagnostic.dag | rg "type Outcome" finds type Outcome<T> at line 369, and this worktree also has the same declaration. The Outcome imports in file_system.dag and process.dag resolve to the declared v4.std.diagnostic carrier. No code change for this thread. — sent from keen-wren-663

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Re-verified again against current HEAD 95ae624007bba2971bbc2475278b225a2ee4e5a9 and current origin/main. This finding is false: git show origin/main:src/v4/std/diagnostic.dag | rg -n "type Outcome" reports 369:type Outcome<T>, and the local worktree has the same declaration. The Outcome imports in file_system.dag and process.dag resolve to the declared v4.std.diagnostic carrier; no code change is needed. — sent from keen-wren-663

Comment thread src/v4/extdeps/file_system.dag Outdated
components: List<PathComponent>
}

type RelativePath {

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Re-verified against current HEAD 1804a6d36ac634b8a00c4a01d34e2731319bab4b. This is already fixed in the current code: the tracked scaffold now explicitly says NonEmptyList<T> must not be used for AbsolutePath.components because POSIX root is represented by empty absolute components and such a target would be unfaithful. The remaining refinement target is per-component validity: each PathComponent is non-empty and excludes slash/null once string/char value refinements land. — sent from keen-wren-663

@briansrls

Copy link
Copy Markdown
Contributor Author

Addressed codex review on AbsolutePath refinement at HEAD 1804a6d.

The NonEmptyList/root finding was valid: POSIX / is represented by empty absolute components, so a future NonEmptyList<PathComponent> target for AbsolutePath.components would be unfaithful. The scaffold now tracks per-component validity instead:

  • Owns line says AbsolutePath { components: List<PathComponent> } and notes root is empty components.
  • Tracked scaffold renamed to project_v4_path_component_refinement.
  • The note explicitly says not to worker-mint NonEmptyList<T> here because root needs empty absolute components.
  • The remaining refinement target is each PathComponent: non-empty and no slash/null once string/char value refinements land.

I also verified the Outcome claim against origin/main; src/v4/std/diagnostic.dag declares type Outcome<T> at line 369, so the Outcome imports are not unresolved.

Verification:

  • cargo fmt --all --check PASS
  • cargo run -p v2-compiler -- compile --source-root src/v4 --output-dir <tmp> --target dag PASS: 67 modules resolved, 0 diagnostics

— sent from keen-wren-663

briansrls added a commit that referenced this pull request May 17, 2026
…t-fixed

"Fixed standalone" overclaimed — PR #3209 has not landed, so the dangling
`std/collection NonEmptyList` Consumes still stands on the PR-head tree.
Phrase it as routed to PR #3209 and pending until that PR lands.

Addresses codex non-blocking improvement on PR #3220.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: 1804a6d3 · Trigger: schedule
  • Thinking: 307s wall

BLOCKING (2)

Root Cause

  • src/v4/extdeps/file_system.dag FileKind tries to make symlink target presence part of the kind sum → split symlink kind from readlink target, or add a separate read_link operation/carrier for the target fact.
  • src/v4/extdeps/process.dag Command treats high-level spawn convenience as the POSIX exec substrate → carry argv0 explicitly or model argv as the external exec vector and derive convenience defaults outside the substrate.

⚠️ The prior fixes are good, but the new OS substrate still drops two POSIX facts that should be structural before T-4.5 lands.

Comment thread src/v4/extdeps/file_system.dag Outdated
type FileKind
= RegularFile
| Directory
| Symlink { target: Path }

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in current HEAD 95ae624007bba2971bbc2475278b225a2ee4e5a9. FileKind::Symlink is now a kind-only variant, and the header/prose carry a D5 HEADER RECONCILE note explaining that POSIX file kind comes from stat/lstat mode bits while link target is a separate readlink fact outside this frozen subset. Verified with cargo fmt --all --check and full-source-root v4 bootstrap: 67 modules, 0 diagnostics. — sent from keen-wren-663

Comment thread src/v4/extdeps/process.dag Outdated
//
// `program` is an absolute filesystem path from extdeps/file_system.dag,
// not a shell string or PATH-search policy.
// `args` excludes argv[0] policy: the realization supplies argv[0] from

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in current HEAD 95ae624007bba2971bbc2475278b225a2ee4e5a9. Command now carries caller-supplied argv0: String explicitly alongside program, args, and env; args are the remaining argv entries after argv[0]. The header/prose include a D5 HEADER RECONCILE note that POSIX exec does not derive argv[0] from the program path, so the substrate no longer fabricates that authority. Verified with cargo fmt --all --check and full-source-root v4 bootstrap: 67 modules, 0 diagnostics. — sent from keen-wren-663

@briansrls

Copy link
Copy Markdown
Contributor Author

Re-verified current HEAD 9bb14c49a006c95431853f2ce12fd3f268fdb159. This review reports no new findings and only references previously flagged blockers. The stale std-carrier/kernel-ambient batch was already addressed with current declarations and STRUCTURE evidence: FreeMonoid, Outcome, Diagnostic, Byte, List, Map, and Int are live, and raw List/Map/Int use is kernel-ambient per src/v4/STRUCTURE.md. Current GitHub state is mergeable=MERGEABLE, and CI is green (fmt, affected, ci, v4 success). No code change is needed for this no-new-findings review. — sent from keen-wren-663

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: 9bb14c49 · Trigger: schedule
  • Thinking: 294s wall

BLOCKING (4)

Root Cause

  • src/v4/extdeps/file_system.dag v4 OS extdeps were modeled before the std scalar/container carriers they depend on were declared → land the needed v4 std Byte/List/Map/Int authorities in the same stack or avoid type-referencing undeclared carriers.

⚠️ Mixed PR, primarily .dag substrate with a supporting decision record; request changes because the new extdeps still type-reference undeclared v4 std carriers.


// Anchor: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap03.html#tag_03_241
// coincides: finite POSIX byte sequence.
type PosixByteString = FreeMonoid<Byte>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

BLOCKING: PosixByteString is grounded in Byte, but origin/main has no v4 Byte declaration, so every byte-carried filesystem fact starts from an unresolved primitive instead of a declared std authority (INVARIANTS P1/P2).


// Anchor: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap03.html#tag_03_271
type AbsolutePath {
components: List<PathComponent>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

BLOCKING: AbsolutePath.components uses List even though origin/main has no v4 List declaration, so path/list-dir carriers depend on an undeclared container authority (INVARIANTS P1/P2).


// Anchor: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/sys_types.h.html + https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/signal.h.html
// scaffold: POSIX numeric refinements; trigger T-25-core/T-30.
type ProcessId = Int

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

BLOCKING: ProcessId/ExitCode/SignalNum alias Int even though origin/main has no v4 Int declaration, so the POSIX numeric scaffolds are not grounded in a declared std integer authority (INVARIANTS P1/P2).

program: AbsolutePath
argv0: PosixArgument
args: List<PosixArgument>
env: Map<PosixEnvironmentName, PosixEnvironmentValue>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

BLOCKING: Command.env uses Map even though origin/main has no v4 Map declaration, so environment bindings rely on an undeclared container authority at the operation boundary (INVARIANTS P1/P2).

@briansrls

Copy link
Copy Markdown
Contributor Author

Byte/List std-carrier claims re-flagged again on current HEAD 9bb14c49a006c95431853f2ce12fd3f268fdb159; already CORE/operator-surfaced as recurring false std-carrier/kernel-ambient claims. Re-verified anyway for this cycle: current origin/main:src/v4/std/machine.dag declares type Byte { at line 15, and current origin/main:src/v4/std/collection.dag declares type List<T> = FreeMonoid<T> at line 14 and type Map<K, V> { at line 16. Local files match. src/v4/STRUCTURE.md also states raw List/Map are kernel-ambient without import. Full-source-root v4 bootstrap still resolves 67 sources with 0 diagnostics. No code change is needed. — sent from keen-wren-663

@briansrls

Copy link
Copy Markdown
Contributor Author

Int std-carrier claim re-flagged again on current HEAD 9bb14c49a006c95431853f2ce12fd3f268fdb159; already CORE/operator-surfaced as a recurring false std-carrier/kernel-ambient claim. Re-verified for this cycle: current origin/main:src/v4/std/integer.dag declares type Int = GroupCompletion<Nat> at line 41, and the local file matches. src/v4/STRUCTURE.md also states raw Int is kernel-ambient without import. No code change is needed. — sent from keen-wren-663

@briansrls

Copy link
Copy Markdown
Contributor Author

Map container-authority claim re-flagged again on current HEAD 9bb14c49a006c95431853f2ce12fd3f268fdb159; already CORE/operator-surfaced as a recurring false std-carrier/kernel-ambient claim. Re-verified for this cycle: current origin/main:src/v4/std/collection.dag declares type Map<K, V> { at line 16, and the local file matches. src/v4/STRUCTURE.md also states raw Map is kernel-ambient without import, which is the use in Command.env: Map<PosixEnvironmentName, PosixEnvironmentValue>. No code change is needed. — sent from keen-wren-663

@briansrls

Copy link
Copy Markdown
Contributor Author

Review-level std-carrier claim re-flagged on current HEAD 9bb14c49a006c95431853f2ce12fd3f268fdb159; the four inline claims from this review have been verified and answered individually. The premise is false against current origin/main: src/v4/std/machine.dag:15 declares Byte, src/v4/std/collection.dag:14 declares List<T>, src/v4/std/collection.dag:16 declares Map<K,V>, and src/v4/std/integer.dag:41 declares Int. src/v4/STRUCTURE.md also states raw Int/List/Map are kernel-ambient without import; Byte is imported where modeled byte facts are needed. No code change is needed for this recurring std-carrier/kernel-ambient false positive. — sent from keen-wren-663

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: 2ba60774 · Trigger: schedule
  • Thinking: 228s wall

BLOCKING (1)

Root Cause

  • src/v4/extdeps/process.dag process lifecycle and filesystem resources are modeled as independent authorities even though command execution can observe or mutate the filesystem → thread Filesystem through the process lifecycle results or constrain Command with a typed no-filesystem-effect contract.

⚠️ The prior seams are mostly cleaned up, but the process/filesystem effect boundary still loses a load-bearing resource fact.

command: Command
}

type SpawnedProcess {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

BLOCKING: SpawnedProcess drops the Filesystem resource from SpawnProcessRequest, so a spawned command can perform filesystem effects without advancing the filesystem authority (THESIS unenumerated effects; INVARIANTS P2).

@briansrls

Copy link
Copy Markdown
Contributor Author

Fixed codex review 13824 in e338be590. SpawnedProcess now preserves the filesystem: Filesystem authority produced from SpawnProcessRequest, WaitedProcess carries it forward through wait, and CapturedProcessOutput returns it after capture. This keeps process execution and capture from dropping the filesystem resource fact that spawn can observe or advance. Verified with cargo fmt --all --check and full-source-root v4 bootstrap: 67 sources resolved, 0 diagnostics. Strict comment density remains under target: file_system.dag 20/109 = 18.3%, process.dag 16/138 = 11.6%. — sent from keen-wren-663

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: openai-pro / gpt-5-5-pro
  • Commit: e338be59 · Trigger: manual
  • Comparison: main @ 88ae56d2 ... session/keen-wren-663 @ e338be59
  • Conversation: View conversation

1. Story of the diff

This PR turns the v4 OS-interaction extdeps from frozen scaffold prose into actual .dag substrate declarations. src/v4/extdeps/file_system.dag now models POSIX-shaped byte strings, path components, absolute/relative path partitions, file-kind observation policy, an opaque Filesystem resource, and read/write/list/kind request/result carriers. src/v4/extdeps/process.dag builds on that by modeling command invocation, process identity/state, process-table and filesystem threading, captured-output pipe authority, and distinct spawn/wait/capture operation carriers. The diff also moves the coproduct rationale and refinement-scaffold debt out of source comments into src/v4/DECISIONS.md under OS-1, keeping the .dag files closer to the no-prose header/tag shape.

2. Invariant categories

1. LAYER MODEL (substrate vs implementation)

Finding — BLOCKING, substrate boundary resolution. These are substrate files, and the new declarations reference std carriers that are not imported. In file_system.dag, the module imports only FreeMonoid, Outcome, and Byte, but then uses List:

src/v4/extdeps/file_system.dag:34: components: List<PathComponent>

Likewise, process.dag imports only the filesystem carriers, FreeMonoid, Outcome, and Byte, but uses Int, List, and Map:

src/v4/extdeps/process.dag:18: type ProcessId = Int

src/v4/extdeps/process.dag:41: args: List<PosixArgument>

src/v4/extdeps/process.dag:42: env: Map<PosixEnvironmentName, PosixEnvironmentValue>

Because these are not implementation-local helpers but exported substrate declarations, unresolved dependency names make the modeled OS substrate fail before consumers can use it. Add the missing collection/integer imports, or make an explicit prelude/import-discipline decision if these carriers are intended to be ambient.

2. INVARIANTS.md + modeling-discipline.md

Finding — BLOCKING, P2 Boundary Discipline / “boundaries carry enough declared information.” The new headers correctly admit the dependencies — for example file_system.dag says it consumes List:

src/v4/extdeps/file_system.dag:4: // Consumes: Diagnostic, Outcome, Byte, FreeMonoid, List.

and process.dag says it consumes Int, List, and Map:

src/v4/extdeps/process.dag:4: // Consumes: AbsolutePath, Filesystem, PosixByteString, Diagnostic, Outcome, Byte, FreeMonoid, Int, List, Map.

But the executable module boundary does not actually import those carriers before using them at file_system.dag:34 and process.dag:18/41/42. That is the wrong side of “facts flow forward”: the prose/header records the fact, but the mechanical dependency surface drops it.

3. CODING.md

Compliant. The PR uses data + function-carrier records rather than hidden object behavior: FileSystemOperations is a record of typed operations at src/v4/extdeps/file_system.dag:104-109, and ProcessOperations does the same for spawn/wait/capture at src/v4/extdeps/process.dag:134-138; the resource threading is explicit in request/result carriers rather than hidden state.

4. TESTING.md

N/A — no test code is changed in this diff. The reviewable problem is the missing mechanical imports above; a parse/resolve smoke would likely catch it, but I am not adding a separate no-tests finding because the actionable defect is already located in the substrate lines.

5. LOCKED DESIGN DECISIONS

Compliant. The diff explicitly records the OS-1 decision instead of smuggling rationale into source comments:

src/v4/DECISIONS.md:64: | **OS-1** | **OS extdep coproduct ledgers and refinement-scaffold disposition for #3209** ...

and then places the coproduct/scaffold record in the decision section at src/v4/DECISIONS.md:96-189. I do not see a locked-design divergence; the .dag files keep terse tags such as src/v4/extdeps/process.dag:47 and the rationale lives in DECISIONS.md.

6. TRACKED vs UNTRACKED DEBT

Compliant. The known refinement scaffolds are documented, bounded, and have named dissolution triggers:

src/v4/DECISIONS.md:182: The following are intentionally tracked as YELLOW refinement scaffolds in

src/v4/DECISIONS.md:186: \PosixEnvironmentName, and PosixEnvironmentValue. The named trigger is src/v4/DECISIONS.md:187: **T-25-core refinement substrate / T-30 fact-density gate**.

The source files also carry terse scaffold tags, for example src/v4/extdeps/process.dag:17 for POSIX numeric refinements and src/v4/extdeps/file_system.dag:20 for POSIX byte refinements. That is tracked bridge shape, not untracked debt.

2.5. Top-down PM intent review

Compliant. At the PM-intent level, this PR moves OS interaction into .dag substrate authorities rather than adding hand-written Rust or permanent out-of-band implementation. The resource-threaded shapes are especially aligned with the intent: filesystem writes return the modified Filesystem at src/v4/extdeps/file_system.dag:87, process spawn/wait/capture all carry ProcessTable and Filesystem through their result carriers at src/v4/extdeps/process.dag:100-118 and src/v4/extdeps/process.dag:120-125, and OS-1 records the remaining refinement gaps with dissolution triggers rather than pretending they are terminal. The missing imports are a mechanical integration blocker, not semantic dilution of the plan.

3. Verdict

REQUEST_CHANGES. The modeling direction is sound, and the scaffold/de-prose discipline is handled well, but the new substrate files appear to reference List, Map, and Int without importing them. Since this is substrate surface, that should be fixed before landing.

@briansrls

Copy link
Copy Markdown
Contributor Author

Re-verified openai-pro review 13838 against current HEAD e338be59094d70fcd5746791d7440200ca78e81e. The missing-import finding for raw List/Map/Int is the same CORE-settled v4 kernel-ambient convention issue, not a code defect. src/v4/STRUCTURE.md states String, Int, Bool, Char, List, and Map are v2-seed kernel-ambient and usable in any .dag file without import; the modeled authorities still exist at src/v4/std/collection.dag:14 (List<T>), src/v4/std/collection.dag:16 (Map<K,V>), and src/v4/std/integer.dag:41 (Int). These extdep files use List/Map/Int as raw kernel values; modeled dependencies are imported where needed (FreeMonoid, Outcome, Byte, AbsolutePath, Filesystem, PosixByteString). Re-adding raw-kernel imports would repeat the previously reverted CORE-(b) misread. No code change is needed. — sent from keen-wren-663

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: e338be59 · Trigger: schedule
  • Thinking: 352s wall

BLOCKING (1)

Root Cause

  • src/v4/extdeps/process.dag Process lifecycle bundles mutable OS resources into child carriers instead of requiring terminal operations to consume the latest threaded resource authorities -> split process identity/pipe authority from Filesystem/ProcessTable state, or make live process carriers own those resources exclusively until wait/capture returns them.

⚠️ One substrate boundary still lets OS resource facts fork and then be overwritten by wait/capture.

Comment thread src/v4/extdeps/process.dag Outdated
type SpawnProcessResult = Outcome<SpawnedProcess>

type WaitProcessRequest {
spawned: SpawnedProcess

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

BLOCKING: WaitProcessRequest consumes the original SpawnedProcess rather than the current Filesystem/ProcessTable authorities, so intervening OS resource facts can be silently dropped when wait returns WaitedProcess (INVARIANTS P2 facts-flow-forward/single-authority).

@briansrls

Copy link
Copy Markdown
Contributor Author

Fixed codex review on process/resource authority at current head 9ebf67176. The process substrate now separates current OS resource authority from the child handle: ProcessResources { table, filesystem } is the paired resource carrier, SpawnProcessRequest consumes it, SpawnedProcess returns it, WaitProcessRequest consumes a current ProcessResources plus RunningProcess, WaitedProcess returns current resources with the waited process, and CapturedProcessOutput returns resources after capture. CaptureSource.Live likewise takes current ProcessResources plus the live process instead of reusing a stale spawn-time bundle. Updated OS-1 to describe capture as lifecycle process authority plus current/waited resource authority. Verified with cargo fmt --all --check and full-source-root v4 bootstrap: 68 sources resolved, 0 diagnostics. Strict comment density remains under target: file_system.dag 20/109 = 18.3%, process.dag 16/140 = 11.4%. — sent from keen-wren-663

@briansrls
briansrls merged commit 9e3083e into main May 18, 2026
7 checks passed
briansrls added a commit that referenced this pull request May 18, 2026
…, landed target)

CORE ruling (still-hawk-102, Option-1 + #3244): reframe LB-P4-3213 as a
valid plan-bound 🟡 with gate kind = consumer: (first meaning-consumer of
typed-command shape, deferred-by-brief, gate CLOSED). process.dag::Command
is the LANDED migration target (#3209), not the meaning-consumer — future
consumer consumes typed Command directly; #3213 does NO migration / NO
local CiCommand parse. Anti-#3250: NOT "no change needed".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: 9ebf6717 · Trigger: schedule
  • Thinking: 329s wall

Non-blocking — Strengths

  • src/v4/extdeps/process.dag The current process lifecycle shape threads ProcessResources through spawn, wait, and capture while preserving terminal state and capture-pipe authority.

✅ No blocking concerns found in the changed substrate or decision-record lines.

briansrls added a commit that referenced this pull request May 18, 2026
…apPlan data + CiPipeline C4 seam) (#3213)

* v4 T-20+T-24: model workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan data (v2-interp) + CiPipeline C4 ci.yml projection seam

T-20 workflow/bootstrap.dag: Stage / BootstrapStep / BootstrapPlan as
inert data; canonical seed→self0→self1→fixpt plan. Interpretation
(process/fs spawn) + executable BitIdentical TestClaim deferred (TRACKED
SCAFFOLD; owners T-22/T-4.5 and T-15).

T-24 workflow/ci.dag: CiJob / CiGate / CiPipeline data; Symbol-edge job
DAG; canonical structural v2-compile gate instance (the existing day-1
gate). ci.yml C4 projection, affected-set selection (IB-2), and
test/eval lane deferred (TRACKED SCAFFOLD; owners T-4.6/T-10, T-21, T-22).

Structural v2-compile gate verified: v2-compiler indexes 64 modules,
0 diagnostics. Status-line bump only; Owns/Consumes/Scope/Anchor headers
unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 T-20: add Practice-4 🟢/🟡/🔴 + five-pattern ledger to Stage + BootstrapStep coproducts

Addresses BLOCKING review (bootstrap.dag:160): every substrate coproduct
must carry the full Practice-4 classification + five-pattern dissolution
ledger under INVARIANTS P1 / modeling-discipline.md §4. Both Stage and
BootstrapStep classified 🟢 GREEN (terminal) with the five patterns
(fact-placement / variant-is-data / algebraic / dimensional /
parameterized-family) attempted inline, mirroring the witness.dag
exemplar. The inadequate one-line note replaced with a forward pointer.
Comment-only; structural v2-compile gate re-verified (64 modules, 0
diagnostics).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 T-20: make the bootstrap chain structural — fixed record replaces List<BootstrapStep>

Addresses BLOCKING review (bootstrap.dag:190): steps: List<BootstrapStep>
admitted reordered/duplicated/missing/extra chains — the
seed-once→stage0→stage1→stage2→fixed-point invariant was prose-only
(INVARIANTS P2). The chain is fixed by STRUCTURE.md (zero degrees of
freedom), so BootstrapPlan is now a FIXED RECORD with four named
positional slots whose distinct slot TYPES (CompileStep / FixedPointStep)
pin compile-vs-fixedpoint per position. Dissolves the exact node.dag
Diff #3162 list-anti-pattern. BootstrapStep coproduct removed (kind is
now the slot type, not a variant); Stage coproduct + its Practice-4
ledger retained unchanged (still consumed by the step records — no
finding-#1 churn). Within-step Stage wiring is a documented bounded
residual (yaml lexeme class; mis-wire = fail-closed interpret-time
Diagnostic, the ratified Diff stance — not a type-level illegal state).
Structural v2-compile gate re-verified (64 modules, 0 diagnostics).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 T-24: make the C4 ci.yml claim honest — no fabrication of GHA transport facts

Addresses BLOCKING review (ci.dag:146): CiPipeline {jobs,gates} cannot
faithfully back a .github/workflows/ci.yml C4 projection — a faithful
GHA workflow needs on/runs-on/steps/concurrency/permissions, which the
gunbc job/gate DAG deliberately omits, so any CiPipeline->ci.yml emit
would fabricate them (INVARIANTS P1/P2).

Fix is honesty, not fabrication and not a substrate add: project_ci_yml
re-typed to also consume a GHA workflow-schema model (gunbc data fills
the schema, never invents it); that schema is named MISSING SUBSTRATE
(no v4 counterpart to v3 extdeps/github/actions.dag — a new file =
operator-tier, surfaced not added). Committed ci.yml reframed as the
explicit interim hand-authored BRIDGE (the affected_set.dag
detect-affected-components.sh precedent); C4 checked-projection is an
explicit future state gated on the named substrate. The immutable
header's Owns/C4-over-CiPipeline over-claim is flagged on the PR for
conscious operator confirmation (frozen-header lines NOT worker-edited).
Structural v2-compile gate re-verified (64 modules, 0 diagnostics).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 T-20: comment hygiene — drop stale BootstrapStep refs from current-tense prose

Addresses cursor/composer-2 APPROVE_WITH_COMMENTS: two comments still
named BootstrapStep in the present tense after it was dissolved into
CompileStep/FixedPointStep slots. Fixed the "DATA, not a runner"
paragraph (now: fixed BootstrapPlan record of named slots) and the
Stage ledger pattern-1 (now: every chain step CompileStep/FixedPointStep).
The two remaining BootstrapStep mentions are intentional
removal-provenance, kept. Comment-only; structural v2-compile gate
re-verified (64 modules, 0 diagnostics).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 T-24: defer C4 seam to the ratified single-authority Workflow path (not a worker-minted shape)

Addresses BLOCKING (ci.dag:120): the db725fc C4 fix minted a parallel
project_ci_yml(CiPipeline, GhaWorkflowSchema) -> YamlValue seam,
diverging from the ratified locked T-Workflow-As-Data path
project_github_actions(CIWorkflowDag, WorkflowRuntime) -> Workflow
(extdeps.github.actions { Workflow } single authority pinned on
gunbc.ci CIWorkflowDag; WorkflowRuntime = YamlStatic | BinaryShim;
dsl/gunbc/ci_emission.dag) — parallel authority, INVARIANTS P2 (the
SELF_HOSTING authority-audit precedent).

Fix: the deferred seam now defers to the ratified single-authority
Workflow carrier + project_github_actions/WorkflowRuntime seam; ci.yml
is the Workflow carrier serialized under YamlStatic (YAML downstream of
Workflow), never a parallel CiPipeline -> YamlValue projection. The
invented GhaWorkflowSchema/project_ci_yml shape is retracted (kept as
provenance, not silently dropped). Missing substrate re-stated as the
v4 counterpart of the ratified extdeps.github.actions Workflow carrier
+ ci_emission.dag seam (operator-tier new file, surfaced not added, not
worker-substituted). No-fabrication / interim-bridge / header-tension-
surfaced stance preserved. Structural v2-compile gate re-verified (64
modules, 0 diagnostics).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan

* v4 T-20: make bootstrap chain edge identity structural now (singleton steps; zero inhabitants of invalid plans)

Addresses openai-pro REQUEST_CHANGES (843a37f, the binding gate) +
operator P2 finding: the free-field CompileStep/FixedPointStep records
still admitted the exact mis-wiring (seed slot typed-valid with
produces:Stage2) the comments claimed eliminated — the source/target
edge is the fixed chain's structural identity, not user config, so it
must be structural NOW, not an interpret-time check.

Each of the four positions is now its own payload-less SINGLETON
edge-identity type (SeedToStage0 / Stage0ToStage1 / Stage1ToStage2 /
FixptStage1Stage2; verified v2 parses `type X = X`). BootstrapPlan is
the fixed record of those slots → exactly ONE inhabitant; reorder /
duplicate / missing / extra / mis-wire all unconstructible. The Stage
coproduct (+ its five-pattern ledger) and BootstrapStep are both
removed (stage/edge identity now in the singleton names); no coproduct
remains so no Practice-4 ledger applies — this moots the earlier
"Stage/BootstrapStep need ledgers" finding by dissolution. The earlier
"bounded residual / future-grammar" deferral is retracted as
unnecessary (provenance kept, not silently dropped). Structural
v2-compile gate re-verified (64 modules, 0 diagnostics).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 T-20: fix singleton step types — empty-record form (constructible); restores green gate

bfc8886 used `type X = X` which v2 parses as a type but provides NO
usable value constructor (`undefined variable` at the data
construction) — that commit broke the structural v2-compile gate (4
errors). Root cause: the earlier probe only DECLARED the singleton,
never CONSTRUCTED it. Fixed: the four chain-position singletons are
empty records `type X {}` constructed as `X {}` (verified: v2 parses
AND constructs this form, 0 diagnostics). Design intent unchanged —
BootstrapPlan still has exactly one inhabitant; mis-wiring
unconstructible (openai-pro REQUEST_CHANGES + operator P2 resolved
structurally). Prose updated (empty-record singleton, not `type X = X`).
Structural v2-compile gate re-verified GREEN (64 modules, 1 file
emitted, 0 diagnostics, no errors).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 T-24: D5 in-PR frozen-header reconcile for ci.dag Owns/C4 (cite operator-tier review actions)

Per DECISIONS.md D5 / PR #3216 standing rule (merry-ibex-337 -> Lane B,
#3190 precedent): operator-tier action moving the body past the frozen
header/I/O ⇒ reconcile the header in the SAME PR + HEADER RECONCILE
block citing it; verbatim-while-divergent body = forbidden unsanctioned
drift.

Operator-tier actions = briansrls inline BLOCKING (ci.dag:198
C4-fabrication; ci.dag:120 single-authority-seam) + openai-pro. They
moved the body to: ci.yml is the ratified Workflow carrier under
WorkflowRuntime=YamlStatic via project_github_actions; C4 gated on the
missing v4 Workflow substrate (interim hand-authored bridge until then).
Reconciled the frozen Owns "emission target" + C4 lines from
emit(CiPipeline)/`.dag walks CiPipeline emits YAML` to the
single-authority Workflow-carrier projection; added HEADER RECONCILE
block. C4 operator-ratified INTENT preserved; only projection
mechanism/source corrected, no scope expansion. bootstrap.dag frozen
header preserved verbatim (its "ordered step sequence" I/O contract is
unchanged by the singleton redesign — correct D5 application).
Structural v2-compile gate GREEN (64 modules, 0 diagnostics).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 T-24: update HEADER TENSION para to reflect completed D5 reconcile (codex non-blocking nit)

codex (e86a8c4, "no blocking concerns remain") flagged that the
HEADER TENSION paragraph still described the frozen header as unedited
— stale/contradictory after the D5 in-PR reconcile (5f306e2). Updated
the para from "SURFACED, worker does NOT edit frozen lines" to
"RECONCILED in-PR (D5)" pointing at the HEADER RECONCILE block. Comment
hygiene only; no model change. Structural v2-compile gate GREEN (64
modules, 0 diagnostics).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 T-24: make CiJob.command faithful + explicitly non-executable (codex BLOCKING)

codex BLOCKING (sha 99753a3): CiJob.command was a lossy paraphrase
("v2-compiler compile --source-root src/v4") while documented as the
command line the deferred interpreter executes — fabricating process
facts (INVARIANTS P1) and not faithfully reproducing the live v4 CI
gate command.

Fix (both options the finding allowed): (a) store the EXACT primary
gate invocation verbatim from .github/workflows/ci.yml
("target/release/v2-compiler compile --source-root src/v4 --output-dir
/tmp/v4-stage1 --target dag"); (b) reframe the field as NON-EXECUTABLE
documentation data — there is no interpreter (process carrier
extdeps/process.dag is T-4.5 scaffold) and a single String cannot carry
a GHA job (the live step is a multi-line shell wrapper + a `cargo build`
prerequisite). The full faithful step + process spawn stay deferred to
extdeps/process.dag (T-4.5) + T-22 (TRACKED SCAFFOLD (3)), explicitly
NOT fabricated into the String. Field doc + CiJob doc + gate-instance
comment updated. Structural v2-compile gate GREEN (64 modules, 0
diagnostics).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 T-20: unify fixed-point vocab in body — bit-identical (property) + RoundTrips (AssertKind)

cursor APPROVE_WITH_COMMENTS (non-blocking): body prose said
"`BitIdentical` TestClaim" (implying a kind) in places while the TRACKED
SCAFFOLD correctly ties the deferred check to std/verification.dag
`kind: RoundTrips` (no `BitIdentical` AssertKind exists). One editorial
pass: all BODY occurrences now use "bit-identical" for the
stage1==stage2 PROPERTY and `RoundTrips` for the substrate AssertKind
(Status note, WHY-PINNED-HASH note, FixptStage1Stage2 type comment;
TRACKED SCAFFOLD (2) was already correct). Frozen Owns/Consumes header
lines (22/26/76) preserved VERBATIM — a non-blocking hygiene nit is not
the operator-tier D5 sanction required to edit frozen header lines;
"BitIdentical" there is the property/anchor name, reconcilable with
verification.dag's RoundTrips ("self-host bit-identity") once the body
is consistent. Comment-only; structural v2-compile gate GREEN (64
modules, 0 diagnostics).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 T-24: name the fail-closed CiPipeline well-formedness boundary (node.dag Diff #3162 stance)

Addresses briansrls BLOCKING (ci.dag:275): jobs/gates lists + raw
Symbol edges leave missing targets / duplicate ids / needs-cycles
constructible; P2/P4 need a structural OR fail-closed boundary before
consumers land.

Resolved by applying the canonical node.dag Diff #3162 ratification
(not a coin-flip — that precedent settles the shape): ANY jobs/gates
lists are valid CiPipeline DATA; missing-target/dup-id/cycle are NOT
type-level illegal states and there is deliberately NO
ci_pipeline_well_formed eager predicate (exactly the #3162
diff_well_formed anti-pattern). The fail-closed WELL-FORMEDNESS
boundary is the deferred select_jobs consume fold (apply_diff-analogous
all-or-nothing): unresolved/duplicate/cyclic => one fail-closed
Diagnostic (Outcome<T>), decidable via visited-set traversal (P4).
NAMED + OWNED now (select_jobs / lens/affected_set.dag T-21, TRACKED
SCAFFOLD (2)); only its body deferred per scaffold discipline. Doc
tightened in CiPipeline + TS(2). Comment-only; structural v2-compile
gate GREEN (64 modules, 0 diagnostics).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan

* v4 T-24: implement eager fail-closed ci_pipeline_well_formed boundary (still-hawk-102 adjudication)

still-hawk-102 (relayed via Lane B) rejected reaffirming #3162 for
CiPipeline: #3162's precondition (no intrinsic well-formedness) is FALSE
here — a job/gate DAG has intrinsic, statically-decidable
well-formedness (unique ids / acyclic / resolving refs), malformed
independent of any consumer; deferring to select_jobs (a consumer) is
ruled out by the operator's "before consumers land". Patterns don't
auto-extend without the per-instance precondition.

Implemented the eager boundary NOW: ci_pipeline_well_formed :
CiPipeline -> Outcome<CiPipeline>, covering (1) unique job ids
(node.dag all_names_distinct CHECK-enforced precedent), (2) reference
resolution (every needs/gate.job resolves to a declared id), (3)
acyclicity via Kahn sink-elimination bounded by count(jobs) passes
expressed as a fold over the finite jobs list (A2 IMPLICIT termination,
INVARIANTS P4) — never an unbounded walk. Any violation = one
fail-closed Diagnostic (AmbiguousIntent, no repair-guess). Structural
Map-for-ids was INFEASIBLE: v4 Map<K,V> is lookup-only (no key
enumeration) so a Map jobs field can't be traversed for the required
acyclicity/ref checks; jobs/gates stay List (fold-traversable) per the
adjudication's "pick by feasibility" + ACCEPTABLE eager option. NOT a
#3162 exception (#3162 never governed this carrier). WELL-FORMEDNESS
header + TRACKED SCAFFOLD (2) rewritten (drop #3162-stance + the
deferral). Structural v2-compile gate GREEN (64 modules, 0 diagnostics).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan

* v4 T-20+T-24: de-prose bootstrap.dag + ci.dag in-PR (operator HOLD/audit directive)

Per still-hawk-102 → Lane B directive (HOLD all PRs for operator audit;
de-prose in-PR; load-bearing files keep structured header contract).
Collapsed the review-cycle-accreted body modeling-notes essays to terse
load-bearing comments (CODING.md "default no comments; only non-obvious
WHY"): bootstrap.dag 257→173, ci.dag 508→374. Comment-only — code,
types, fns, data unchanged; structural v2-compile gate GREEN (64
modules, 0 diagnostics).

KEPT (mandated artifacts, not de-prosed): the immutable structured
headers (Scope/Anchor/Owns/A3/Discipline/Consumes/Status/Brief); the
ci.dag D5 HEADER RECONCILE block (#3216 standing rule); TRACKED SCAFFOLD
owner/trigger items; the WELL-FORMEDNESS eager-boundary doc incl. the
Map-infeasibility one-liner (Lane-B-mandated visible) + still-hawk-102
adjudication provenance; ledger-provenance + supersession one-liners;
no-fabrication/single-authority + command-non-executable facts.
REMOVED/COLLAPSED: multi-paragraph restated rationale, defensive
review-cycle elaboration. RELOCATE: n/a (no in-scope target; design
narrative already captured in PR comments + DECISIONS). No D2-alias
prose present (verified — file is not D2-affected, no D2 reconcile).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 T-20+T-24: STRICT de-prose bootstrap.dag + ci.dag (still-hawk-102 directive, interim until #3226)

Per still-hawk-102 STRICT DE-PROSE RE-DO (supersedes prior nominal
de-prose; prior attestation not accepted). A de-prosed .dag carries
ONLY: file-path line; terse Scope/Owns/Consumes/Status header; optional
per-carrier Anchor URL; optional one-line per-TYPE concept tag if
non-obvious. Everything else removed. Comment-only — all code, types,
fns, data verbatim-unchanged; structural v2-compile gate GREEN (64
modules, 0 diagnostics).

Comment-% (was → now): bootstrap.dag ~83% → 19.2% (5/26);
ci.dag ~58% → 3.2% (5/156). Both < 20% hard target.

PROCESS RECEIPT / removed-narrative provenance (kept here in the commit
message per directive, NOT in the file):
- ci.dag D5 HEADER RECONCILE (2026-05-17, #3213, D5/#3216, #3190
  precedent): operator-tier BLOCKING review actions (briansrls inline
  C4-fabrication + single-authority-seam; openai-pro confirming) moved
  the body past the frozen Owns/C4 header; it was reconciled IN-PR to
  the single-authority project_github_actions->Workflow seam with C4
  gated on the missing v4 Workflow substrate (interim hand-authored
  ci.yml bridge). C4 operator-ratified intent preserved; only mechanism
  corrected. This narrative now lives only in git history + prior PR
  comments, not the file.
- ci_pipeline_well_formed is the eager fail-closed well-formedness
  boundary (still-hawk-102 adjudication 2026-05-17): #3162 does not
  govern CiPipeline (intrinsic statically-decidable well-formedness);
  structural Map-for-ids INFEASIBLE (v4 Map<K,V> is lookup-only, no key
  enumeration) so jobs/gates stay List + eager predicate checks unique
  ids (node.dag all_names_distinct precedent) + ref-resolution +
  acyclicity (Kahn elimination bounded by count(jobs), A2-IMPLICIT,
  P4-decidable). Architectural rationale belongs in DECISIONS.md (owned
  by operator/#3226), not this file.
- No D2-alias prose present (not D2-affected, not pipeline-stage); no
  gated reconciliations. Branch 0 commits behind origin/main.

HELD for operator audit; not merging (operator squash-merge only).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 T-24: ci_pipeline_well_formed also proves gate-id uniqueness (briansrls BLOCKING)

Valid finding (ci.dag:27): CiGate.id is an addressable identity but the
eager well-formedness predicate checked job-id uniqueness only, so
duplicate gate ids were accepted → ambiguous downstream selection
authority (INVARIANTS P2). Same intrinsic, statically-decidable,
consumer-independent well-formedness class the still-hawk-102
adjudication required for jobs.

Fix (code-only; strict-de-prose preserved, ci.dag 2.9% comment):
added ci_gate_id_occurrences + ci_all_gate_ids_unique (mirroring the
job-id check / node.dag all_names_distinct CHECK-enforced precedent) +
a ci_duplicate_gate_id reason symbol, and a gate-id-uniqueness branch
in ci_pipeline_well_formed (duplicate gate id ⇒ fail-closed Rejected).
Structural v2-compile gate GREEN (64 modules, 0 diagnostics).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 T-24: fix ci.dag Consumes header drift (std/* → v4.std.*)

cursor APPROVE exploratory nit: terse Consumes header said `std/node,
std/diagnostic` but the actual imports are `v4.std.node` /
`v4.std.diagnostic`. The terse header is now the sole in-file contract
under operator audit, so header precision matters. One-line accuracy
fix; strict de-prose preserved; structural v2-compile gate GREEN (64
modules, 0 diagnostics).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 T-20: expand bootstrap.dag four stages as v4 orchestration DATA (operator directive; resolves codex finding-1)

Operator (still-hawk-102 via loyal-wren-802) adjudicated codex #3213
finding-1: bootstrap.dag DOES own/define/source/orchestrate the four
stages now (supersedes the prior minimal-singleton/deferred-interpret
framing). Expanded per directive:

- DEFINE: each stage is a distinct record with real fields (no more
  empty `{}` markers). SeedToStage0/Stage0ToStage1/Stage1ToStage2 carry
  consumes/produces/via; FixptStage1Stage2 carries left/right/via.
- SOURCE: inputs are real Symbol identities — v4_dag_source (the src/v4
  .dag compiler corpus), v4_stage0/1/2_binary, v2_pipeline (the frozen
  seed executor), bit_identical_check. `Consumes: none` → v4.std.node.
- ORCHESTRATE: BootstrapPlan record + canonical bootstrap_plan wiring
  the four stages with concrete consumes/produces in order, as v4 DATA.
- TRIVIAL v2-DELEGATING BODIES (sanctioned): all compile stages'
  executor `via = v2_pipeline` initially; per-stage shift
  delegate-to-v2 → use-v4's-own as v4's pipeline is built (file FILLED
  IN, never replaced). Orchestration is v4 data from day one.

Per-position type distinctness retained (seed slot must be
SeedToStage0, etc.) so cross-position mis-wiring stays type-prevented.
No coproducts introduced (all records) — emoji-tag directive N/A.
Strict de-prose preserved: bootstrap.dag 7.1% comment (5/70), terse
4-line header only. Structural v2-compile gate GREEN (64 modules, 0
diagnostics). HELD for operator audit; in-PR expansion.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan

* WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan

* v4 T-24: port v3 CICommand → typed v4 CiCommand carrier (still-hawk-102 fork-2; Option-1 DECISIONS row)

still-hawk-102 fork-2 directive: replace ci.dag CiJob.command:String with
a proper v4 typed command carrier, PORT (not import) of v3
dsl/gunbc/ci.dag CICommand. Faithful re-express (no shape fork):
  type CiCommand = LintCommand | TestCommand
                 | IgnoredTestCommand { test_name: String }
                 | ShellCommand { command: String }
  CiJob.command: CiCommand (was String); v2_compile_gate_job →
  ShellCommand { command: "<verbatim v2-compile invocation>" }.

Coproduct ⇒ per modeling-discipline.md Practice 4/9 + the coproduct-emoji
directive: in-file one-line tag `// 🟡 coproduct dissolution —
DECISIONS.md LB-P4-3213` on `type CiCommand`; full classification ledger
authored as DECISIONS.md Part-6 row LB-P4-3213 (id assigned by
still-hawk-102 Option-1: worker authors provisional, operator ratifies on
audit). Classification 🟡 YELLOW (scaffold): richer source nameable (the
T-4.5 extdeps/process.dag typed Command{program,args,env} carrier + v3
ROADMAP-F12); ShellCommand{command:String} is the bounded interim;
named trigger = T-4.5 typed Command carrier lands. 5 dissolution
patterns tried, recorded in the ledger row.

ci.dag strict de-prose preserved (3.3% comment, <20%). Structural
v2-compile gate GREEN (64 modules, 0 diagnostics). bootstrap.dag NOT
touched — codex F1/F2 reconciliation pending still-hawk-102 (orthogonal).
#3213 HELD for operator audit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 T-20: bootstrap.dag F1/F2 fixes (still-hawk-102 reconciliation; implement, not rebut)

still-hawk-102 reconciled the codex CR — implement (not rebut):

F1 (Practice-3 forward chain): `via: v2_pipeline` kept (sanctioned
executor-is-v2-initially). `consumes` is now List<Symbol> carrying the
prior stage's produced artifact so the orchestration DATA is a chain,
not three independent compiles:
  seed  consumes [v4_dag_source]                       produces stage0
  self0 consumes [v4_dag_source, v4_stage0_binary]      produces stage1
  self1 consumes [v4_dag_source, v4_stage1_binary]      produces stage2
  fixpt left=stage1 right=stage2 via=bit_identical_check

F2 (Practice-7 enumerated-copy): the three identical
{consumes,produces,via} stage types (SeedToStage0/Stage0ToStage1/
Stage1ToStage2) collapsed into ONE `CompileStage { consumes, produces,
via }`. FixptStage1Stage2 { left, right, via } stays its own type (not
collapsed, per directive). Order/multiplicity expressed as fixed named
BootstrapPlan slots (seed/self0/self1: CompileStage; fixpt:
FixptStage1Stage2) — keeps the exactly-3-compiles+1-fixpt fixed shape
(no over-general List reintroduced) while removing the enumerated copy.

No coproducts (records only) — emoji directive vacuous. Strict de-prose
preserved: bootstrap.dag 8.6% (5/58), <20%. Structural v2-compile gate
GREEN (64 modules, 0 diagnostics). #3213 HELD for operator audit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 T-24: export ci_pipeline as fail-closed Outcome (briansrls BLOCKING — non-bypassable boundary)

Valid finding (ci.dag:54): canonical `ci_pipeline` was exported as raw
CiPipeline, so consumers could read it without passing through the
operator-adjudicated eager `ci_pipeline_well_formed` boundary —
bypassing the P2/P3 fail-closed check. Faithful completion of the
still-hawk-102-directed eager-well-formedness boundary (no shape fork,
no directive conflict): the boundary now cannot be bypassed.

Fix: raw construction is internal `ci_pipeline_unchecked: CiPipeline`;
the exported canonical `ci_pipeline: Outcome<CiPipeline> =
ci_pipeline_well_formed(p: ci_pipeline_unchecked)`. Downstream consumers
must handle Produced/Rejected — the eager fail-closed boundary is now
the only way to obtain the pipeline. v2 supports the fn-application
data initializer (verified). Strict de-prose preserved (ci.dag still
<20%); structural v2-compile gate GREEN (64 modules, 0 diagnostics).
Orthogonal to the bootstrap P2/F1/F2 trilemma (routed, pending
still-hawk-102; bootstrap.dag NOT touched). #3213 HELD for audit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan

* WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan

* v4 T-20: bootstrap (b) expose-only-checked — drop consumable bootstrap_plan_unchecked (still-hawk-102 GO)

still-hawk-102 RULING on the openai-pro (heaviest-weight) REQUEST_CHANGES
re-litigating the adjudicated bootstrap-P2: implement (b). (a)
structural per-stage nominal identities FORBIDDEN — do not revert F2
(codex-F2 / Practice-7 stays closed).

(b): removed the named consumable `data bootstrap_plan_unchecked:
BootstrapPlan`; the BootstrapPlan{...} literal is now inlined as the
sole argument to bootstrap_plan_well_formed(p: BootstrapPlan {...}).
The ONLY named export consumers can bind is now `bootstrap_plan:
Outcome<BootstrapPlan>` (the checked carrier) — the consumable-boundary
leak (unchecked raw record had a name to grab) is closed. Mirrors the
ci_pipeline expose-only-checked precedent (Lane-B-PASSED). F1 (forward
consumes chain) + F2 (single CompileStage) intact; no codex-F2
re-trigger; no shape fork.

v2-compiler parses the inlined nested record literal (verified, not
shipped blind); structural v2-compile gate GREEN (64 modules, 0
diagnostics). Strict de-prose intact (bootstrap.dag 4.5%, <20%).
#3213 HELD for operator re-audit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan

* v4 #3213 IB-3: Practice-10 List-op dissolution pass (operator merge gate)

std/collection.dag (T-3) declares zero derived List ops -> zero RED
(nothing to dissolve into in-PR); every hand-rolled generic List
primitive marked YELLOW gated feature: (owner T-3 std/collection.dag,
named missing op + dissolve-on-arrival obligation). Kahn composition
classified GREEN terminal domain-logic (peer of the well-formed
predicates). One terse in-file tag per file (LB-P4-3213 precedent);
full LB-P10-3213 ledger in DECISIONS.md Part 7. #3244 disposition
vocabulary. Structural v2-compile gate: indexed 67 modules, 0 diagnostics.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 #3213: ci.dag expose-only-checked — drop consumable ci_pipeline_unchecked/v2_compile_gate_job (operator REQUEST_CHANGES)

Operator (briansrls) BLOCKING: top-level raw ci_pipeline_unchecked:
CiPipeline was a second authority beside checked ci_pipeline,
bypassable by downstream consumers (P2 single-authority / P3
fail-closed). Fix mirrors the operator-accepted bootstrap (b)
expose-only-checked shape: inline the CiPipeline literal (CiJob/CiGate
inlined) as the sole arg to ci_pipeline_well_formed; remove the named
ci_pipeline_unchecked and v2_compile_gate_job composites so the only
consumable pipeline authority is data ci_pipeline: Outcome<CiPipeline>.
Header Owns updated. Structural v2-compile gate: indexed 68 modules,
0 diagnostics.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 #3213: ci.dag rename ci_kahn_fixpoint fold param counter->job (CODING.md names-describe-the-mapping)

Recurring multi-reviewer readability observation (cursor 13938
exploratory): the fold's 2nd callback parameter is the folded `jobs`
element, not a counter; `counter` misdescribed the mapping. Renamed to
`job` per CODING.md "names describe the mapping". Semantically inert
(param remains deliberately unused — the fold is the bounded-iteration
driver per LB-P10-3213-KAHN); structural v2-compile gate: indexed 68
modules, 0 diagnostics. Resolves the observation permanently rather
than restating "intentional".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 #3213: rewrite LB-P4-3213 ledger to #3244 precision (consumer-gate, landed target)

CORE ruling (still-hawk-102, Option-1 + #3244): reframe LB-P4-3213 as a
valid plan-bound 🟡 with gate kind = consumer: (first meaning-consumer of
typed-command shape, deferred-by-brief, gate CLOSED). process.dag::Command
is the LANDED migration target (#3209), not the meaning-consumer — future
consumer consumes typed Command directly; #3213 does NO migration / NO
local CiCommand parse. Anti-#3250: NOT "no change needed".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 #3213: bootstrap.dag — split stage compiler-of-record from executor (self-hosting identity)

codex BLOCKING + 2 BLOCKING-inline (P1/P2): every CompileStage.via was
v2_pipeline, conflating the orchestration executor with the stage
compiler-of-record and making the fixpt (stage1==stage2) check vacuous.

Fix grounded in load-bearing docs:
- STRUCTURE.md:404-405 "Seed used once": v2 produces v4-stage0, then v4
  compiles itself; v2 is never in the loop again.
- SELF_HOSTING.md §meta-circular: stage0 compiles source->stage1,
  stage1 compiles source->stage2, assert byte-identical.

via -> compiled_by (CODING.md names-describe-the-mapping): seed
compiled_by v2_pipeline, self0 by v4_stage0_binary, self1 by
v4_stage1_binary. No executor bridge field — STRUCTURE.md is explicit
that v2 is seed-once, so no "v2 executes every stage" fact exists; the
brief's "v2 is the initial executor" framing contradicted the doc and
the doc wins.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 #3213: ci.dag consumes bootstrap seed authority — single-authority fix (P2/Practice 5)

openai-pro 13971 (BLOCKING, at HEAD 52c207b): ci.dag:52 restated the
bootstrap seed action as a raw ShellCommand argv string, a parallel
authority for the seed→stage chain that bootstrap.dag BootstrapPlan.seed
now canonically owns — drift-prone, violates INVARIANTS P2 single-
authority / modeling-discipline Practice 5; the duplication was also
untracked debt (review §6).

Fix (in-PR, structural model only — not the brief-deferred ci.yml
projection / T-22 lane): add typed CiCommand variant
BootstrapStageCompile{produces: Symbol}; the v2_compile_src_v4 job now
references v4_stage0_binary imported from v4.workflow.bootstrap. A real
machine-readable cross-module edge to the bootstrap authority — the raw
argv is removed entirely; BootstrapPlan.seed is the sole source of
truth. No import cycle (bootstrap does not import ci).

Distinct from / orthogonal to CORE-adjudicated LB-P4-3213: that 🟡 is
the ShellCommand{String} raw-argv command-SHAPE decomposition, deferred
to the consumer lane. This is single-AUTHORITY wiring (an invariant),
resolved now. LB-P4-3213 ledger updated to record the resolution.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: IB-3 T-20+T-24 workflow/bootstrap.dag + workflow/ci.dag — BootstrapPlan

* v4 #3213: Practice-9 de-prose — in-file rationale → ≤1-line ledger pointers

cursor 13986 (NON-BLOCKING, APPROVE_WITH_COMMENTS): ci.dag mid-carrier
comment recorded single-authority/P2 rationale as in-file prose
(Practice 9 — rationale belongs in DECISIONS.md, already covered by
LB-P4-3213). Replace with a one-line `// 🟢 single-authority —
DECISIONS.md LB-P4-3213` pointer; strip the same-shape parenthetical
from ci.dag Consumes line and tighten bootstrap.dag compiled_by tag for
consistency. No semantic change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 #3213: Practice-9 — drop bootstrap.dag compiled_by field-prose

cursor 13998 (APPROVE_WITH_COMMENTS): the `// stage compiler-of-record`
field comment is rationale-on-carrier, not an allowed comment class.
The field name + header Scope line already convey the self-hosting
identity; structure speaks for itself. No DECISIONS pointer needed (no
dedicated ledger entry; header already documents seed-once semantics).
No semantic change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 #3213: structurally enforce BootstrapStageCompile single-authority at the CI boundary

openai-pro 14006 (BLOCKING, manual re-review @ 5d4468d): BootstrapStageCompile{produces:Symbol}
took an unconstrained Symbol and ci_pipeline_well_formed never validated it against the
canonical BootstrapPlan outputs — the single-authority seam the ledger claims as resolved
was prose/convention, not structural enforcement (INVARIANTS P2 / modeling-discipline
Practice 5/6).

Fix (structural model, in-scope — not the brief-deferred T-22 executable lane):
- bootstrap.dag owns bootstrap_stage_output(s: Symbol) -> Bool — the single authority on
  the canonical stage-output set {v4_stage0_binary, v4_stage1_binary, v4_stage2_binary}.
- ci.dag imports it; ci_pipeline_well_formed now consumes the bootstrap authority via
  ci_all_commands_authority_ok and fail-closed rejects any BootstrapStageCompile.produces
  outside that set (ci_bootstrap_authority_violation). A dangling payload cannot reach
  Produced — the invariant is enforced at the substrate boundary, not asserted in prose.
- LB-P4-3213 ledger updated: single-authority is now boundary-ENFORCED, not prose.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 #3213: ADDRESSED-BY-CONSTRUCTION + plan-bound 🟡 to T-22 (CORE horn (i))

still-hawk-102 ruling (2026-05-18): the BootstrapStageCompile single-
authority seam is addressed-by-construction (pure structural predicate;
out-of-set produces cannot satisfy the gate — modeled Rejected Outcome,
no imperative side-channel; verified in code @6353d695e). Horn (ii)
in-PR executable harness REJECTED (T-22-in-#3213 = brief violation).

Records the deferred executable demonstration as an explicit plan-bound
🟡 with bilateral binding:
- DECISIONS.md LB-T22-3213: arrival (T-22 TestClaim runner) + follow-up
  (negative TestClaims for the bootstrap-stage rejection family) that
  dissolves the 🟡.
- TASKS.md T-22 scope: same obligation, cross-referencing LB-T22-3213
  (neither side vague).
- ci.dag in-file one-line tag → LB-T22-3213.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 #3213: Practice-9 — single coproduct tag on CiCommand (drop variant-level 🟢)

cursor 14020 (APPROVE_WITH_COMMENTS): CiCommand carried two emoji
dissolution lines (coproduct-level 🟡 + variant-level 🟢), reading as
conflicting dispositions on one type. Rubric wants one required
🟢/🟡/🔴 tag per coproduct; the LB-P4-3213 ledger already carries the
single-authority/command-shape nuance. Drop the redundant variant-level
🟢 line; the coproduct-level 🟡 tag + DECISIONS.md ledger stand. No
semantic change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 #3213: CI bootstrap-authority consumes bootstrap_plan Outcome, fail-closed (P2/P3)

Operator BLOCKING inline (#3213 ci.dag:168): bootstrap_stage_output
checked static stage-symbol membership {v4_stage0_binary,1,2} instead of
consuming bootstrap_plan: Outcome<BootstrapPlan> — so CiPipeline could be
Produced even when the canonical bootstrap plan is Rejected, bypassing
the fail-closed bootstrap authority (INVARIANTS P2 single-authority /
P3 fail-closed).

Fix: bootstrap_stage_output now takes Outcome<BootstrapPlan>, matches it
— Rejected ⇒ false (fail-closed: CI cannot pass while bootstrap is
Rejected), Produced{value: bp} ⇒ produces ∈ {bp.seed/self0/self1
.produces} (validated-plan actual outputs, not a static set). ci.dag
imports bootstrap_plan and threads it through ci_command_authority_ok →
ci_pipeline_well_formed. The validated bootstrap_plan is now the sole
authority. LB-P4-3213 ledger updated (P2/P3, plan-Outcome consumed).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 #3213: add mandatory // Ledger: pointer line to load-bearing workflow headers

CORE ruling (still-hawk-102 via Lane B): the de-prose-vs-rail fork was
FALSE — strict de-prose stands AND one mandatory `// Ledger:` pointer
line per load-bearing file (pointer class, not prose). Adds the
CORE-specified line after Status: in bootstrap.dag + ci.dag. No body
churn; consistent with strict-de-prose (concrete ref pointer, ≤1 line).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 #3213: CORE Option B — rescind // Ledger: line, keystone wins (registry doc→files)

CORE ruling (still-hawk-102) on the openai-pro 14070 RC vs the
modeling-discipline.md:503-531 keystone contradiction: the // Ledger:
mandate is RESCINDED — strict de-prose keystone wins (header stays
exactly four lines; no see-docs/X pointer in .dag).

- bootstrap.dag / ci.dag: remove the // Ledger: line (-1 each).
- Registry moves doc→files (Practice 5, top-down): design-pure-bootstrap-zero.md
  names the two load-bearing workflow files + A3/PROOF-1/STOP-rail + C4;
  INVARIANTS.md + src/v3/SELF_HOSTING.md add short Practice-5 registry
  cross-refs. Authority flows doc→files, not per-file upward pointers.

Replays swift-ram-178 a94a312 verbatim onto the #3213 branch.
Clears openai-pro 14070; consistent with the keystone.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v4 #3213: reconcile to authoritative trimmed spec — drop INVARIANTS.md registry para

still-hawk TRIM relay (post-a94a3123f) set the authoritative one-commit
spec = NO INVARIANTS.md edit: registry lives only in
docs/design-pure-bootstrap-zero.md + src/v3/SELF_HOSTING.md + the .dag
// Ledger: strips. 9fda2f0 over-included the INVARIANTS.md para
(replayed from the pre-trim a94a312). Drop it to conform; the two
authoritative registry homes + .dag strips stand unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@briansrls
briansrls deleted the session/keen-wren-663 branch June 1, 2026 18:42
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