Skip to content

bundle: a bundle's identity stops at its own files, and its bound holds on every read (#908) - #934

Merged
valentinyanakiev merged 13 commits into
mainfrom
story-908-bundle-walk
Nov 1, 2026
Merged

valentinyanakiev merged 13 commits into
mainfrom
story-908-bundle-walk

Conversation

@valentinyanakiev

@valentinyanakiev valentinyanakiev commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

What changed

A bundle's identity stops at its own files.

  • The walk skips .git and git-ignored trees, as it skips its other unpinned trees. It still searches them, so a file the compile consumes inside one is refused by name.
  • One skip decision. It is made on the full relative path and shared by the walk, the consumed inputs and the pinned-script lookup.
    • .git at the top is git's metadata, decided before git is asked.
    • Git is asked check-ignore -- ./<rel>, so a path is a literal name, and a skipped tree's children inherit the answer.
    • If git cannot be asked (a failed discovery, or a check-ignore status other than 0 or 1), the bundle is refused by name with git's status and stderr. Brokkr never guesses.
    • A bundle outside any work tree skips only .git.
  • The bounds: a bundle past 5,000 files or 64 MiB per pinned layer (both inclusive) is refused by name before any run starts. Both checks use one past_bound message.
    • The metadata preflight judges the walked paths' listed sizes.
    • The bound is enforced again on the bytes actually read:
      • an unconsumed entry is read through a cap at the budget left plus one byte;
      • a consumed entry is charged the length of the buffer it was pinned from, never its metadata;
      • a consumed read stops at the bound plus one byte;
      • an integrity re-read stops at the pinned length plus one byte.
  • Decision 0083 gains a dated addendum (2026-10-29) and amendment (2026-10-31), both proposed.

Brokkr-Run: landing-pr-for-issue-908-bug-a-b-fdf84582

How it's held

  • Story, then fix rounds: 908b, the discovery refusal and one full-path decision; 908c, ./<rel> and git's stderr; 908d, the bound on bytes read; 908e, consumed charges, capped consumed and integrity reads, the amendment, test isolation, the shrink and vanish regressions.
  • 908d's own review never ran. OpenAI's cyber_policy filter refused its adversarial seat twice. The first landing, 908L, stood in for it and stopped at a security hold (C1-C5), which 908e fixed. 908e closed RESIDUAL-OK at LOW.
  • This landing (908L2) closed REVIEW-RESIDUAL-OK at LOW, with no security residual and no specification defect. It ran with a Fable 5.1 chief and DeepSeek Flash as the adversarial member.
    • Its chief checked every read path for its cap, the one skip decision at all three callers, and the bounds.
    • Scope: no contracts/, fixtures/, policy/ or reference/ change; no witness pin moved; the API ratchet holds. bundle.rs shrank 4,593 → 4,533 lines and places.rs is unchanged at 800.
  • Controller commits after 908e (each in its message, with removal controls):
    • 9c5a655, 908e's unsigned seat commit, signed with its tree unchanged;
    • 48ddd7f covers four lines and one branch: pinned_key's git-metadata arm, first_name and relative_text's None arms, and git's silent refusal;
    • 6ca6470 fixes a test comment (908e's INFO F2).
  • Tests: runtime lib 1,478; witness and frozen 24; queued_launch 8; CLI 68; recipes/self compiles with 0 unruled valuations.
  • Lints: fmt, clippy, typos, and the file, clone and API ratchets.
  • Coverage: exact coverage covered every line (78,686), branch (9,760) and function (10,553), with every test passing.

Commits since the landing

The landing vouched 6ca6470. Two controller commits followed it:

  • 4be15ab, test only. The landing's host coverage covered every line and branch, but only 10,552 of 10,553 functions. The miss was the walk's own refusal closure at walk.rs:84: every git-failure test was refused earlier, at the declaring document's consumed read.

    • a_check_ignore_failure_during_the_walk_refuses_by_name corrupts .git/index as the walk lists the bundle's root, so the walk's own question fails and is refused with git's words.
    • Removal control: a walk that reads a failed decision as "not skipped" lets the compile succeed and fails the test.
    • The coverage figures above are for this head.
  • 8b2d529, docs only (the landing's LOW F2). 0083's addendum said the preflight runs "before any byte is hashed", and the amendment said "before any byte is read". Both were overbroad: the consumed inputs are already read, each through its own cap, before the walk's preflight. Both now say "judged from the walked paths' listed sizes alone, before any walked byte is read or hashed". No bound, refusal or ruling moves.

  • a11934f, test only, after the PR's CI. The macOS leg failed two tests that pinned Linux's spawn error for a git started in a file ("Not a directory (os error 20)"); macOS reports "No such file or directory (os error 2)". The refusal is the same on both hosts. spawned_in_a_file() names each host's words, and both tests keep exact pins.

  • c3cec85, production (operator, 2026-11-01). The Ubuntu leg failed writer_lease and machine_proof::release. CI's temporary bundles sit under the repository's git-ignored target/, so git called every path ignored, bundle.json included. A bundle whose own root git reports ignored is now judged as a bundle outside any work tree: git_ignored asks check-ignore -- . first. Git's ignore question moved to places/ignored.rs (places.rs 800 → 714), and 0083's addendum says it.

    • a_bundle_inside_an_ignored_tree_of_its_repository_pins_its_own_files holds it, with a removal control.
    • The fresh landing landing-pr-for-issue-908-bug-a-b-fdf84582 judged the whole branch at c3cec85 and closed REVIEW-RESIDUAL-OK at LOW. Its chief checked every read cap, the one skip decision at every caller, and c3cec85 against git 2.51 in a scratch repository. Its one finding is the carried test-isolation LOW (tests: the repository-root bundle tests hold their verdict under an inherited GIT_CONFIG_COUNT (#908 F1) #936).
    • Exact coverage on this head covered every line (78,695), branch (9,762) and function (10,554).

Rulings asked (ruled 2026-10-31, as recommended)

  1. (a) The git-ignored rule's exact semantics, as above. Recommended: accept as built.
  2. (b) The bounds: 5,000 files and 64 MiB, inclusive per pinned layer, enforced by the metadata preflight and on the bytes actually read, with one refusal. Recommended: accept.
  3. (c) Decision 0083's 2026-10-29 addendum and its 2026-10-31 amendment, proposed, with 8b2d529's wording. Recommended: accept.
  4. (d) Whether a repository-root bundle stays reachable (the story's question 3). Bundle::compile reaches a repository root and applies the skip, as the tests prove.
    • The CLI's compile checks the layout of the workspace's root, not --bundle's path. So brokkr compile --bundle ., run inside a non-library repository whose root holds bundle.json, is refused by 0083 ruling 4, as it already was before this branch.
    • The same bundle named from another workspace compiles.
    • Recommended: accept that statement as built, with no change here.
  5. New: the two commits since the landing. Either the operator's by-hand label for 4be15ab (test only) and 8b2d529 (docs only), or a new landing run on this head. Recommended: the by-hand label, as ruled for protocol: an idle run driver walks its own tree to detect, and one full snapshot attributes (#918) #931's test-only coverage commit.
  6. Carried LOW F1 (test isolation, decision 0071 ruling 9), as a follow-up.
    • What fails: a test process that inherits GIT_CONFIG_COUNT/GIT_CONFIG_KEY_0/GIT_CONFIG_VALUE_0 pointing core.excludesFile at a file that lists roles/ fails a_repository_root_bundle_pins_neither_git_nor_an_ignored_tree. The adversarial member saw queued_launch::a_nested_folder_made_after_queueing_refuses_the_start fail the same way.
    • Production is right and refuses by name. The fix is test-only: the hardening must cover the process that runs Bundle::compile.
    • Recommended: a follow-up issue. Filed as tests: the repository-root bundle tests hold their verdict under an inherited GIT_CONFIG_COUNT (#908 F1) #936.

Ruling: operator 2026-11-01, in chat, "go with recommended" (#908, #908 (comment)): a bundle whose own root git ignores is judged as a bundle outside any work tree; a fresh landing re-judges the branch
Ruling: operator 2026-10-31, in chat, "push it by hand" (#908, #908 (comment)): the by-hand label also covers the test-only a11934f, the macOS spawn error pin
Ruling: operator 2026-10-31, in chat, "go with recommended" (#908, #908 (comment)): (a)-(d) as built, 0083's addendum and amendment with 8b2d529's wording; the by-hand label for the test-only 4be15ab and the docs-only 8b2d529; F1 a follow-up (#936)
Ruling: operator 2026-10-31, in chat, "go with recommended everywhere" (#908, #908 (comment)): fix round 908e for C1-C5
Ruling: operator 2026-10-30, in chat, "go with recommended" (#908, #908 (comment)): fix round 908d, the bound enforced on the bytes actually read
Ruling: operator 2026-10-30, in chat, "go with recommended on all the rulings" (#908, #908 (comment)): git is asked with ./<rel>; a check-ignore failure keeps git's stderr
Ruling: operator 2026-10-29, in chat, "go with recommended on the rulings" (#908, #908 (comment)): the walk skips .git and git-ignored trees and still searches them for consumed files; a bundle past a file-count or byte bound is refused by name before any run starts

Notes for the operator

  • INFO, not carried as defects:
    • git_ignored's --stdin parenthetical is half-wrong on git 2.51;
    • two git spawns per entry, with batching headroom;
    • the ignored-charter refusal's pre-existing "move it to … such as roles/" hint reads oddly when roles/ is the ignored tree.
  • Commit signatures could not be verified from the review seat (no GPG helper there). The host verifies them: every commit on the branch is signed.

Fixes #908.

🤖 Generated with Claude Code

valentinyanakiev and others added 11 commits October 31, 2026 09:00
…5,000 files or 64 MiB is refused by name before any run starts (#908)

The manifest walk asks git check-ignore for the bundle's repository. A
bundle outside a work tree skips only .git, as before; a git that cannot
answer refuses by name. The skipped trees are still searched for the
one-entry rule, so a consumed file, or a second name for one, inside an
ignored tree is refused by name. The bound is judged from the walked paths
before a byte is hashed, and names the count or bytes and the largest
top-level trees. Decision 0083 gains a proposed amendment; no shipped
recipe's digest moves.

Fixtures that hide the host's tools on PATH now plant git beside them,
because the compile asks it.

Removal controls:
- Dropped the ignore rule (unpinned_reason returned None): a_repository_root_bundle_pins_neither_git_nor_an_ignored_tree failed with "assertion failed: !files.keys().any(|key| key.starts_with(\"target/\"))"; with the digest equality asserted first, the same run failed on the moved identity ("left: cdd6f458..." vs "right: 52e614f7...").
- Dropped the skipped-tree search (`if skipped { return Ok(()) }`): a_second_name_inside_an_ignored_tree_is_refused_by_name failed with "expected compilation to fail".
- Dropped refuse_oversized: a_bundle_past_the_file_bound_is_refused_before_a_run_starts and a_bundle_past_the_byte_bound_is_refused_before_a_run_starts both failed with "expected compilation to fail".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Valentin Yanakiev <valentin.yanakiev@gmail.com>
… on the full relative path, so a nested ignored tree stays out of a bundle's identity (#908)

Fix round 908b for issue #908, on b22401a94. The operator ruled "Fix round
908b (Recommended)" and "go with recommended on the rulings" (2026-10-29).

- A directory with a `.git` at it or above it is asked of git; a non-zero
  `rev-parse --is-inside-work-tree` is now a refusal naming the bundle and
  carrying git's own stderr, never "not ignored". A directory with no
  `.git` anywhere still skips only `.git`, and a successful `false` answer
  (git's own metadata, a bare repository) still pins. Fixtures that marked
  a root with a bare `.git` directory now initialize a repository, because
  the compile asks git there.
- One full-relative-path `unpinned_reason` decides every skip. The walk
  asks it per entry and inherits a skipped tree's verdict for everything
  under it; the consumed-input clause and the pinned-script lookup ask the
  same function with the whole path, so a tree ignored at any depth is
  skipped and a file inside one is refused by its full relative path.
- `pinned_key`'s match names `GitMetadata` and `GitIgnored` explicitly, and
  both interface checks for `SkipError`'s display share one literal pin.
- Decision 0083's proposed addendum now states the full-path rule.

Removal controls:
- `!inside.status.success()` back to `Ok(false)` (a failed discovery read
  as "not ignored"): a_git_answer_that_cannot_be_read_refuses_the_bundle_by_name
  failed with "expected compilation to fail".
- `git_ignored` asked with the first component again: both
  a_nested_tree_git_ignores_is_skipped_at_any_depth (digest moved:
  74fe99... -> d1aa13...) and
  a_charter_inside_a_nested_ignored_tree_is_refused_by_name ("expected
  compilation to fail") failed.
- `if skipped && consumed.is_empty()` back to `if skipped` (the
  skipped-tree consumed search dropped):
  a_second_name_inside_an_ignored_tree_is_refused_by_name failed with
  "expected compilation to fail".

Gates: cargo fmt --all -- --check; cargo clippy --workspace --all-targets
--all-features --locked -- -D warnings; cargo test -p brokkr-runtime
--locked --lib (1449 passed); the runtime witness_digests:: and
frozen_contracts:: integration tests (24 passed, no witness moved);
cargo test -p brokkr-cli --test it --locked -- decisions_index:: doc_truth::
contributing:: doc_samples:: (68 passed); cargo run --locked -p brokkr-cli
-- compile --bundle recipes/self; typos --hidden; quality/ratchet.sh files,
clones and api; git diff --check. The full workspace run's only failures
are the 72 capability_broker tests that hardcode `/var/tmp`, read-only in
this box.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Valentin Yanakiev <valentin.yanakiev@gmail.com>
…ot marker stands for (#908)

Fix round 908b's return: `cargo test --workspace` failed in
queued_launch because two fixtures marked a repository root with a bare
`.git` directory. The walk now asks git in any directory that has a
`.git` at or above it and refuses by name when git cannot answer (#908),
so a bare marker is a refusal, not a marker. Both fixtures now make a
real repository through one shared `tests/support/git.rs` helper, which
the unit places fixtures also use, so the fixture has one home.

Removal controls (each planted, run, failed, restored):
- `!inside.status.success()` -> `Ok(false)`: a failed discovery read as
  "not ignored" makes
  bundle::tests::walk_908::a_git_answer_that_cannot_be_read_refuses_the_bundle_by_name
  fail with "expected compilation to fail".
- `unpinned_reason` asked of the first component again:
  bundle::tests::walk_908::a_nested_tree_git_ignores_is_skipped_at_any_depth
  fails with the digest moved from 74fe99... to d1aa13..., and
  bundle::tests::walk_908::a_charter_inside_a_nested_ignored_tree_is_refused_by_name
  fails with "expected compilation to fail".
- `if skipped && consumed.is_empty()` -> `if skipped`: the skipped-tree
  consumed search dropped makes
  bundle::tests::walk_908::a_second_name_inside_an_ignored_tree_is_refused_by_name
  fail with "expected compilation to fail".

Gates, all run in this session: cargo fmt --all -- --check; cargo clippy
--workspace --all-targets --all-features --locked -- -D warnings; cargo
test -p brokkr-runtime --locked --lib (1449 passed); cargo test -p
brokkr-runtime --locked --test it (143 passed, including
witness_digests:: and frozen_contracts::); cargo test -p brokkr-cli
--test it --locked -- --skip capability_broker:: (714 passed); cargo
test -p brokkr-cli --test it --locked -- decisions_index:: doc_truth::
contributing:: doc_samples:: (68 passed); cargo run --locked -p
brokkr-cli -- compile --bundle recipes/self; typos --hidden;
quality/ratchet.sh files, clones and api; git diff --check. The full
workspace run I observed failed in two environmental places only:
capability_broker's fixtures build under `/var/tmp`, read-only in this
sandbox, and brokkr-protocol's live-box proofs refuse `Identity` in this
unprivileged namespace.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Valentin Yanakiev <valentin.yanakiev@gmail.com>
…-ignore failure keeps its stderr (#908)

The manifest walk passed a bundle-relative path to `git check-ignore` bare.
`--` ends options but does not make the operand literal: a name beginning
with `:` is pathspec magic, so git judged a different path than the walk
named — an ignored charter was pinned and a non-ignored `:foo` was omitted.

Pass `./<rel>`, relative to the bundle git already runs in, so check-ignore
judges the literal name. A check-ignore failure now goes through
`git_refusal`, so the named refusal carries git's status and its own stderr.

Removal controls, each run on this change and observed to fail:
- passing `rel` without `./` again failed
  a_pathspec_shaped_name_is_judged_literally,
  a_name_beginning_with_a_colon_is_judged_literally and
  a_charter_under_a_colon_pathspec_is_refused_by_name;
- formatting the check-ignore failure without `git_refusal` again failed
  a_check_ignore_failure_refuses_by_name_with_gits_own_words.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Valentin Yanakiev <valentin.yanakiev@gmail.com>
…t only the preflight's metadata (#908)

The walk's metadata preflight refused a bundle past 64 MiB before any
byte was hashed, but `walk_digests` then read each unpinned file with
`std::fs::read`: a blob that grew after the preflight was hashed whole
and admitted with its enlarged digest (decision 0083 addendum ruling 2;
fix round 908d).

Each walked file is now read through `read_within`, capped at the byte
budget still left plus one. `spend` counts every entry cumulatively —
an unconsumed file's actual bytes, and a consumed entry's bytes, which
the bound read that supplied its digest already read and whose `intact`
check refuses any change — and refuses the moment the total passes
MAX_BYTES. The preflight and this refusal share one `past_bound`
message, so they cannot drift. The file-count bound and the cheap
metadata preflight are unchanged. A file that shrinks is admitted and
pinned at the bytes read; one that vanishes still refuses as before.

Removal controls, each run on this change and observed to fail:
- restoring `std::fs::read` and dropping the spend made
  a_file_growing_after_the_pre_hash_bound_is_refused_chief_908 fail
  with "expected compilation to fail";
- reading only the first five bytes in `read_within` made
  a_file_growing_within_the_bound_is_pinned_at_the_bytes_read fail
  with digest 599c4643... against ad10470f....

Gates, all run in this session: cargo fmt --all -- --check; cargo
clippy --workspace --all-targets --all-features --locked -- -D
warnings; cargo test -p brokkr-runtime --locked --lib (1453 passed);
cargo test -p brokkr-runtime --locked --test it -- witness_digests::
frozen_contracts:: (24 passed); cargo test -p brokkr-runtime --locked
--test queued_launch (8 passed); cargo test -p brokkr-cli --test it
--locked -- decisions_index:: doc_truth:: contributing:: doc_samples::
(68 passed); cargo run --locked -p brokkr-cli -- compile --bundle
recipes/self; typos --hidden; quality/ratchet.sh files, clones and
api; git diff --check. The 24 walk_908 tests pass. No witness moved and
no frozen path changed.

Signed-off-by: Valentin Yanakiev <valentin.yanakiev@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…tops at the bound plus one (#908)

C1: a consumed entry charges the length of the buffer whose digest it
supplied, never the metadata of an entry truncated after the read.
C2: bound_input and Held::intact read through the walk's one
read_within cap; a consumed input past 64 MiB is refused with the
shared past_bound text, and an integrity re-read stops at the pinned
length plus one.
C3: decision 0083's 2026-10-29 addendum gains its 2026-10-31
amendment, recording the 2026-10-30 ruling that the bound is enforced
on the bytes actually read as well as at the metadata preflight.
C4: the shared test_repository isolates git's global and system
configuration and pins its own core.excludesFile, so a host global
exclude cannot change what a fixture's walk pins.
C5: the walk's shrinking-file regression is committed, with the
vanished-file case beside it.

Removal controls, each observed then restored:
(i) charging a consumed entry from metadata again makes
    a_consumed_file_shrunk_during_the_walk_is_charged_its_pinned_bytes
    fail ("expected compilation to fail");
(ii) restoring the uncapped read_to_end in bound_input makes
     a_consumed_input_past_the_bound_is_refused_without_reading_it_all
     fail (it read 67108866 bytes against the 67108865 expected);
(iii) restoring it in Held::intact makes
      a_held_file_grown_past_its_pinned_length_is_not_intact_without_reading_it_all
      fail (position 67108866 against pinned+1 = 7);
(iv) dropping the fixture's git isolation makes the C4 control
     (GIT_CONFIG_GLOBAL listing roles/) fail with the ignored-charter
     refusal.

A further control moved the walk's Walked stage after the read: both
a_file_that_shrinks_during_the_walk_is_pinned_at_its_bytes_read and
a_file_that_vanishes_during_the_walk_is_refused fail, pinning the old
bytes and admitting the vanished file.

The bound stays 5,000 files and 64 MiB, inclusive per pinned layer, with
one past_bound message; no frozen path, witness, policy pin or public
declaration moved; bundle.rs is 4,533 lines and places.rs is unchanged.

Signed-off-by: Valentin Yanakiev <valentin.yanakiev@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…anished-file test binds its io kind (#908)

C4 (review F1): the repository-root test now runs its compile in a child
process whose GIT_CONFIG_GLOBAL names a config whose core.excludesFile
lists roles/. The repository's own core.excludesFile set by
test_repository wins, so the charter stays pinned; the child must report
that it ran one test, so a filter mismatch cannot pass vacuously.

C5 (review F2): a file that vanishes during the walk is asserted as
CompileError::Io with ErrorKind::NotFound, not by its display text;
a_walked_file_that_vanishes_before_the_bound_is_refused keeps the
module's one display pin.

Removal controls, each observed then restored:
(i) charging a consumed entry from metadata again makes
    a_consumed_file_shrunk_during_the_walk_is_charged_its_pinned_bytes
    fail ("expected compilation to fail");
(ii) restoring the uncapped read_to_end in bound_input makes
     a_consumed_input_past_the_bound_is_refused_without_reading_it_all
     fail (67108866 pinned bytes against 67108865 expected);
(iii) restoring it in Held::intact makes
      a_held_file_grown_past_its_pinned_length_is_not_intact_without_reading_it_all
      fail (position 67108866 against 7);
(iv) dropping the fixture's local core.excludesFile makes the committed
     hostile-global test fail with the ignored-charter refusal, while
     a_repository_root_bundle_pins_neither_git_nor_an_ignored_tree still
     passes;
(v) losing the vanished stat's ErrorKind in consumed_entry makes
    a_file_that_vanishes_during_the_walk_is_refused fail (Other against
    NotFound).

The bound stays 5,000 files and 64 MiB, inclusive per pinned layer, with
one past_bound message; no frozen path, witness, policy pin or public
declaration moved; bundle.rs is 4,533 lines, places.rs is unchanged, and
walk_908's file stays under the test ceiling.

Signed-off-by: Valentin Yanakiev <valentin.yanakiev@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… git's silent refusal are each held by a test (#908)

Exact coverage on 908e's head (cfd6c2655) covered every function but
missed four lines and one branch, all on this branch:

- crates/brokkr-runtime/src/bundle.rs:2717, `pinned_key`'s
  `Skip::GitMetadata` arm. a_pinned_script_under_git_metadata_is_refused_by_name
  asks for `./.git/hooks/run.sh` and is refused with "git's own
  metadata, which no bundle pins".
- crates/brokkr-runtime/src/places.rs:270 and :282, the `None` arms of
  `first_name` and `relative_text`.
  a_path_that_is_not_plain_names_is_never_spelled_for_git holds that
  `../x` has no first name and `a/../b` has no spelling for git, beside
  their plain counterparts.
- places.rs:387-388, `git_refusal` when git says nothing on stderr.
  a_git_refusal_names_its_status_with_or_without_stderr holds both
  forms: "git check-ignore answered exit status: 128" and the same with
  git's words after it.

places.rs is unchanged (at its 800-line ceiling); the tests live in
places/places_tests.rs and bundle/tests/walk_908.rs.

Removal controls, each failing its named test and restored:
- dropping the `.git` first-name check fails
  a_pinned_script_under_git_metadata_is_refused_by_name (walk_908.rs:358);
- `first_name` reading any first component's text fails the
  not-plain-names test at its `../x` assertion (places_tests.rs:554);
- `relative_text` joining every component's text fails it at its
  `a/../b` assertion (:556);
- `git_refusal` always appending stderr fails the silent-refusal
  assertion (:574).

Gates: cargo fmt --all -- --check; cargo clippy -p brokkr-runtime
--all-targets --all-features -D warnings; brokkr-runtime lib places::
and bundle::tests::walk_908 (62 passed); quality/ratchet.sh files and
clones; typos; git diff --check.

Signed-off-by: Valentin Yanakiev <valentin.yanakiev@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… the bundle's root (#908)

908e's review INFO F2: hostile_global's comment (bundle/tests/walk_908.rs)
said its exclude file is outside the fixture's root. Fixture::root is the
canonicalised temporary directory and both files are joined to it, so
they are ordinary pinned entries. The comment now says so and that the
tests using them assert only the charter and the skipped trees. Comment
only; no test or behaviour changes.

Signed-off-by: Valentin Yanakiev <valentin.yanakiev@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…by a test (#908)

Host coverage of landing 908L2's head (6ca6470) covered every line and
branch but 10,552 of 10,553 functions: the walk's own map_err closure at
crates/brokkr-runtime/src/bundle/walk.rs:84, which turns a failed skip
decision into the walk's refusal. Every existing git-failure test is
refused earlier, when the declaring document's consumed read asks the
same question, so the walk's own ask never failed under test. (908e's
host coverage had the same function miss beside its lines.)

a_check_ignore_failure_during_the_walk_refuses_by_name lets the consumed
reads pass on a healthy repository, then corrupts .git/index as the walk
lists the bundle's root (ReadStage::Listing): the walk's first entry that
asks git is refused with git's own words, through the walk's own
CompileError, and nothing is pinned or skipped by guessing.

Removal control: the walk reading a failed skip decision as "not
skipped" (`.ok().flatten().is_some()`) lets the compile succeed and
fails the test; restored.

Gates: cargo fmt --all -- --check; cargo clippy -p brokkr-runtime
--all-targets --all-features -D warnings; brokkr-runtime lib
bundle::tests::walk_908 and places:: (63 passed); git diff --check.

Signed-off-by: Valentin Yanakiev <valentin.yanakiev@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… not any byte (#908)

Landing 908L2's LOW F2 (decision 0071 ruling 5): walk_files
(bundle.rs:4297-4302) receives the consumed inputs, whose buffers
bound_through already read through the MAX_BYTES cap and Pinned::of
already hashed, and only then calls refuse_oversized. So the 2026-10-29
addendum's point 2 ("before any byte is hashed") and the 2026-10-31
amendment's "before any byte is read" were overbroad.

Point 2 now says the bound is judged from the walked paths' listed sizes
alone, before any walked byte is read or hashed. The amendment quotes
it, and says the consumed inputs were read before the preflight, each
through its own cap. Docs only: the behaviour is bounded either way, and
no bound, refusal or ruling moves.

Gates: decisions_index:: and doc_truth:: (39 passed); typos; git diff
--check.

Signed-off-by: Valentin Yanakiev <valentin.yanakiev@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
valentinyanakiev and others added 2 commits October 31, 2026 23:20
…s ENOENT and Linux's ENOTDIR (#908)

PR #934's macOS CI leg (run 41240540032) failed two tests that pin the
error git's spawn reports when the bundle is a file, not a directory:
a_git_that_cannot_be_asked_refuses_by_name and
a_pinned_script_lookup_that_cannot_ask_git_refuses_by_name expected
Linux's "Not a directory (os error 20)", but macOS's posix_spawn reports
"No such file or directory (os error 2)" for a working directory that is
a file. The production refusal is the same on both hosts (refused by
name, git's words); only the OS text differs. Decision 0063 keeps both
as hosts, so spawned_in_a_file() names each host's words and both tests
keep exact pins.

Test only. Gates: cargo fmt; cargo clippy -p brokkr-runtime
--all-targets --all-features -D warnings; brokkr-runtime lib
bundle::tests::walk_908 (32 passed, on Linux). The macOS leg is CI's.

Signed-off-by: Valentin Yanakiev <valentin.yanakiev@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…bundle outside any work tree does (#908)

PR #934's Ubuntu CI leg (run 41243528039) failed writer_lease's
a_real_boxed_exec_strikes_from_inside_its_lease_and_every_protected_byte_stands
and machine_proof::release::a_killed_engines_worktree_is_released_by_the_operator_and_a_conflicting_run_admits:
CI's temporary directories sit under the repository's git-ignored
target/, so git answered "ignored" for every path of a bundle placed there,
its own bundle.json included, and the compile refused the declaring
document. Any bundle inside an ignored tree of an enclosing repository
(a scratch or build directory) was unusable; local runs, with TMPDIR
outside the repository, never saw it.

The operator ruled 2026-11-01, "go with recommended" (#908,
#908 (comment)):
a bundle whose own root git reports ignored lies outside the repository's
tracked content and is judged as a bundle outside any work tree: it skips
only .git and the fixed names, and no git-ignore skip applies inside it.
git_ignored asks `check-ignore -- .` (the bundle itself) before the
entry, through one check_ignore helper, so both answers keep the
refusal-by-name on any status but 0 or 1.

git's ignore question moves to the new places/ignored.rs
(stands_in_git, git_ignored, check_ignore, git_refusal), so places.rs
goes from its 800-line ceiling to 714. Decision 0083's 2026-10-29
addendum says the new sentence.

a_bundle_inside_an_ignored_tree_of_its_repository_pins_its_own_files: a
repository ignoring scratch/ and target/, a bundle at scratch/bundle
with its own target/artifact: it compiles, and pins roles/role.md and
target/artifact.

Removal control: dropping the root check fails the test by name with the
declaring-document refusal CI saw; restored. With TMPDIR under this
worktree's target/, the two CI failures pass.

Gates: cargo fmt --all -- --check; cargo clippy --workspace
--all-targets --all-features -D warnings; brokkr-runtime lib (1,480
passed); queued_launch (8); brokkr-cli it writer_lease:: and
machine_proof::release:: under TMPDIR=target/tmp (2); decisions_index::
and doc_truth:: (39); quality/ratchet.sh files, clones and api; typos;
git diff --check.

Signed-off-by: Valentin Yanakiev <valentin.yanakiev@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@valentinyanakiev
valentinyanakiev added this pull request to the merge queue Nov 1, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Nov 1, 2026
@valentinyanakiev
valentinyanakiev added this pull request to the merge queue Nov 1, 2026
Merged via the queue into main with commit a6c965d Nov 1, 2026
22 of 23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

by-hand Operator-only escape hatch for 'delivered by brokkr' (decision 0033)

Projects

None yet

1 participant