8000 T23 — Check type constraints last, and let a derived type only narrow by minimal-foundry[bot] · Pull Request #3292 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content

T23 — Check type constraints last, and let a derived type only narrow - #3292

Merged
mitodrummer merged 8 commits into
mainfrom
agent/2424-check-type-constraints-last-and-let-a-derived-ty
Nov 12, 2026
Merged

mitodrummer merged 8 commits into
mainfrom
agent/2424-check-type-constraints-last-and-let-a-derived-ty

Conversation

@minimal-foundry
@minimal-foundry minimal-foundry Bot commented Nov 11, 2026 •
Copy link
Copy Markdown
Contributor

T23 — Check type constraints last, and let a derived type only narrow

slice: S5
kind: task
covers: BOX-061, BOX-062, BOX-156
size: L
est: 300 code, 240 tests
executor: agent
difficulty: needs care
model: strongest
diagnostics: error names type, key and layer
observability: none: a pure function, no runtime
layers:
- constraints:
- crates/mfile/src/box_types.rs: narrowing only; never adds
- crates/mfile/src/expand.rs: constraints checked last
test: cargo nextest run -p mfile expanded_spec_violating_constraint_exit3_names_type_and_layer
test: cargo nextest run -p mfile derived_type_loosening_constraint_exit3_names_type_key_parent
test: cargo nextest run -p mfile constraint_never_adds_package_port_or_egress
produces: none
consumes:
- crates/mfile/src/box_types.rs
proof: An entry breaking its type's constraint fails naming the layer.
depends on:
- blocked by #2420

Proof

In mfile, an entry whose expanded value breaks its type's constraints fails with exit 3 after the override layer. The error names the type, the key and the layer, for example: "[boxes.pty] in minimal.toml sets pty_enabled to true. [box_types.ci] allows only false for pty_enabled. Change the value." A derived type that loosens its parent's constraint fails to resolve, and the error names the type, the key and the parent. A constraint never changes the spec.

Notes from the agent: Design: expand returns crate::Error, and a new variant needs error.rs, which is outside the layers. So the BOX-061 check is the new mfile::expand::check_constraints(entry, &expansion, &resolved_type). It reads the finished expansion, after the override layer, and returns the new BoxTypeError::ConstraintBroken. expand does not call it. No product caller calls it yet. The callers in crates/minimal/src/cmd/boxes/create.rs do not resolve the type or fill type_defaults either. A later task must call check_constraints after each expand. BOX-156 is checked in BoxTypes::resolve, so BoxTypes::from_file fails on a loosening type (new BoxTypeError::Loosening). Constraint meaning: a list admits each of its items. A table constrains each key it names, where the spec sets that key. Any other value admits only itself. A spec list is checked item by item, and the error names 8000 the layer that added the failing item. An absent key passes. Values compare as TOML values, so "10m" and "600s" are different values for a timeout constraint. For a table constraint, a derived type must repeat every key its parent constrains, or it counts as a loosening. The error names the immediate parent type (the extends target). Ran the whole mfile suite once at the end: 151 passed. cargo clippy -p mfile --all-targets is clean. Did not run just clippy-strict or just lint-prose.

Tests

line exit tail
cargo nextest run -p mfile expanded_spec_violating_constraint_exit3_names_type_and_layer 0 warning: unknown fields in task runtime-implement-test-0: network warning: unknown fields in task runtime-implement-test-1: network warning: unknown fields in task runtime-implement-test-2: network help: do you need to update to a newer version of minimal? Applying loadouts: default Running task run
cargo nextest run -p mfile derived_type_loosening_constraint_exit3_names_type_key_parent 0 warning: unknown fields in task runtime-implement-test-0: network warning: unknown fields in task runtime-implement-test-1: network warning: unknown fields in task runtime-implement-test-2: network help: do you need to update to a newer version of minimal? Applying loadouts: default Running task run
cargo nextest run -p mfile constraint_never_adds_package_port_or_egress 0 warning: unknown fields in task runtime-implement-test-0: network warning: unknown fields in task runtime-implement-test-1: network warning: unknown fields in task runtime-implement-test-2: network help: do you need to update to a newer version of minimal? Applying loadouts: default Running task run

Verify

min task run agent-verify passed ([tasks.verify]).

Residual: #3295 calls mfile::expand::check_constraints after each mfile::expand::expand in crates/minimal/src/cmd/boxes/create.rs. Until it lands, no product expansion runs the BOX-061 check.

