Repository navigation
Conversation
Add a non-mutating source seam for production verifier functions, generic provider-facts regression coverage, and guarded live SBX/MSB validation procedures that record PASS, FAIL, or BLOCKED honestly. Co-authored-by: OpenCode Agent <agent@gsa.gov>
On macOS the host-config dir often resolves through the /var -> /private/var alias (e.g. when HOME or XDG_STATE_HOME sits under /var/folders/...). msb cannot mount a symlinked host path and fails with "mount ...: Not a directory (os error 20)". The workspace mount already calls canonicalize_path for the same reason (diagnosed at msb.sh lines 3574-3579); apply the identical guard to the host-config dir mount source. Falls back to the original path when canonicalize_path is unavailable. The dir is acq-owned (not user-supplied) so there is no arbitrary-symlink-traversal risk. Closes #594 Tests: 71c-msb-canonical-host-config.bats covers the Darwin /var alias simulation (case a) and an arbitrary symlink negative-control (case b). Co-authored-by: OpenCode [claude_4_6_sonnet] <bret.amogilefsky@gsa.gov>
Pass the provider generation through SBX workspace mount syntax after the agent token so it is not resolved as a kit path. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Verify the provider root environment token independently of trailing kit and workspace arguments in the consolidated adoption branch. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Record observed SBX/MSB results without overstating unexecuted rows and add an actionable opencode models check for the next live run. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Preserve observed SBX and MSB startup, config-generation, model-listing, and verifier results while keeping unexecuted destructive/negative rows explicitly blocked. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Keep the focused MSB signal regression self-contained until the trusted macOS canonicalizer lands on main. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Install the adapter projection boundary after sourcing the MSB adapter while preserving the narrow canonicalizer contract. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Preserve SBX positional grammar by placing the provider generation mount after the agent and primary workspace. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Update SBX create assertions for the corrected positional mount order. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Reflect provider mount placement and current interactive environment tokens. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Record post-fix SBX and MSB live validation totals and model-list evidence. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Record the observed interactive MSB run, USAi model listing, and successful model response. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Record successful interactive USAi model requests on both SBX and MSB without retaining secret material. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Convert malformed provider-input JSON into an actionable acq diagnostic before schema validation. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Record observed fail-closed malformed provider input rejection on SBX and MSB. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Allow an authoritative empty provider set without changing the default USAi selection. Co-authored-by: OpenCode [gpt-5.6-terra] <bret.mogilefsky@gsa.gov>
Use Bash 3.2-safe empty-array expansion when no provider kits are selected. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Record successful no-provider SBX and MSB validation evidence. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Silence dynamic-global ShellCheck checks and tolerate current interactive environment tokens. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Use a per-test sandbox, lock, and PID path so parallel workers cannot share signal lifecycle state. Co-authored-by: OpenCode Agent <agent@gsa.gov>
Replace guest-writable extra-kit markers with host-authoritative state for SBX create and heal paths. Refs: #636 Co-authored-by: OpenCode [gpt-5.6-terra] <bret.mogilefsky@gsa.gov>
…ntity Replace the bare `opencode models | grep -q "^usai/"` with a comparison of the projected snapshot's model IDs against both the rendered OpenCode config's model keys for the provider and the `opencode models` output. Missing or unexpected IDs fail and print the difference. Offline bats cases cover exact match, stale, missing, extra and empty-snapshot inputs plus the guest collection script. Not yet exercised on a live SBX or MSB host. Co-authored-by: OpenCode Agent <bret.mogilefsky@gsa.gov>
…ending row Replace the unspecified temporary override and BLOCKED instruction with the supported flag and reproducible omission assertions (no USAi kit or credential gate, no usai projection, no usai models). Record the new identity-bound model check as PENDING: it has not been run on a live SBX or MSB host. Co-authored-by: OpenCode Agent <bret.mogilefsky@gsa.gov>
…rocedure notes Co-authored-by: OpenCode Agent <bret.mogilefsky@gsa.gov>
e023fd3 to
55f3c27
Compare
7c07a31 to
5c80304
Compare
|
🤖: AI agent (First Mate), posting on behalf of @mogul. Branch update for the Windows re-run: PR 642 was merged into Please run the re-run steps from my previous comment against |
|
Windows re-run on the junction-fix head + the earlier follow-ups, combined. Re-run:
|
| # | result | test |
|---|---|---|
| 1 | ok |
windows: safe_mkdir succeeds on a real path |
| 2 | ok |
windows: safe_mkdir rejects an ancestor junction |
| 3 | ok |
windows: safe_dir rejects an ancestor junction |
| 4 | ok # skip |
windows: safe_mkdir rejects an ancestor symlink — directory symlink creation unavailable (developer mode / elevation required) |
| 5 | ok # skip |
windows: safe_dir rejects an ancestor symlink — directory symlink creation unavailable (developer mode / elevation required) |
The safe_mkdir ancestor-junction test now passes. 3 passed, 0 failed, 2 skipped (symlink-only). Test 2 asserts both assert_failure and [ ! -e "$target/new_child" ], so the projection is rejected and not redirected into the junction target.
The MSYS2_ARG_CONV_EXCL/MSYS_NO_PATHCONV opt-out is honored on this host — cross-checked directly:
MSYS2_ARG_CONV_EXCL='*' MSYS_NO_PATHCONV=1 python3 -c 'import sys;print(sys.argv[1])' /tmp/diag-jt/link/new_child
→ /tmp/diag-jt/link/new_child # link still present (unrewritten)
# control, no env vars:
python3 -c 'import sys;print(sys.argv[1])' /tmp/diag-jt/link/new_child
→ C:/Users/bmogi/AppData/Local/Temp/diag-jt/target/new_child # junction resolved
So the literal-path walk fix works as intended on real Git Bash.
Earlier follow-ups (from the previous run)
Developer Mode: BLOCKED on this host. The session is non-elevated — reg add HKLM\...\AppModelUnlock returns ERROR: Access is denied, and the token has no SeCreateSymbolicLinkPrivilege. mklink /D fails with "You do not have sufficient privilege to perform this operation", while mklink /J succeeds. So the two directory-symlink tests (4/5) can only skip here; they need an elevated shell or a Dev-Mode-enabled runner. (Also note: MSYS=winsymlinks:nativestrict breaks bats-core itself — it can't create its test-source symlink and runs 0 of 5 tests — so that specific repro can't be run here regardless.)
Baseline on main (worktree ec73abd, submodules pinned):
- 112
msb ports: LIST mode surfaces …— not ok onmaintoo (byte-identical TAP), so pre-existing. Root-caused: native Windowsjq(WinGet) writes CRLF, and the digit guard in_acq_msb_ports_from_inspectdrops every record with a trailing\r(all but the last create-time port). Reproducible A/B (stripping\rmakes it pass). Separate Windows-portability defect, not this PR. - 117
msys: ssh authorize --file …— passes on both branches; no hang in isolation (~31 s). The earlier "hang" was a contention/timeout artifact. (Full 117: PR is 11/11;mainis 9/11 — this PR fixes two of those.)
146 / 148 / 149 run individually (ACQ_BATS_JOBS=1, TMPDIR=/c/tmp):
| file | ok | not ok | skip |
|---|---|---|---|
| 146-provider-verification | 28 | 0 | 0 |
| 148-provider-credential-bindings | 56 | 0 | 0 |
| 149-kit-source | 38 | 0 | 0 |
All green. The earlier fork-exhaustion / loader errors were contention/timeout artifacts — no fork: Resource temporarily unavailable or /src/output.bash error in any serial run, and git submodule status is healthy (all three vendors pinned/populated).
Bottom line: the junction bypass is fixed and confirmed on a real Windows host; the only windows: tests still not exercisable here are the two directory-symlink ones (need elevation/Developer Mode, which this host can't provide).
|
🤖: AI agent (First Mate), posting on behalf of @mogul. Thank you; this is exactly the evidence needed.
|
…bility # Conflicts: # acq.backends/common.sh # acq.backends/msb.sh # acq.backends/sbx.sh # test/bats/149-kit-source.bats # test/bats/50-kit-list-completeness.bats
Bash 3.2 does not understand a here-document inside a process substitution; it scans the body for quote and parenthesis balance. The Python comment added for the CRLF fix contained an apostrophe and a backtick, so the whole of common.sh failed to parse under bash 3.2 and every facts reader test failed there. Move the explanation to the shell side above the function and keep the heredoc body free of apostrophes, backticks, odd double quotes, and unbalanced parentheses. Add a static scan, run as a bats test under whatever bash executes the suite, that fails when a heredoc nested in a command or process substitution has such a body anywhere in acq, acq.backends, or scripts, and a test that the facts reader output carries no carriage return.
basiliskus
left a comment
There was a problem hiding this comment.
Verdict: request changes — 077677fab1e4c6438ab77c1d0796fb150fb274f2
The earlier descriptor-read, inherited-git-rewrite, and ancestor-junction findings are resolved. One Windows blocker remains:
- Major —
acq.backends/common.sh:4609: provider-input publication still usesln -sfor thecurrentpointer. On the real Windows run, Git Bash’s symlink fallback caused thereadlink "$root/current"tests to fail. Therefore a successful backend create can still fail during publication or leavecurrentas the wrong object type on a non-elevated, non-Developer-Mode host. Please use a reliable Windows-safe current-pointer mechanism or fail before creating the backend, and add Windows publication coverage.
CI’s Bash 3.2 job is still in progress; elevated Windows directory-symlink tests also remain unverified.
Assisted-by: OpenCode [gpt-5.6-sol-latest-guardrails-defaultv2] skill:change-review
Publication used `ln -s` for the `current` pointer, which Git Bash silently degrades to a directory copy on a non-elevated, non-Developer- Mode Windows host — leaving `current` as the wrong object type and breaking `readlink`-based checks. Use a junction (`mklink /J`, which needs no elevation) on Windows instead, and remove the old pointer before swapping since Windows cannot atomically replace an existing junction. Add Windows publication coverage that asserts `current` is a junction and that both generations survive repeated publication.
|
Addressed the remaining Windows blocker (review on
Added Still unverifiable here (unchanged): the two elevated/Developer-Mode directory-symlink tests, which need a Developer-Mode or elevated runner. |
basiliskus
left a comment
There was a problem hiding this comment.
Verdict: request changes — 388d2aa34eb00610f79d34299890b7eaf9e03b49
The previous Windows publication finding is resolved: current is now created as a junction, and the real-Windows success-path evidence covers repeated publication. One failure-path regression remains:
- Major —
acq.backends/common.sh:4651-4652: the Windows path removes the existingcurrentjunction beforeos.replace, but does not restore it if replacement fails. I reproduced the failure through the helper seam: publication returned nonzero and leftcurrentabsent while both generations remained intact. Please preserve or restore the previous pointer on swap failure and add an MSYS-branch regression corresponding to the existing “failed atomic swap preserves prior current generation” test.
Bash 3.2 CI is still in progress; elevated Windows directory-symlink tests also remain unverified.
Assisted-by: OpenCode [gpt-5.6-sol-latest-guardrails-defaultv2] skill:change-review
…swap The Windows swap moved the old `current` junction aside before the `os.replace`, but did not restore it if the replace failed — leaving `current` absent even though both generations stayed intact. Back the old pointer up and restore it on failure, and add an MSYS-branch regression test for the failed-swap case.
|
Addressed the failed-swap regression (review on The Windows swap now backs up the existing |
basiliskus
left a comment
There was a problem hiding this comment.
Verdict: approve — 2b6f62ccc4fc13aa8a415e5f1e426ce27c269b89
The prior Windows failed-swap finding is resolved. The implementation backs up the existing current junction before replacement and restores it on failure; the new real-Windows regression verifies that current still points to the old generation and both generations remain intact. I found no new correctness, security, scope, test-adequacy, or regression issues.
Assisted-by: OpenCode [gpt-5.6-sol-latest-guardrails-defaultv2] skill:change-review
wz-gsa
left a comment
There was a problem hiding this comment.
Fixed-head rereview of 2b6f62ccc4fc13aa8a415e5f1e426ce27c269b89 (full eight-file diff inspected; required checks pass). The revised Windows path helpers reject pre-planted junctions, but publication still has a failure-path blocker: acq.backends/common.sh:4665-4673 moves current to backup, attempts the new pointer, then ignores _acq_provider_input_move_link "$backup" "$current" failure before deleting temp and returning. If restore fails, current stays absent despite the new comment promising otherwise; the Windows test at test/bats/147-provider-input-projection.bats:1125-1144 injects only the initial swap failure. Check restore status, preserve/report the backup on failure, and add a restore-failure negative fixture. Also, the successful Windows two-rename swap necessarily has a period with no current name; readers in common.sh use that path without the transaction lock. Either make reader behavior explicitly tolerate this gap (with tests) or stop claiming the pointer is never absent. Further trust-boundary concern: common.sh:4575-4578,4653-4655 uses pathname checks then recursive chmod/rm on paths that may be swapped for reparse points; the portable lstat tests cover pre-planted links only. Establish a private non-attacker-writable parent or use handle-bound operations and add a swap test before presenting this as a race-safe Windows boundary. No PR code was executed on the host. AI-assisted adversarial review (OpenCode); rereview a corrected head.
|
🤖: AI agent (OpenCode), posting on behalf of @mogul. Dependency note: this PR should land after #667.
|
|
🤖: AI agent (OpenCode), posting on behalf of @mogul. Correction to my earlier dependency note on this PR. This PR still waits on #667, but #667 is not yet ready to merge: |
|
Note: I'm holding off on chasing down those Windows-related bash-ism PRs because I would rather get the 🐍 version upstreamed and not deal with them. I've made that explicit by putting them back in the draft state. I'll keep them open until I determine that the 🐍 version will be arriving soon, so we're sure don't need to do this specific fix merged as an interim state. |
Point 151-heredoc-in-substitution at scripts/scan-heredoc-subst.py instead of the duplicate test/bats/heredoc-scan.py, and remove that duplicate. The canonical scanner was introduced by the bash 3.2 test runner (#653); this deconflicts the two in-flight heredoc scanners. Co-authored-by: OpenCode [deepseek-v4-pro] <bmogilefsky@gmail.com>
Summary
Fixes five Windows/MSYS portability bugs in the provider-input and kit-fetch paths that surfaced while running
acq --backend msbunder Git-Bash (MSYS2) on Windows against the provider-neutral branch. Without these,acq createfails partway through provisioning.Fixes
common.sh):ps -o ppid=/ps -o lstart=are rejected by MSYSps(no-oflag), so the guardian's transaction-PID check and the lock's process-identity aborted. Added MSYS-aware fallbacks (parseps -pcolumns /WINPID).os.O_DIRECTORY/os.O_NOFOLLOW/dir_fdare missing from Windows Python, so the safe-dir traversal helpers raisedAttributeError. Guarded withhasattrand fell back toos.path.islink/os.makedirs./c/...→C:/..., which the manual/-split turned into a bogus/C:component. Switched to drive-awareos.path/os.makedirs.kit-translate.sh): an emptyinsteadOfvalue makes git treat the empty string as a match prefix and prependhttps://github.com/to every URL (fetch 404s onhttps://github.com/https://github.com/...). Replaced with an identity rewrite (insteadOf=https://github.com/), a no-op that still shadows a user'surl.<x>.insteadOf=https://github.com/rewrite for the anonymous attempt.msb.sh): the cache subdir was the full sanitized kit ref (URL + sha + dir), which exceeds Windows MAX_PATH once git materializes.git/objects/pack/*under it (Filename too longon fetch). Keyed by a hash of the ref instead.Verification
Ran
acq --backend msb create ...live against the branch and iterated past each failure in order: msb detection →provider-credential/secret → agent-kit selection → provider-input staging → kit fetch.bash -nclean on all three files.Not fixed here (separate issue)
The pinned patterns validator requires the normalizer's executable bit (
normalizer_path.stat().st_mode & 0o111), which Windows never reports: Windows Python'sos.stathas no exec bits, and neitheros.chmodnor achmod +xround-trips one. That check needs a Windows-aware guard inagentic-coding-patterns(scripts/validate_provider_input_contract.py).Related
Test 151 now calls the shared
scripts/scan-heredoc-subst.pyinstead of a second copy, so the here-document-in-substitution check lives in one place.Closes #665
AI-assisted (OpenCode). Human review required.