Skip to content

feat: move workspace index to topo lock#487

Merged
graphite-app[bot] merged 1 commit into
mainfrom
trl-701-move-workspace-trail-index-from-trailslock-to-topolock
May 12, 2026
Merged

feat: move workspace index to topo lock#487
graphite-app[bot] merged 1 commit into
mainfrom
trl-701-move-workspace-trail-index-from-trailslock-to-topolock

Conversation

@galligan
Copy link
Copy Markdown
Contributor

@galligan galligan commented May 11, 2026

Context

The last Stack 1 branch moves workspace trail ownership metadata to the artifact that actually serializes resolved topology.

This PR covers TRL-701. It is built on the corrected TRL-700 workspace layout: trails.lock stays a compact manifest, while topo.lock carries optional workspace metadata under TopoGraph.workspace.

Changes

  • Moves workspace trail index metadata out of the lock manifest and into TopoGraph.workspace in topo.lock.
  • Adds strict schemas for workspace trail entries, workspace trail indexes, collision metadata, and workspace topo metadata.
  • Adds readWorkspaceTopoMetadata() and readWorkspaceTrailIndex() over topo.lock, while keeping readWorkspaceLock() as a deprecated compatibility alias.
  • Updates workspace index building to prefer topo.lock metadata, fall back to discovery when no workspace metadata exists, and distinguish missing topo.lock from a topo.lock without workspace metadata.
  • Preserves structured collision metadata from persisted workspace topo graphs without reloading every app.
  • Renames the workspace index source from lockfile to topo-lock in tests and docs.
  • Updates completions, Topographer README, ADR-0042, and workspace-topos tests for the new artifact ownership.
  • Adds a changeset for the workspace index relocation.

Verification

Local verification in this review-feedback pass:

  • bun scripts/adr.ts check
  • bun test packages/topographer/src/__tests__/io.test.ts packages/warden/src/__tests__/drift.test.ts apps/trails/src/__tests__/topo-dev.test.ts apps/trails/src/__tests__/run-watch.test.ts
  • bun run typecheck
  • bun run lint
  • bun run lint:ast-grep
  • bun run format:check
  • bun run test
  • bun run build
  • bun run check
  • git diff --check

Remote CI, Greptile, and Graphite mergeability rerun on every push; use the PR check rollup for current remote status.

Release / Risk

This is the final Stack 1 artifact-family alignment: trails.lock remains compact, and workspace topology belongs in topo.lock. Consumers still using the deprecated readWorkspaceLock() alias should move to readWorkspaceTrailIndex().

@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 11, 2026

TRL-701

Copy link
Copy Markdown
Contributor Author

galligan commented May 11, 2026


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • queue:merge - adds this PR to the back of the merge queue
  • queue:priority - for urgent changes, fast-track this PR to the front of the merge queue

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@galligan galligan force-pushed the trl-701-move-workspace-trail-index-from-trailslock-to-topolock branch from c08427f to ed3b737 Compare May 11, 2026 19:23
@galligan galligan marked this pull request as ready for review May 11, 2026 19:26
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 11, 2026

Greptile Summary

This PR completes the Stack 1 artifact-family alignment by moving the workspace trail index out of trails.lock and into topo.lock's optional workspace field. readWorkspaceTopoMetadata and readWorkspaceTrailIndex are added over the already-validated readTopoGraph path, readWorkspaceLock becomes a deprecated alias, and the WorkspaceTrailCollision type is promoted from a local interface in workspace-topos.ts to a Zod-backed schema in types.ts.

  • packages/topographer/src/types.ts: Adds workspaceTrailCollisionSchema, workspaceTopoMetadataSchema, and their inferred types; removes workspaceTrails from lockManifestSchema; wires workspace into the strict topoGraphSchema so all reads are Zod-validated.
  • packages/topographer/src/io.ts: Routes workspace reads through readTopoGraph (which runs topoGraphSchema.safeParse), ensuring the previously-flagged unvalidated read path is now fully guarded.
  • packages/topographer/src/workspace-topos.ts: Replaces buildFromLockfile with buildFromTopoLock that reads WorkspaceTopoMetadata (including persisted collisions) and uses existsSync to distinguish "missing topo.lock" from "topo.lock without workspace metadata" for the fallback warning.

Confidence Score: 5/5

Safe to merge — the workspace index read path is properly Zod-validated end-to-end, and the deprecated readWorkspaceLock alias preserves backward compatibility.

All workspace reads flow through readTopoGraph → parseTopoGraph → topoGraphSchema.safeParse, so a corrupt or hand-edited topo.lock throws a clear actionable error rather than silently propagating bad data. The only gap is a missing test for the topo.lock exists without a workspace field warning branch, which is diagnostic text and does not affect correctness.

packages/topographer/src/tests/workspace-topos.test.ts — needs a test for the untested fallback warning emitted when topo.lock exists but has no workspace field.

Important Files Changed

Filename Overview
packages/topographer/src/io.ts Adds readWorkspaceTopoMetadata and readWorkspaceTrailIndex over the already-validated readTopoGraph path; renames readWorkspaceLock to a deprecated alias. Validation through parseTopoGraph/topoGraphSchema.safeParse correctly covers the new workspace field.
packages/topographer/src/types.ts Adds workspaceTrailCollisionSchema, workspaceTopoMetadataSchema, and their inferred types; wires them into topoGraphSchema; removes workspaceTrails from lockManifestSchema. Schemas are strict and internally consistent.
packages/topographer/src/workspace-topos.ts Replaces buildFromLockfile with buildFromTopoLock reading WorkspaceTopoMetadata; adds existsSync to distinguish missing topo.lock from topo.lock without workspace for the fallback warning. The topo.lock present but no workspace branch is not covered by any test.
packages/topographer/src/tests/workspace-topos.test.ts Migrates all lockfile-path tests to write topo.lock; adds a new collision-ownership test. Missing coverage for the topo.lock exists but has no workspace field fallback branch.
packages/topographer/src/index.ts Exports new functions and types; moves WorkspaceTrailCollision from workspace-topos.js re-export to types.js re-export; readWorkspaceLock kept as a deprecated export.
apps/trails/src/tests/completions-example.test.ts Updates broken-workspace fixture from trails.lock to a full topo.lock structure with workspace.trails; structure matches the schema correctly.
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
packages/topographer/src/__tests__/workspace-topos.test.ts:499-519
**Missing test for "topo.lock exists but has no workspace field" branch**

`buildWorkspaceTrailIndex` now uses `existsSync` to emit two distinct warnings, but only the `"No workspace topo.lock found"` path is exercised here. The second branch — where `topo.lock` is present and valid but its `workspace` field is `undefined` — produces `"Workspace topo.lock in \"...\" does not include workspace metadata; falling back to discovery."` and is never tested. Adding a test that writes a minimal `topo.lock` (no `workspace` key) and asserts the new warning string would close this gap.

Reviews (7): Last reviewed commit: "feat: move workspace index to topo lock ..." | Re-trigger Greptile

Comment thread packages/topographer/src/workspace-topos.ts Outdated
Comment thread packages/topographer/src/workspace-topos.ts
@galligan galligan force-pushed the trl-701-move-workspace-trail-index-from-trailslock-to-topolock branch from ed3b737 to 4e8c5c6 Compare May 11, 2026 19:51
@galligan galligan force-pushed the trl-700-migrate-trails-workspace-layout-for-state-and-local-config branch from 16bb0c1 to 1ef092a Compare May 11, 2026 19:51
@galligan galligan force-pushed the trl-701-move-workspace-trail-index-from-trailslock-to-topolock branch 2 times, most recently from 3f53e58 to 2dcc22f Compare May 11, 2026 23:02
@galligan galligan force-pushed the trl-700-migrate-trails-workspace-layout-for-state-and-local-config branch from b03d19f to d7e5d3f Compare May 12, 2026 03:41
@galligan galligan force-pushed the trl-701-move-workspace-trail-index-from-trailslock-to-topolock branch 2 times, most recently from 2083937 to 49e3fd2 Compare May 12, 2026 03:49
@galligan galligan force-pushed the trl-700-migrate-trails-workspace-layout-for-state-and-local-config branch from d7e5d3f to 0b8ee04 Compare May 12, 2026 03:49
@graphite-app
Copy link
Copy Markdown

graphite-app Bot commented May 12, 2026

Merge activity

## Context

The last Stack 1 branch moves workspace trail ownership metadata to the artifact that actually serializes resolved topology.

This PR covers TRL-701. It is built on the corrected TRL-700 workspace layout: `trails.lock` stays a compact manifest, while `topo.lock` carries optional workspace metadata under `TopoGraph.workspace`.

## Changes

- Moves workspace trail index metadata out of the lock manifest and into `TopoGraph.workspace` in `topo.lock`.
- Adds strict schemas for workspace trail entries, workspace trail indexes, collision metadata, and workspace topo metadata.
- Adds `readWorkspaceTopoMetadata()` and `readWorkspaceTrailIndex()` over `topo.lock`, while keeping `readWorkspaceLock()` as a deprecated compatibility alias.
- Updates workspace index building to prefer `topo.lock` metadata, fall back to discovery when no workspace metadata exists, and distinguish missing `topo.lock` from a `topo.lock` without workspace metadata.
- Preserves structured collision metadata from persisted workspace topo graphs without reloading every app.
- Renames the workspace index source from `lockfile` to `topo-lock` in tests and docs.
- Updates completions, Topographer README, ADR-0042, and workspace-topos tests for the new artifact ownership.
- Adds a changeset for the workspace index relocation.

## Verification

Local verification in this review-feedback pass:

- `bun scripts/adr.ts check`
- `bun test packages/topographer/src/__tests__/io.test.ts packages/warden/src/__tests__/drift.test.ts apps/trails/src/__tests__/topo-dev.test.ts apps/trails/src/__tests__/run-watch.test.ts`
- `bun run typecheck`
- `bun run lint`
- `bun run lint:ast-grep`
- `bun run format:check`
- `bun run test`
- `bun run build`
- `bun run check`
- `git diff --check`

Remote CI, Greptile, and Graphite mergeability rerun on every push; use the PR check rollup for current remote status.

## Release / Risk

This is the final Stack 1 artifact-family alignment: `trails.lock` remains compact, and workspace topology belongs in `topo.lock`. Consumers still using the deprecated `readWorkspaceLock()` alias should move to `readWorkspaceTrailIndex()`.
@graphite-app graphite-app Bot force-pushed the trl-700-migrate-trails-workspace-layout-for-state-and-local-config branch from 0b8ee04 to 10eae9a Compare May 12, 2026 14:36
@graphite-app graphite-app Bot force-pushed the trl-701-move-workspace-trail-index-from-trailslock-to-topolock branch from 49e3fd2 to bbb1ea4 Compare May 12, 2026 14:37
Base automatically changed from trl-700-migrate-trails-workspace-layout-for-state-and-local-config to main May 12, 2026 14:43
@graphite-app graphite-app Bot merged commit bbb1ea4 into main May 12, 2026
10 checks passed
@graphite-app graphite-app Bot deleted the trl-701-move-workspace-trail-index-from-trailslock-to-topolock branch May 12, 2026 14:44
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.

1 participant