Closes #2424

A type's constraints are a check, never a layer. check_constraints
reads a finished expansion, after the override layer, and fails with
exit 3 naming the type, the key and the layer that set the value
(BOX-061). It never changes the spec, so a constraint never adds a
package, a port or an egress entry (BOX-062). Type resolution fails
with exit 3 naming the type, the key and the parent when a derived
type's constraint admits a value its parent's excludes (BOX-156).
@coderabbitai
coderabbitai Bot commented Nov 11, 2026 •
Copy link
Copy Markdown
Contributor

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 54ec1aec-23ba-4072-bd24-7fa222b8cbb9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
Pre-merge checks: Inconclusive 2
8000

Failed Failed checks: 2 inconclusive

Check name Status Explanation Resolution
Title check Pending This assessment has not completed. The check will be retried on the next pre-merge check run.
Description check Pending This assessment has not completed. The check will be retried on the next pre-merge check run.
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

@minimal-foundry
minimal-foundry Bot commented Nov 11, 2026 •
Copy link
Copy Markdown
Contributor Author

Reviewed: no findings; approval withheld, 11 threads unresolved at 0af040b7e1ff.

APPROVE withheld: 11 unresolved threads — minimal-arch[bot] crates/mfile/src/box_types.rs:413, minimal-arch[bot] crates/mfile/src/expand.rs, minimal-arch[bot] crates/mfile/src/expand.rs:319, minimal-arch[bot] crates/mfile/src/box_types.rs:413, minimal-arch[bot] crates/mfile/src/expand.rs, …. Resolving the last thread releases the approval on this head.

Resolve the open threads. Resolving the last one releases the approval on this head; no new review is required.

Clobber: none seen.

@minimal-foundry minimal-foundry Bot 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.

minimal-review — advisory review

Verdict COMMENT — 1 finding, 1 inline.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

Comment thread crates/mfile/src/expand.rs Resolved
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

arch-review: CONDITIONS · 3 conditions · the full ruling

The checks are in the right crate, and BOX-062 conforms. The built-in roots carry no constraints, so a type that extends task can allow pty_enabled = true. Line 1264 of the design refuses that. Make the change in C1. check_constraints skips a key the spec does not set, but the product then applies the root default. Make the change in C2. No product path calls the check yet. Name the issue for that work in the PR body, as C3 says.

Ruled at a50eb1b against gominimal/arch@15b603e6afb8 by claude-opus-5-5.

defaults.push(((*t).to_owned(), project.defaults.clone()));
constraints.push(((*t).to_owned(), project.constraints.clone()));
}
check_narrowing(&constraints)?;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

C1 · The chain starts with an empty table for the built-in root, so this check never sees the root's constraints. A type with extends = "task" and constraints = { pty_enabled = true } resolves. Seed the root's table from the design table, lines 1212-1220, as C1 says.

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 70864457b8ee: BoxTypes::resolve seeds the root entry with builtin_constraints(root), so extends = "task" with constraints = { pty_enabled = true } now fails with Loosening naming parent task.

