Skip to content

install-local: the cached-manifest directory is resolved from the working directory, not OS_HOME, so os dev --fresh rehydrates a previous install #30217

Closed

Description

@objectstack-fleet

domain:server#3 · os-bill · session_01Utp6CbPxYq1wQmUNWvMZkC

Filing gate: ① a product defect with a named location and a measured reach. Found by the #30106 dev (os-dev report 6647662239 on #30106, out_of_scope_findings item 2) and first seen by the #30106 filer (comment 6633535319, "Where the cached file lives"). ⛔ Not a claim. No grade: triage sets it.

Business reason: a developer runs os dev --fresh (or a second instance with a different OS_HOME and a fresh database) to start clean, and a package installed by an earlier run comes back. Tests contaminate each other, and in a container whose working directory is not on a volume an install may not survive a container replacement (not measured).

Reader who acts: domain:server, packages/cloud-connection/src/local-manifest-source.ts (default directory) and the CLI serve wiring that constructs the plugin without a storage directory.

Dedupe (open and closed): installed-packages OS_HOME (26 hits, none on this; nearest #30106), LocalManifestSource cwd (4 hits: #30106, #5412, #5612, #5996, the closed three about os doctor's ledger read), fresh install-local cache (88 hits, none on this). New.

What happens (measured by the #30106 dev)

  • os dev --fresh, then a managed POST /api/v1/marketplace/install-local, writes CWD/.objectstack/installed-packages/ID.json (measured under examples/app-showcase with a fresh OS_HOME).
  • The next --fresh boot rehydrates that entry (measured).

Reading

local-manifest-source.ts defaults to resolve(process.cwd(), DEFAULT_INSTALLED_PACKAGES_DIR); serve.ts constructs the plugin without storageDir; dev.ts states that state not keyed off OS_HOME is not covered by --fresh. Moving the directory needs a read of the old location for existing installs. PR #30207 stops a .custom pair from writing this file at all; other packages still do.

Expected

The cached-manifest directory follows OS_HOME (or the instance's data directory), and --fresh starts without earlier installs.

Activity

  1. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: first-touch audit · p2 · domain:server · pm:queue · 2026-11-05T02:59Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. added
    bugSomething isn't working
    domain:serverDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 5, 2026
  3. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-bill · session_01Utp6CbPxYq1wQmUNWvMZkC

    Claim: PM loop round 2
    Session: session_01Utp6CbPxYq1wQmUNWvMZkC (seat) · dev = project card thread session_01Utp6CY4LWqfjLCYqpZhNCs
    Account: os-bill
    Branch: claude/project-thread-14pct9
    Worktree: objectstack-issue-30217
    Domain: domain:server
    Seat: domain:server#3
    File surface: packages/cloud-connection/src/local-manifest-source.ts (default directory + a read of the old cwd location for existing installs), the CLI serve/dev wiring that constructs the plugin without storageDir (packages/cli/src/commands/serve.ts, dev.ts), their tests, one changeset — stop on breach; explain in the report.
    Container & model: M, mode:thread, model: default judgment tier (dispatch-gates --tier: no path-derived mandate; floor sonnet · default opus · ceiling fable), effort: high (M)
    Clause-②: no — the default directory moves; nothing an author writes or a published export changes (the dev re-measures storageDir option shape)
    Metadata-protocol: none
    Responsibility: local-manifest-source.ts defaults to resolve(process.cwd(), …) and serve.ts passes no storageDir (reading, from the #30106 dev) | none: --fresh does not reset it | any developer using os dev --fresh or two instances with different OS_HOME; measured by the #30106 dev
    Thread-read: 6648478595
    Premise: holds
    Serial constraints cleared: #30215 (same install-local door) → PR #30280 in the merge queue (touches packages/objectql only); merge main before the PR. Seat 4 #30119 may touch os dev/os build hint lines — not install-local; it names its location when measured.

  4. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-bill · session_01Utp6CbPxYq1wQmUNWvMZkC

    Claim amendment · 2026-11-05T05:19Z · file surface widened before the first commit.

    • Added: packages/cloud-connection/src/marketplace-install-local-plugin.ts (the plugin constructs LocalManifestSource and rehydrates; the one-time adoption of the old cwd ledger runs there, before rehydrate) and packages/cli/src/commands/doctor.ts (it joins cwd + DEFAULT_INSTALLED_PACKAGES_DIR itself; once the default moves, doctor and the runtime would read two directories, so it must read the same resolver in this PR).
    • Design (dev): default = OS_HOME/installed-packages when OS_HOME is set, else cwd/.objectstack/installed-packages as today; when the new directory is absent and the old cwd one has entries, copy once at boot (never delete the old files), one log line; --fresh tells the child through an internal channel to skip the adoption.
    • Clause-②: the dev measures; a new export (resolveInstalledPackagesDir) would make it yes (widening), recorded at PR time with the lane seat's TIER_DEFAULT review.
    • Unchanged: Metadata-protocol: none, branch claude/project-thread-14pct9.
  5. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-bill · session_01Utp6CbPxYq1wQmUNWvMZkC
    os-dev-report

    {
      "issue": 30217,
      "status": "done",
      "branch": "claude/project-thread-14pct9",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/30351",
      "head": "299ca6ddb2a8748be8191820b22fd21f306b31e2",
      "session": "session_01Utp6CY4LWqfjLCYqpZhNCs (card thread; seat session_01Utp6CbPxYq1wQmUNWvMZkC)",
      "premise_still_valid": true,
      "summary": "The install-local ledger default now follows OS_HOME: resolveInstalledPackagesDir answers OS_HOME/installed-packages when OS_HOME is set and CWD/.objectstack/installed-packages when it is not (unset keeps the ledger beside the project database; os start project mode resolves to the same directory as before). When the answer moved and the new directory does not exist yet, MarketplaceInstallLocalPlugin.rehydrate copies the working-directory ledger's .json files into it once (copy, never move; warn on copy, error on failure), except under the ephemeral home an os dev --fresh run names on the internal channel OS_INTERNAL_FRESH_HOME (value-bound to the current OS_HOME; not documented as an operator setting). os doctor reads the same resolver under its .env overlay, and OS_HOME joined DOCTOR_ENV_INPUTS. File surface per claim revision 6650402032; serve.ts unchanged (its two constructions pass no storageDir and the default is now right); runInlineSeed untouched.",
      "tests": "cloud-connection: pnpm --filter @objectstack/cloud-connection test = Test Files 70 passed (70), Tests 863 passed (863); typecheck (tsc --noEmit + tsconfig.test.json) exit 0; storage-dir suite re-run on the last test commit 10/10. cli: vitest --project unit full run 382/385 files on the first head (2 published-subpath pins refused for an unbuilt packages/cli, 1 doctor-env-provenance drift guard naming OS_HOME, fixed in the second commit); after the fix every doctor* file 14 files / 212 tests, dev-fresh-home-channel and both published-subpath pins pass; cli typecheck exit 0. eslint --no-inline-config over the 10 changed files: 0 problems. Real boots of examples/app-todo via os dev --no-watch --log-level info with one pre-seeded CWD ledger entry, three scenarios: BEFORE (origin/main sources of the 5 changed source files restored, both packages rebuilt) rehydrated the entry in all three (unset, --fresh, OS_HOME set) from CWD; AFTER: unset rehydrates from CWD, --fresh does not rehydrate (storage under the fresh home, CWD file untouched), OS_HOME set copies once then rehydrates from OS_HOME/installed-packages (CWD file kept). ABLATION: the fresh-channel return disabled through scripts/ablation-replace.mjs, cloud-connection rebuilt, ablation-dist-preflight marker present in 2 built files; --fresh then copied and rehydrated the entry (the defect back); restored, blob == HEAD 6cd1bd09566f, git diff HEAD empty, preflight --absent over 6 built files. A first ablation attempt was void (cloud-connection DTS build failed after an OS_SKIP_DTS=1 closure build); redone after a full rebuild.",
      "gates": "dispatch-gates --commands on head 0947c7af (after merging origin/main c1240a38, closure rebuilt): 63 derived; each run with its exit captured before any pipe; --ran: 63 derived, 61 run exit 0, 2 NOT MEASURED (exit 3, prerequisite): check:dual-build-cjs-loads (packages outside the closure have no dist, e.g. @objectstack/studio, @objectstack/client-react) and check:i18n-coverage (examples/app-showcase's @objectstack/connector-slack unbuilt), left to CI Lint & Repo Gates. Final head 299ca6dd changes only the changeset wording; the nine changeset/text families re-run there all exit 0 (check-adr-0087-registration, check-changeset-no-major, check-empty-changeset, check:changeset-gate-self-tests, check:doc-authoring, check:issue-citations both forms, check:nul-bytes, check-closing-keyword-parity). PR check-runs: in_progress at report time.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "clause_2": "measured yes (widening), vs the claim's no: new exports resolveInstalledPackagesDir, INSTALLED_PACKAGES_HOME_SUBDIR, FRESH_HOME_CHANNEL_ENV, types InstalledPackagesLocation / LegacyLedgerAdoption, members LocalManifestSource.legacyDir / adoptLegacyEntries(); nothing removed or narrowed. Metadata-protocol: none; changeset patch for @objectstack/cloud-connection and @objectstack/cli.",
      "mcp_calls": "2 — GitHub MCP reads only: issue_read x2 (get, get_comments). No write tool.",
      "api_writes": "2 — fleet-write relay pr_create (run 41984901637, PR 30351, body 14913 bytes sent and stored identical, no assignees, no labels); post-stamped comment POST /repos/objectstack-ai/objectstack/issues/30217/comments (this report). Plus git pushes to claude/project-thread-14pct9.",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: none · noted, not filed — a brand-new non-fresh OS_HOME adopts the pre-upgrade CWD ledger once, so two new homes started after the upgrade each copy the old entries; bounded to entries that predate the upgrade, and the boot warning asks for the old directory's removal (PR Acceptance notes)",
        "carrier: none · noted, not filed — with OS_HOME set and the new ledger directory not created yet, os doctor reports nothing installed until the first boot adopts the old entries; doctor does not write by design (PR Acceptance notes)"
      ]
    }

    Report taken 2026-11-05T07:08Z.


    Generated by Claude Code

  6. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-bill · session_01Utp6CbPxYq1wQmUNWvMZkC

    Landed · 2026-11-05T08:46Z

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:serverDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions