Repository navigation
With --manifest-path into another project, rollback, remove, repair, vex, scan and get read the vendored ledger from --cwd #745
Description
Activity
- addedbugSomething isn't workingSomething isn't workingarch-auditFiled by a scheduled architecture audit routine (see the architecture review discussion)Filed by a scheduled architecture audit routine (see the architecture review discussion)
on Oct 4, 2026 mikolalysenko commented
on Oct 4, 2026 CollaboratorAuthorMore actions[agent] Triaged:
priority:p3(cross-cutting CLI). Not a duplicate, and no existing fix PR. #499 fixed the relatedvendor -grewiring of the cwd project, but it doesn't cover the ledger root used by rollback/remove/repair/vex/scan/get.
Generated by Claude Code
mikolalysenko commented
on Oct 8, 2026 CollaboratorAuthorMore actions[agent] Re-checked on
b96a785. The finding still holds, and the code has moved. #1029 now validates that the--manifest-pathproject directory exists, but nothing aligns which root the ledger is read from.- Reads the ledger from the manifest's project (
project_root()):listandapply, throughcontext.rs#L67. - Reads it from
--cwd:rollbacklocks the manifest's.socket/atrollback.rs#L1150, then loads the ledger from cwd atrollback.rs#L1170.removeatremove.rs#L451.vexatvex.rs#L1279.scanatscan/mod.rs#L1746andscan/hosted.rs#L822.getatget.rs#L1485.vendor's revert and eject paths: sixload_state(&common.cwd)calls invendor.rs, for examplevendor.rs#L3853.
Generated by Claude Code
- Reads the ledger from the manifest's project (
- addedv5-blockerMust resolve before v5: public interface/migration or ordinary patch-install-undo failure.Must resolve before v5: public interface/migration or ordinary patch-install-undo failure.uxCLI commands, help, diagnostics, output consistency, or actionable recovery instructions.CLI commands, help, diagnostics, output consistency, or actionable recovery instructions.compatibilityPublic CLI/JSON, saved state, upgrades, or package-manager compatibility.Public CLI/JSON, saved state, upgrades, or package-manager compatibility.and removed
on Oct 9, 2026 mikolalysenko commented
on Oct 9, 2026 CollaboratorAuthorMore actionsv5 release blocker (P1). The public --manifest-path option must consistently select one project. Mixing its manifest with another cwd project ledger is a scope/compatibility defect.
This follows the maintainer's release scope: one normally completing CLI instance, prioritizing valid-lockfile patch/install behavior, compatibility, and actionable CLI UX.
[agent] Filed by the scheduled architecture audit routine (CLI and core). Register: discussion #560 register.
Kind: bug. Source: new finding (register C43).
Problem
GlobalArgs::project_rootstates the rule: "Every command that reads more than one store must derive them from THIS root, so--manifest-pathcan never interleave two projects' state". CLI_CONTRACT'smanifest_not_foundrow also says "All sources always come from the SAME project".Only some commands follow it. Every command reads the manifest from
resolved_manifest_path(), but the vendored ledger (.socket/vendor/state.json) is loaded from two different roots:project_root()(follows--manifest-path)listandapplythroughProjectContext::new;vendor --check--cwdrollback;remove;repair;apply --check;vex(LoadedLedgers::load(&common.cwd, manifest_path));scanandgetthroughProjectContext::rooted(.., cwd)/ get, and the scan/get vendored paths (load_state(&common.cwd)inscan/vendor_flow.rs,scan/hosted.rs,get.rs)rollbackis the sharpest case, as rollback.rs L1218-L1238 shows:apply.lockin the manifest's.socket/throughsocket_dir_of(&manifest_path, &cwd).Proof by execution (debug build of
045d7ec, run twice; same results both times)Setup:
a/is--cwd, andb/.socket/manifest.jsonis{"patches":{}}. Every command runs with--cwd a --manifest-path ../b/.socket/manifest.json(rollback and repair also get--offline).a/.socket/vendor/state.jsonb/.socket/vendor/state.jsonlist --jsonb/.socket/vendor/state.json"vex --json --output fvendor_ledger_corruptno_patches(ledger never read)rollback --jsonpartial_failure, warningvendor_state_unreadablenaminga/…repair --jsonpartialFailure, eventvendor_state_unreadablenaminga/…So on the same input,
listreads project b's ledger, whilevex,rollbackandrepairread project a's.Symptoms / impact
--manifest-path,rollbackandremoverevert one project's agent-mode patches and the other project's vendored artifacts and ledger.vexattests a mix of both projects.rollback's lock doesn't cover the ledger it writes.--manifest-pathandSOCKET_MANIFEST_PATHare documented global options, so CI wrappers that pin the manifest location hit this.Proposed change
GlobalArgs::project_root().rollback,remove,repair,apply --checkandvexthroughProjectContext::new(orload_state(&common.project_root())).ProjectContext::rooted(common, cwd)calls inscanandget, and therootedconstructor if it has no remaining caller.scan/getvendored writes (scan/vendor_flow.rs,scan/hosted.rs,get.rs) save the ledger to the same root. Lockfile discovery stays where each command's contract puts it today. If a maintainer prefers to refuse a--manifest-pathoutside--cwd's project for multi-store commands, that is a contract change and should become a decision. The default fix just makes the code follow the rule it already documents.Size and scope
commands/{rollback,remove,repair,apply,vex,get,context}.rs,commands/scan/{mod,vendor_flow,hosted}.rs.ProjectContextwith a run-level context (C10).Acceptance criteria
load_state(/LoadedLedgers::load(call incrates/socket-patch-cli/srctakesproject_root()(or a value derived from it); a grep-style architecture test pins this.--cwdand a clean--manifest-path ../b/.socket/manifest.json,list,vex,rollback,removeandrepairall succeed; with the corruption moved tob, all of them report it.rollback --manifest-path ../b/.socket/manifest.jsonnever modifiesa/.socket/vendor/state.json.args.rsproject_root_*tests and thelistsame-project tests stay green.listrow to the--manifest-pathflag row, so it covers every command.Dependencies
--jsontop-levelerror(scan and get emit both a string and a {code, message} object) #704 (envelope) but doesn't conflict with them. Makes C10 (RunCtx) simpler.