Comment thread crates/mfile/src/expand.rs Outdated
) -> Result<(), BoxTypeError> {
for (_, constraints) in &box_type.constraints {
for (key, constraint) in constraints {
let Some(value) = expansion.spec.get(key) else {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

C2 · An absent key passes here, but the product then applies the built-in root default for it. A type that extends session with pty_enabled = false still gets a PTY. Check the root default for the key, as C2 says (lines 1234 and 1281).

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 70864457b8ee: Seeded session with pty_enabled = true, so a type that extends session with pty_enabled = false now fails at resolution as Loosening. A root default for a key that the root does not constrain is still not checked, because the root defaults table is empty in this tree.

/// [`BoxTypeError::ConstraintBroken`] for the first value that a
/// constraint excludes. It names `box_type`, the key and the layer that
/// set the value, and exits 3.
pub fn check_constraints(
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

C3 · No product path calls this function, and expand does not call it. Name the issue that adds the call after each expand on the create path in the PR body, as C3 says.

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 70864457b8ee: No code change. The residual is #3295, which adds the call after each expand in crates/minimal/src/cmd/boxes/create.rs. It is listed in the notes for the PR body.

check_constraints named the entry's own type for every failure, even
when the failing constraint came from a parent type. Check the entry's
type first and name the type whose constraints table failed.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 1 of 10 on the runtime's review findings, pushed as 24d497fd3cc7.

line exit tail
cargo nextest run -p mfile expanded_spec_violating_constraint_exit3_names_type_and_layer 0 warning: unknown fields in task runtime-implement-test-0: network warning: unknown fields in task runtime-implement-test-1: network warning: unknown fields in task runtime-implement-test-2: network help: do you need to update to a newer version of minimal? Applying loadouts: default Running task run
cargo nextest run -p mfile derived_type_loosening_constraint_exit3_names_type_key_parent 0 warning: unknown fields in task runtime-implement-test-0: network warning: unknown fields in task runtime-implement-test-1: network warning: unknown fields in task runtime-implement-test-2: network help: do you need to update to a newer version of minimal? Applying loadouts: default Running task run
cargo nextest run -p mfile constraint_never_adds_package_port_or_egress 0 warning: unknown fields in task runtime-implement-test-0: network warning: unknown fields in task runtime-implement-test-1: network warning: unknown fields in task runtime-implement-test-2: network help: do you need to update to a newer version of minimal? Applying loadouts: default Running task run

Verify min task run agent-verify passed.

Review threads the coder judged:

  • 👍 valid — crates/mfile/src/expand.rs: check_constraints now checks the entry's type first and names the type whose constraints table failed. A new test case (ci-small narrows restart to never) pins the message.

An entry that breaks a constraint of its type fails with exit 3. The message names the layer that set the value, the key, and the type whose constraints table holds the broken constraint. When a derived type narrows a parent, the message names the derived type.

Notes from the agent: Revise round 1. check_constraints now checks the chain from the entry's own type to the root, and it names the type whose table holds the failing constraint. A type only narrows its parent (BOX-156), so the first failure is the tightest constraint. The existing network.mode case in the test named ci-small for a constraint that only ci holds. It now expects ci. A new entry, small-always, pins the narrowed case.

@minimal-foundry minimal-foundry Bot 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.

minimal-review — approval withheld

Verdict COMMENT — APPROVE withheld: 4 unresolved threads — minimal-foundry[bot] crates/mfile/src/expand.rs, minimal-arch[bot] crates/mfile/src/box_types.rs:391, minimal-arch[bot] crates/mfile/src/expand.rs:312, minimal-arch[bot] crates/mfile/src/expand.rs:305. No findings.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

arch-review: CONDITIONS · 3 conditions · the full ruling

The check is in the right place and never writes the spec. Three gaps remain. The built-in types carry no constraints, so a task entry with pty_enabled = true passes. A project type that loosens task also passes (lines 1212-1216 and 1264, C2). A constraint on pty_enabled or restart misses the same setting written as io.pty_enabled or execution.restart, so an entry can override it (line 1288, C3). No product path calls check_constraints, and the PR names no issue for that work (line 1234, C1).

Ruled at 24d497f against gominimal/arch@15b603e6afb8 by claude-opus-5-5.

defaults.push(((*t).to_owned(), project.defaults.clone()));
constraints.push(((*t).to_owned(), project.constraints.clone()));
}
check_narrowing(&constraints)?;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

C2 · The root entry of constraints (line 385) is an empty table. So this check never compares a project type with its built-in parent, and check_constraints never applies the shipped constraints. Seed the root entry from the design table at lines 1212-1220. For example, task holds pty_enabled = false.

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 70864457b8ee: The root entry of constraints is now builtin_constraints(root): task holds pty_enabled = false, and build holds exec_enabled, loadout_mode and nesting.allowed as well.

Comment thread crates/mfile/src/expand.rs Outdated
) -> Result<(), BoxTypeError> {
for (type_name, constraints) in box_type.constraints.iter().rev() {
for (key, constraint) in constraints {
let Some(value) = expansion.spec.get(key) else {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

C3 · This line reads only the flat key. expand also accepts the setting under its section, such as io = { pty_enabled = true } or execution = { restart = "always" }, and the daemon reads io.pty_enabled. A constraint on pty_enabled then passes. Check both forms, with the map from the section tables in spec.rs (line 1288).

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 70864457b8ee: check_constraints now checks the flat key and

., with the section from spec::flat_key_section. Section-form constraints are lifted to the flat key in both directions.

/// constraint excludes. It names the type of the chain whose
/// `constraints` table holds that constraint, the key and the layer that
/// set the value, and exits 3.
pub fn check_constraints(
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

C1 · No product path calls this function. Add a residual line to the PR body. It must name the issue that calls check_constraints after each expand in crates/minimal/src/cmd/boxes/create.rs (line 1234).

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 70864457b8ee: No code change. The residual is #3295, which calls check_constraints after each expand in crates/minimal/src/cmd/boxes/create.rs. It is listed in the notes for the PR body.

@agent-137
Copy link
Copy Markdown
Member

/revise

Arch conditions (arch_rulings 1145, ruled at 24d497f), in full:

  • C1: Add a residual line to the PR body that names the issue for calling mfile::expand::check_constraints after each mfile::expand::expand in crates/minimal/src/cmd/boxes/create.rs (today lines 1345 and 1487), with the entry's BoxTypes::resolve_entry result. Open that issue if it does not exist. Until a caller exists, no product expansion runs the BOX-061 check.
  • C2: crates/mfile/src/box_types.rs BoxTypes::resolve: seed the root entry of constraints (today vec![(root.to_owned(), toml::Table::new())]) with the shipped type's constraints from the design table. session: pty_enabled = true. task, service, build, container-build: pty_enabled = false. build and container-build also: exec_enabled = false, loadout_mode = "sealed", nesting = { allowed = false }. agent: none. Add a test that a [tasks.x] entry with pty_enabled = true fails check_constraints naming the built-in type task, and that a project type with extends = "task" and constraints = { pty_enabled = true } fails BoxTypes::from_file with BoxTypeError::Loosening naming parent task.
  • C3: crates/mfile/src/expand.rs check_constraints: check each constrained setting wherever the expansion carries it, at the flat key and at the same key under its section (pty_enabled/exec_enabled and io.*, lifetime/loadout_mode and box.*, restart/timeout/exec/hooks_on_resume/on_oom and execution.*, packages and install.packages). Apply the same in both directions: a section-table constraint such as io = { pty_enabled = false } also checks a flat pty_enabled. Take the map from the section key tables in crates/mfile/src/spec.rs, not a second copy. Add a test that [boxes.x] type = "ci-small" with execution = { restart = "always" } and with io = { pty_enabled = true } both fail with ConstraintBroken.

C1: the issue is #3295. Name it in the PR body as a residual.

Each built-in Box Type now ships its constraints, so a project type
cannot loosen them and an entry of the type is checked against them.
A constrained setting is checked at its flat key and under its section,
with the section map taken from spec.rs.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 2 of 10 on a /revise note, pushed as 70864457b8ee.

line exit tail
cargo nextest run -p mfile expanded_spec_violating_constraint_exit3_names_type_and_layer 0 warning: unknown fields in task runtime-implement-test-0: network warning: unknown fields in task runtime-implement-test-1: network warning: unknown fields in task runtime-implement-test-2: network help: do you need to update to a newer version of minimal? Applying loadouts: default Running task run
cargo nextest run -p mfile derived_type_loosening_constraint_exit3_names_type_key_parent 0 warning: unknown fields in task runtime-implement-test-0: network warning: unknown fields in task runtime-implement-test-1: network warning: unknown fields in task runtime-implement-test-2: network help: do you need to update to a newer version of minimal? Applying loadouts: default Running task run
cargo nextest run -p mfile constraint_never_adds_package_port_or_egress 0 warning: unknown fields in task runtime-implement-test-0: network warning: unknown fields in task runtime-implement-test-1: network warning: unknown fields in task runtime-implement-test-2: network help: do you need to update to a newer version of minimal? Applying loadouts: default Running task run

Verify min task run agent-verify passed.

Outside the task's layers::

  • crates/mfile/src/spec.rs

Converted to a draft: something above needs a person before review.

Review threads the coder judged:

  • 👍 valid — crates/mfile/src/box_types.rs:394: BoxTypes::resolve seeds the root entry with builtin_constraints(root), so extends = "task" with constraints = { pty_enabled = true } now fails with Loosening naming parent task.
  • 👍 valid — crates/mfile/src/expand.rs: Seeded session with pty_enabled = true, so a type that extends session with pty_enabled = false now fails at resolution as Loosening. A root default for a key that the root does not constrain is still not checked, because the root defaults table is empty in this tree.
  • 👍 valid — crates/mfile/src/expand.rs:307: No code change. The residual is minimal: run the BOX-061 constraint check after each expansion in min's create paths #3295, which adds the call after each expand in crates/minimal/src/cmd/boxes/create.rs. It is listed in the notes for the PR body.
  • 👍 valid — crates/mfile/src/box_types.rs:394: The root entry of constraints is now builtin_constraints(root): task holds pty_enabled = false, and build holds exec_enabled, loadout_mode and nesting.allowed as well.
  • 👍 valid — crates/mfile/src/expand.rs: check_constraints now checks the flat key and
    ., with the section from spec::flat_key_section. Section-form constraints are lifted to the flat key in both directions.
  • 👍 valid — crates/mfile/src/expand.rs:307: No code change. The residual is minimal: run the BOX-061 constraint check after each expansion in min's create paths #3295, which calls check_constraints after each expand in crates/minimal/src/cmd/boxes/create.rs. It is listed in the notes for the PR body.

An entry that breaks a constraint of its type fails with exit 3. The error names the type, the key and the layer that set the value. This includes the constraints that the built-in types ship, for example a [tasks.x] entry with pty_enabled = true, and a value set under its section, such as io = { pty_enabled = true }.

Notes from the agent: C1: residual for the PR body: #3295 adds the call to mfile::expand::check_constraints after each mfile::expand::expand in crates/minimal/src/cmd/boxes/create.rs. Until it lands, no product expansion runs the BOX-061 check. I cannot edit the PR body, so the runner or a person must add this line. C2: BoxTypes::resolve seeds the root entry with builtin_constraints(root), from the table that the arch note gives. C3: check_constraints checks each flat setting at its flat key and under its section. canonical_constraints lifts a section-form constraint to its flat key, and check_narrowing uses the same form. Out of layers: crates/mfile/src/spec.rs gets one pub(crate) fn flat_key_section, which reads the SECTIONS table. C3 requires that map from spec.rs and forbids a second copy. Printed text: a Loosening error with a built-in parent now says its parent type task, not `its parent type the built-in type `task. The full mfile suite passed (151 tests) before cargo fmt, which changed only formatting. I did not run clippy-strict.

@minimal-foundry
minimal-foundry Bot marked this pull request as draft November 11, 2026 20:00
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

arch-review: CONDITIONS · 1 condition · the full ruling

The constraint check, the narrowing check and the built-in constraints conform to the design. 0be30fda seeds each (constrains) cell of the shipped-types table (lines 1216-1220), and checks section keys. No command calls check_constraints yet, so the product does not do the check that line 1234 requires after every layer. The PR body calls this later work but names no issue. Do C1: open the issue and add its URL to the PR body as a residual.

Ruled at 7086445 against gominimal/arch@15b603e6afb8 by claude-opus-5-5.

/// constraint excludes. It names the type of the chain whose
/// `constraints` table holds that constraint, the key and the layer that
/// set the value, and exits 3.
pub fn check_constraints(
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

C1 · This function is the check that line 1234 requires after every layer. No product path calls it. The expand calls in crates/minimal/src/cmd/boxes/create.rs (lines 1345 and 1487) do not run it. Open an issue for that call, and add its URL to the PR body as a residual.

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 b749d1d85b97: The doc comment on check_constraints now says no product path calls it yet, and names #3295, which adds the call after each expand in create.rs. The PR body names #3295 as a residual.

@agent-137
Copy link
Copy Markdown
Member

/revise

Arch condition (arch_rulings 1149, ruled at 7086445), in full:

  • C1: No product path calls mfile::expand::check_constraints. The mfile::expand::expand calls at crates/minimal/src/cmd/boxes/create.rs lines 1345 and 1487 do not resolve the type, and do not run the check after expansion. The PR body says that a later task must add this call, but it names no issue. Open a gominimal/minimal issue for this work. In the issue, require each create path to call check_constraints(&entry, &expansion, &resolved) after expand and to exit 3 on Err. Then add the issue URL to the PR body as a residual of T23.

The issue exists: #3295. Add it to the PR body as a residual of T23. No code change is needed.

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 3 of 10 on a /revise note: the coder changed nothing. Residual of T23: #3295 . No product path calls mfile::expand::check_constraints yet. The expand calls in crates/minimal/src/cmd/boxes/create.rs (lines 1345 and 1487) must resolve the type, call check_constraints(&entry, &expansion, &resolved) after expand, and exit 3 on Err. That file is outside this task's layers, so issue #3295 owns the call. Add this residual line to the PR body. This round changes no code, as the arch note asks.

@agent-137
agent-137 marked this pull request as ready for review November 11, 2026 21:51
@minimal-foundry minimal-foundry Bot 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.

minimal-review — approval withheld

Verdict COMMENT — APPROVE withheld: 8 unresolved threads — minimal-foundry[bot] crates/mfile/src/expand.rs, minimal-arch[bot] crates/mfile/src/box_types.rs:394, minimal-arch[bot] crates/mfile/src/expand.rs, minimal-arch[bot] crates/mfile/src/expand.rs:307, minimal-arch[bot] crates/mfile/src/box_types.rs:394, …. No findings.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

@agent-137
Copy link
Copy Markdown
Member

/revise

Arch condition (arch_rulings 1149, ruled at 7086445), in full:

  • C1: No product path calls mfile::expand::check_constraints. The mfile::expand::expand calls at crates/minimal/src/cmd/boxes/create.rs lines 1345 and 1487 do not resolve the type, and do not run the check after expansion. The PR body says that a later task must add this call, but it names no issue. Open a gominimal/minimal issue for this work. In the issue, require each create path to call check_constraints(&entry, &expansion, &resolved) after expand and to exit 3 on Err. Then add the issue URL to the PR body as a residual of T23.

The PR body now names #3295 as a residual. Arch has not re-ruled, because no commit followed. Make the change in the code too: on mfile::expand::check_constraints in crates/mfile/src/expand.rs, add a doc-comment sentence that no product path calls this function yet, and that #3295 adds the call after each expand in crates/minimal/src/cmd/boxes/create.rs. Change nothing else.

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

That /revise is held, not dropped. The container platform had no instance to give the coder: its pool of prepared containers was full, which happens most just after a deploy. Your note is kept and asked again every 10 minutes for up to 30; a wait that outlives that is refused here with the reason.

What the platform said

could not start the coder: Error: there is no container instance that can be provided to this durable object

Nothing to type again: the command gets a rocket when its round starts, or a refusal that names the reason. No round was counted for it yet.

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 4 of 10 on a /revise note, pushed as b749d1d85b97.

line exit tail
cargo nextest run -p mfile expanded_spec_violating_constraint_exit3_names_type_and_layer 0 warning: unknown fields in task runtime-implement-test-0: network warning: unknown fields in task runtime-implement-test-1: network warning: unknown fields in task runtime-implement-test-2: network help: do you need to update to a newer version of minimal? Applying loadouts: default Running task run
cargo nextest run -p mfile derived_type_loosening_constraint_exit3_names_type_key_parent 0 warning: unknown fields in task runtime-implement-test-0: network warning: unknown fields in task runtime-implement-test-1: network warning: unknown fields in task runtime-implement-test-2: network help: do you need to update to a newer version of minimal? Applying loadouts: default Running task run
cargo nextest run -p mfile constraint_never_adds_package_port_or_egress 0 warning: unknown fields in task runtime-implement-test-0: network warning: unknown fields in task runtime-implement-test-1: network warning: unknown fields in task runtime-implement-test-2: network help: do you need to update to a newer version of minimal? Applying loadouts: default Running task run

Verify min task run agent-verify passed.

Outside the task's layers::

  • crates/mfile/src/spec.rs

Converted to a draft: something above needs a person before review.

Review threads the coder judged:

An entry that breaks a constraint of its Box Type fails expansion with exit 3. The error names the type that holds the constraint, the key and the layer that set the value. A derived type that loosens a constraint of its parent fails to resolve. The doc comment on check_constraints now says that no create path calls it yet, and that #3295 adds that call.

Notes from the agent: Revise round 4: the only change is the doc-comment sentence that the directive asked for on mfile::expand::check_constraints. The call from crates/minimal/src/cmd/boxes/create.rs is outside this task's layers and is the residual #3295.

@minimal-foundry
minimal-foundry Bot marked this pull request as draft November 11, 2026 23:47
@minimal-foundry minimal-foundry Bot 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.

minimal-review — advisory review

Verdict COMMENT — 1 finding, 1 inline.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

Comment thread crates/mfile/src/box_types.rs Outdated
Comment on lines +446 to +452
name: (*name).to_owned(),
key,
parent: chain[i.saturating_sub(1)].0.to_owned(),
value: value.map(|v| inline(&v)),
});
}
resolved.insert(key, derived);
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.

LOW · correctness · confidence 0.50 · in check_narrowing

canonical_constraints can return the same flat key twice for one type, for example pty_enabled = false and io = { pty_enabled = true }. Its doc says each form constrains. check_narrowing keeps only the last one in resolved, so the first form is lost for later types. A conflict between the two forms in one type is also compared as if the earlier form came from the parent. The error then blames the immediate parent type, not the type that holds both forms. Only a contrived constraints table triggers this.

What the reviewer checked

box_types.rs:452 resolved.insert(key, derived); parent: chain[i.saturating_sub(1)].0

Hand this to an agent
Act on a code-review finding.

File:       crates/mfile/src/box_types.rs
Lines:      446-452
Category:   correctness
Severity:   low (reviewer confidence 0.50)

Finding:
`canonical_constraints` can return the same flat key twice for one type, for example `pty_enabled = false` and `io = { pty_enabled = true }`. Its doc says each form constrains. `check_narrowing` keeps only the last one in `resolved`, so the first form is lost for later types. A conflict between the two forms in one type is also compared as if the earlier form came from the parent. The error then blames the immediate parent type, not the type that holds both forms. Only a contrived constraints table triggers this.

First verify this against the code yourself. It is model output and
may be wrong. If it is wrong, or the tradeoff was deliberate, say so
and change nothing.

👍 useful · 👎 noise — react to tell the reviewer. Replying works too, and says more.

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 0af040b7e1ff: check_narrowing now checks each type only against the types before it, and keeps every form of a key for later types. A new case in derived_type_loosening_constraint_exit3_names_type_key_parent covers a key set flat and under its section.

@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling

The constraint check and the narrowing rule conform to the design. A derived type that loosens a constraint fails with exit 3, and the check never changes the spec. No product path calls check_constraints yet, so the product does not check the result after every layer (line 1234). C1 is that call, and #3295 tracks it. One design question is escalated: what the check does when no layer sets a constrained key. Settle it before #3295 wires the check.

Ruled at b749d1d against gominimal/arch@15b603e6afb8 by claude-opus-5-5.

///
/// The check reads the expansion and never changes it (BOX-062).
///
/// No product path calls this function yet. gominimal/minimal#3295 adds
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

C1 · No product path calls this check. Line 1234 says that type constraints are checked on the result, after every layer. #3295 adds the call after each expand in crates/minimal/src/cmd/boxes/create.rs. This is C1, and it can stay open at merge.

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.

Disputed — not addressed: The gap is real, but the call belongs in crates/minimal/src/cmd/boxes/create.rs. That file is outside this task's layers. #3295 adds the call after each expand. The doc comment on check_constraints names that issue. No change in this PR.

places.push((format!("{section}.{key}"), section.to_owned(), nested));
}
for (path, top, value) in places {
let Some(value) = value else {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

BOX-061 · An absent key passes here. The root layer of defaults is empty, so a session-rooted type that constrains exec_enabled = false passes for an entry that omits the key. The box then gets true. The design does not say what the check must do here (lines 1251-1253, 1281, 1288). This is escalated, so do not change this line in this PR.

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.

Disputed — not addressed: The reviewer escalated this and asked for no change in this PR, so the line stays as it is. After the merge, the root defaults layer carries builtin_defaults(root), but that holds only loadout_mode. An entry that omits exec_enabled still passes. The escalation must decide what an absent key does.

…-constraints-last-and-let-a-derived-ty

# Conflicts:
#	crates/mfile/src/box_types.rs
#	crates/mfile/src/expand.rs
A type that set a key flat and under its section was checked against
itself, and only its last form reached the types that extend it. Check
each type only against the types before it, and keep every form.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

A merge of main before round 5, not counted against the cap (1 of 3), pushed as 0af040b7e1ff.

Resolved conflicts in: crates/mfile/src/box_types.rs, crates/mfile/src/expand.rs

line exit tail
cargo nextest run -p mfile expanded_spec_violating_constraint_exit3_names_type_and_layer 0 warning: unknown fields in task runtime-implement-test-0: network warning: unknown fields in task runtime-implement-test-1: network warning: unknown fields in task runtime-implement-test-2: network help: do you need to update to a newer version of minimal? Applying loadouts: default Running task run
cargo nextest run -p mfile derived_type_loosening_constraint_exit3_names_type_key_parent 0 warning: unknown fields in task runtime-implement-test-0: network warning: unknown fields in task runtime-implement-test-1: network warning: unknown fields in task runtime-implement-test-2: network help: do you need to update to a newer version of minimal? Applying loadouts: default Running task run
cargo nextest run -p mfile constraint_never_adds_package_port_or_egress 0 warning: unknown fields in task runtime-implement-test-0: network warning: unknown fields in task runtime-implement-test-1: network warning: unknown fields in task runtime-implement-test-2: network help: do you need to update to a newer version of minimal? Applying loadouts: default Running task run

Verify min task run agent-verify passed.

Outside the task's layers::

  • crates/mfile/src/spec.rs

Converted to a draft: something above needs a person before review.

Review threads the coder judged:

  • 👍 valid — crates/mfile/src/box_types.rs: check_narrowing now checks each type only against the types before it, and keeps every form of a key for later types. A new case in derived_type_loosening_constraint_exit3_names_type_key_parent covers a key set flat and under its section.
  • 👎 invalid — crates/mfile/src/expand.rs:310: The gap is real, but the call belongs in crates/minimal/src/cmd/boxes/create.rs. That file is outside this task's layers. minimal: run the BOX-061 constraint check after each expansion in min's create paths #3295 adds the call after each expand. The doc comment on check_constraints names that issue. No change in this PR.
  • 👎 invalid — crates/mfile/src/expand.rs:338: The reviewer escalated this and asked for no change in this PR, so the line stays as it is. After the merge, the root defaults layer carries builtin_defaults(root), but that holds only loadout_mode. An entry that omits exec_enabled still passes. The escalation must decide what an absent key does.

An entry whose expanded spec breaks a constraint of its Box Type fails check_constraints with exit 3. The error names the type, the key and the layer that set the value. A project type that loosens a constraint of the type it extends fails to resolve, and the error names the type, the key and the parent.

Notes from the agent: Merged origin/main and resolved the conflicts in box_types.rs and expand.rs. The root layer of a type chain now takes main's builtin_defaults(root) and this branch's builtin_constraints(root). In expand.rs both sides were kept: check_constraints and main's LoadoutMode gate, and both test blocks. Main now seals task-rooted entries, so the loadout case in expanded_spec_violating_constraint_exit3_names_type_and_layer uses a new fixture entry ok-open with loadout_mode = "open". The merge commit includes main's changes to other crates (minimal, minimald, docs). I did not build those crates. The full mfile suite passes (156 tests). No product path calls check_constraints yet. #3295 tracks that call.

@agent-137
agent-137 marked this pull request as ready for review November 12, 2026 02:20
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling

The compare conforms. The fix in check_narrowing closes a gap. A type that set a key both flat and under its section passed on only one form. A derived type could then widen past the intersection that Box Types › Composition (line 1264) requires. The merge of main keeps the PR's own change intact. C1 stays open as residual #3295: no create path calls check_constraints yet, so line 1234 is not enforced on product expansions.

Ruled at 0af040b against gominimal/arch@15b603e6afb8 by claude-opus-5-5.

///
/// The check reads the expansion and never changes it (BOX-062).
///
/// No product path calls this function yet. gominimal/minimal#3295 adds
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

C1 · This function is correct, but no product path calls it. Line 1234 says type constraints are checked on the result, after every layer. Residual #3295 adds the call after each expand in crates/minimal/src/cmd/boxes/create.rs. The merge can go ahead while #3295 is open.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Tracked in #3295, which the PR body names as a residual. As this condition says, the merge goes ahead while #3295 is open: it adds the check_constraints call after each expand in crates/minimal/src/cmd/boxes/create.rs.

@minimal-foundry minimal-foundry Bot 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.

APPROVE withheld: 11 unresolved threads — minimal-arch[bot] crates/mfile/src/box_types.rs:413, minimal-arch[bot] crates/mfile/src/expand.rs, minimal-arch[bot] crates/mfile/src/expand.rs:319, minimal-arch[bot] crates/mfile/src/box_types.rs:413, minimal-arch[bot] crates/mfile/src/expand.rs, ….

minimal-review — advisory review

Verdict COMMENT — No findings.

Panel: 2 of 3 personas ran (correctness, security); did not complete: supply-chain.

@mitodrummer mitodrummer left a comment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Approved.

@mitodrummer
mitodrummer added this pull request to the merge queue Nov 12, 2026
Merged via the queue into main with commit 049c4fb Nov 12, 2026
37 checks passed
@mitodrummer
mitodrummer deleted the agent/2424-check-type-constraints-last-and-let-a-derived-ty branch November 12, 2026 06:37
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.

T23 — Check type constraints last, and let a derived type only narrow

2 participants

0