Skip to content

feat(mount): semantic-key aliases (by-title / by-id) (issue #106 PR 2)#117

Merged
khaliqgant merged 1 commit intomainfrom
feat/106-mount-semantic-aliases
May 9, 2026
Merged

feat(mount): semantic-key aliases (by-title / by-id) (issue #106 PR 2)#117
khaliqgant merged 1 commit intomainfrom
feat/106-mount-semantic-aliases

Conversation

@khaliqgant
Copy link
Copy Markdown
Member

Part 2 of 3 from #106.

Adds direct lookup paths so agents can resolve a record by name in
a single read instead of scanning _index.json:

  • notion/pages/by-title/<slugified-title>.json
  • linear/issues/by-id/<identifier>.json (e.g. AGE-8.json)
  • linear/users/by-name/<name>.json
  • github/repos/by-name/<owner>__<repo>.json

These are content-equivalent to the canonical UUID-named files.
They may be implemented as either:

  1. real symlinks (preferred where the FS layer permits), or
  2. duplicated JSON files generated alongside ingest (acceptable
    fallback — disk is cheap, and the alias dirs are bounded).

Builds on PR 1 (#106).

Repo scope

This PR is the relayfile part of wave wave2-aliases. The
companion PRs in the other repos are linked from issue #106.

Test plan

Generated by an overnight agent run. See
/tmp/106-wave2-aliases-status.md on the host for triage notes.

Refs #106

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 9, 2026

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 85ff2ded-b395-449f-ad3e-85f7d60fb62a

📥 Commits

Reviewing files that changed from the base of the PR and between c6f289c and 3be6ff5.

📒 Files selected for processing (5)
  • internal/mountfuse/dir.go
  • internal/mountfuse/fs.go
  • internal/mountfuse/fuse_test.go
  • internal/mountfuse/layout.go
  • internal/mountfuse/layout_test.go

📝 Walkthrough

Walkthrough

This PR refactors directory lookup semantics to support synthesized alias directories, updates virtual LAYOUT.md metadata to advertise read-only permissions, and adds comprehensive test coverage for alias resolution, readdir synthesis, collision handling, and cache invalidation. All changes remain localized to the mountfuse package.

Changes

Alias Directory and Virtual Layout Implementation

Layer / File(s) Summary
Layout Markdown & Metadata
internal/mountfuse/layout.go
Exports LayoutMarkdown constant documenting alias path segments (by-title, by-id, by-name). Adds internal constants for alias identifiers. Generates virtual LAYOUT.md metadata with read-only permissions (0o444) and inlined markdown content.
Directory Lookup & Unlink Refactoring
internal/mountfuse/dir.go
Replaces lookupCachedChild helper with direct GetChild check in DirNode.Lookup. Updates DirNode.Unlink to discard resolvedName and call RmChild(name) after invalidation. Removes lookupCachedChild method. Adds comment clarifying alias directories follow standard lookup path.
Filesystem Metadata Handling
internal/mountfuse/fs.go
Adds comments explaining alias directories under remote root and virtual-layout-only synthesis at root. Refactors treeEntryToMeta from if-statement to switch with explicit case-insensitive directory/symlink handling and lazy metadata population from ReadFile.
Test Stubs & Infrastructure
internal/mountfuse/fuse_test.go
Adds strings import. Removes fakeRemoteClient delete-call tracking fields and deleteCall struct. Updates DeleteFile stub to discard path and baseRevision. Provides helpers for mounting root, typed lookup (lookupDir/lookupFile), raw lookup, readdir enumeration, file reading with content type, and name set comparison.
Alias Directory Tests
internal/mountfuse/fuse_test.go
Adds six tests: TestFuseAliasByTitleResolves and TestFuseAliasByIDResolves validate alias resolution by identifier. TestFuseAliasReaddirIncludesByTitle confirms synthesized entries in parent and alias-path directory behavior. TestFuseAliasCollisionWithRealFile handles synthesized/real name collisions. TestFuseAliasMissingDirectoryReturnsENOENT validates error codes and negative TTL. TestFuseAliasReaddirRefreshesAfterInvalidation verifies cache refresh after mutation.
Layout File Tests
internal/mountfuse/layout_test.go
Extends TestLayoutMarkdownContainsRequiredAnchors with by-title/by-id/by-name and notion/linear/github path patterns. Updates TestRootDirectorySynthesizesLayoutMarkdown to assert virtual file is read-only (0o444). Removes prior DirNode legacy name-ID lookup/unlink tests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • AgentWorkforce/relayfile#116: Modifies virtual LAYOUT.md handling and listDirectory logic in mountfuse with overlapping changes to fs.go and layout.go.
  • AgentWorkforce/relayfile#115: Refactors directory lookup and unlink logic in mountfuse dir.go with related name-ID resolution test coverage updates.

Poem

🐰 By alias roads and layouts bright,
Synthesized entries spring to sight,
No cached helpers need apply—
Direct child checks swiftly fly,
Permissions read-only, collisions align,
The alias forest is now just fine! 📋✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main change: adding semantic-key aliases for direct lookup by human-friendly names (title/ID) instead of UUID scanning.
Description check ✅ Passed The description is directly related to the changeset, clearly explaining the purpose of aliases, the specific paths added, implementation options, test plan, and issue references.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/106-mount-semantic-aliases

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
internal/mountfuse/fuse_test.go (1)

70-76: ⚡ Quick win

Assert delete call arguments to avoid false-positive remove tests.

Right now DeleteFile ignores inputs, so TestFuseClientRemoveFile can still pass if FuseClient.RemoveFile forwards the wrong path or baseRevision. Capture and assert them.

Proposed test-hardening diff
 type fakeRemoteClient struct {
 	files map[string]mountsync.RemoteFile
 	trees map[string]mountsync.TreeResponse
@@
 	readFileErr  error
 	writeFileErr error
 	deleteErr    error
 	listTreeErr  error
+
+	lastDeletePath         string
+	lastDeleteBaseRevision string
 }
@@
 func (f *fakeRemoteClient) DeleteFile(_ context.Context, _, path, baseRevision string) error {
 	if f.deleteErr != nil {
 		return f.deleteErr
 	}
-	_ = path
-	_ = baseRevision
+	f.lastDeletePath = path
+	f.lastDeleteBaseRevision = baseRevision
 	return nil
 }
 func TestFuseClientRemoveFile(t *testing.T) {
 	remote := &fakeRemoteClient{}
 	fc := NewFuseClient(remote, "ws1", "/")
@@
 	errno := fc.RemoveFile(context.Background(), "/delete-me.txt", "r1")
 	if errno != 0 {
 		t.Errorf("RemoveFile errno = %d, want 0", errno)
 	}
+	if remote.lastDeletePath != "/delete-me.txt" {
+		t.Fatalf("DeleteFile path = %q, want %q", remote.lastDeletePath, "/delete-me.txt")
+	}
+	if remote.lastDeleteBaseRevision != "r1" {
+		t.Fatalf("DeleteFile baseRevision = %q, want %q", remote.lastDeleteBaseRevision, "r1")
+	}
 }

Also applies to: 178-185

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/mountfuse/fuse_test.go` around lines 70 - 76, The
fakeRemoteClient.DeleteFile implementation currently ignores its inputs causing
false-positive tests; update fakeRemoteClient to capture the incoming path and
baseRevision (e.g., store them in fields like lastDeletePath and
lastDeleteBaseRevision) and modify the tests (e.g., TestFuseClientRemoveFile and
the other test using DeleteFile) to set expected values on the fake and assert
those stored fields match the expected path and baseRevision when DeleteFile is
invoked; also ensure DeleteFile still returns f.deleteErr when set.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.trajectories/index.json:
- Around line 5-10: The index entry "traj_rbaf01z4kt7g" in
.trajectories/index.json must not contain a machine-local absolute "path";
change the writer to store a repository-relative path (e.g.,
".trajectories/active/traj_rbaf01z4kt7g.json") instead of "/Users/khaliqgant/…";
update the code that builds this index (the routine that writes the "path" field
for trajectory entries) to compute and persist path.relative(repoRoot, fullPath)
(or equivalent) and ensure any reader that loads "path" treats it as
repo-relative; also add a migration step or update existing entries to convert
absolute paths to relative ones when generating or updating the index.

In `@internal/mountfuse/layout_test.go`:
- Around line 51-63: Update the test's required list in layout_test.go (the
required slice) to include the by-name alias entries introduced by the PR: add
"linear/users/by-name/" and "linear/users/by-name/_index.json" as well as
"github/repos/by-name/" and "github/repos/by-name/_index.json" so the anchor
assertions validate the by-name aliases rather than only by-id semantics.

In `@internal/mountfuse/layout.go`:
- Around line 18-35: LayoutMarkdown currently documents alias paths that
conflict with the semantic-key contract: it still points GitHub repos at the
alias-by-id segment and omits the linear users-by-name path. Update the template
string referenced by LayoutMarkdown to use the correct alias segment constants
(aliasByTitleSegment vs aliasByIDSegment) for each integration: change the
github/repos alias path to the correct segment used for repos (replace the use
of aliasByIDSegment with the appropriate alias constant) and add a line for
linear/users using aliasByTitleSegment (i.e. "linear/users/" +
aliasByTitleSegment + "/<name>.json") so the docs match the actual alias routing
implemented elsewhere.

---

Nitpick comments:
In `@internal/mountfuse/fuse_test.go`:
- Around line 70-76: The fakeRemoteClient.DeleteFile implementation currently
ignores its inputs causing false-positive tests; update fakeRemoteClient to
capture the incoming path and baseRevision (e.g., store them in fields like
lastDeletePath and lastDeleteBaseRevision) and modify the tests (e.g.,
TestFuseClientRemoveFile and the other test using DeleteFile) to set expected
values on the fake and assert those stored fields match the expected path and
baseRevision when DeleteFile is invoked; also ensure DeleteFile still returns
f.deleteErr when set.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 69f722a0-a7ed-4076-befd-f361373297ea

📥 Commits

Reviewing files that changed from the base of the PR and between c8ef4d5 and abe9dae.

📒 Files selected for processing (11)
  • .trajectories/active/traj_rbaf01z4kt7g.json
  • .trajectories/completed/2026-05/traj_pfjtlq9sb0ps.json
  • .trajectories/completed/2026-05/traj_pfjtlq9sb0ps.md
  • .trajectories/completed/2026-05/traj_rbaf01z4kt7g.json
  • .trajectories/completed/2026-05/traj_rbaf01z4kt7g.md
  • .trajectories/index.json
  • internal/mountfuse/dir.go
  • internal/mountfuse/fs.go
  • internal/mountfuse/fuse_test.go
  • internal/mountfuse/layout.go
  • internal/mountfuse/layout_test.go

Comment thread .trajectories/index.json Outdated
Comment on lines 5 to 10
"traj_rbaf01z4kt7g": {
"title": "106-mount-layout-improvements-workflow",
"status": "active",
"startedAt": "2026-04-30T16:53:07.629Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/active/traj_mfyus7zfgxt2.json"
},
"traj_82lywlk9dcnc": {
"title": "Write SDK setup client workflow from spec",
"status": "completed",
"startedAt": "2026-04-30T16:43:24.651Z",
"completedAt": "2026-04-30T16:51:07.147Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_82lywlk9dcnc.json"
},
"traj_iuzm83ogm43k": {
"title": "Replace chokidar with @parcel/watcher in local-mount",
"status": "completed",
"startedAt": "2026-04-20T20:35:15.759Z",
"completedAt": "2026-04-20T20:58:15.412Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_iuzm83ogm43k.json"
},
"traj_nixaonkglri1": {
"title": "Migrate relayfile e2e and conformance scripts to RS256 local JWKS",
"status": "completed",
"startedAt": "2026-04-24T09:06:31.046Z",
"completedAt": "2026-04-24T09:10:42.425Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_nixaonkglri1.json"
},
"traj_i1f02867dkxn": {
"title": "Fix SDK setup workflow verify gate",
"status": "completed",
"startedAt": "2026-04-30T17:07:38.811Z",
"completedAt": "2026-04-30T17:10:18.837Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_i1f02867dkxn.json"
},
"traj_ubq95azheqpt": {
"title": "062-sdk-setup-client-workflow",
"status": "active",
"startedAt": "2026-04-30T17:12:22.684Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/active/traj_ubq95azheqpt.json"
},
"traj_dmoc4slub7ox": {
"title": "Fix SDK setup workflow evidence path",
"status": "completed",
"startedAt": "2026-04-30T17:33:11.390Z",
"completedAt": "2026-04-30T17:34:29.265Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_dmoc4slub7ox.json"
},
"traj_cojnals16pf9": {
"title": "062-sdk-setup-client-workflow",
"status": "active",
"startedAt": "2026-04-30T17:35:02.672Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/active/traj_cojnals16pf9.json"
},
"traj_qi3qmy5oveab": {
"title": "Resolve SDK setup review gate",
"status": "completed",
"startedAt": "2026-04-30T17:41:15.457Z",
"completedAt": "2026-04-30T17:43:16.297Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_qi3qmy5oveab.json"
},
"traj_em3hvzpg1xmx": {
"title": "062-sdk-setup-client-workflow",
"status": "completed",
"startedAt": "2026-04-30T17:43:56.110Z",
"completedAt": "2026-04-30T17:43:59.041Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_em3hvzpg1xmx.json"
},
"traj_cdist8i8vdmd": {
"title": "Address PR 65 feedback",
"status": "completed",
"startedAt": "2026-04-30T20:10:45.916Z",
"completedAt": "2026-04-30T20:11:29.126Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_cdist8i8vdmd.json"
},
"traj_wez7rl7pkfpn": {
"title": "Review PR 65 implementation against spec",
"status": "completed",
"startedAt": "2026-04-30T20:31:59.188Z",
"completedAt": "2026-04-30T20:31:59.361Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_wez7rl7pkfpn.json"
},
"traj_7x9nltybo08h": {
"title": "Update PR 65 usage instructions",
"status": "completed",
"startedAt": "2026-04-30T21:07:25.621Z",
"completedAt": "2026-04-30T21:08:20.135Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_7x9nltybo08h.json"
},
"traj_z2klijcrwqed": {
"title": "Design simple agent workspace connect flow",
"status": "completed",
"startedAt": "2026-05-01T14:58:15.412Z",
"completedAt": "2026-05-01T15:06:23.351Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_z2klijcrwqed.json"
},
"traj_a6rfc30zag40": {
"title": "Draft agent workspace golden path spec",
"status": "completed",
"startedAt": "2026-05-01T15:09:58.013Z",
"completedAt": "2026-05-01T15:12:08.390Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_a6rfc30zag40.json"
},
"traj_hyqnsfininh5": {
"title": "Write agent workspace implementation workflow",
"status": "completed",
"startedAt": "2026-05-01T15:22:05.684Z",
"completedAt": "2026-05-01T15:27:12.578Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_hyqnsfininh5.json"
},
"traj_ailh4waboewf": {
"title": "Design relayfile low-friction cloud login and integration mount flow",
"status": "completed",
"startedAt": "2026-05-01T23:39:39.687Z",
"completedAt": "2026-05-01T23:45:39.611Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_ailh4waboewf.json"
},
"traj_ozxb98dy7hk5": {
"title": "Research relayfile positioning vs MCP and CLI",
"status": "completed",
"startedAt": "2026-05-04T10:00:09.507Z",
"completedAt": "2026-05-04T10:01:10.778Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_ozxb98dy7hk5.json"
},
"traj_rnldje4mr6nw": {
"title": "Research relayfile positioning vs MCP and CLI",
"status": "completed",
"startedAt": "2026-05-04T10:01:57.596Z",
"completedAt": "2026-05-04T10:01:57.776Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_rnldje4mr6nw.json"
},
"traj_78fn1fyq1m4d": {
"title": "Explain relayfile relayauth governance model",
"status": "completed",
"startedAt": "2026-05-04T10:16:51.523Z",
"completedAt": "2026-05-04T10:17:37.753Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_78fn1fyq1m4d.json"
},
"traj_aomtlnb3g5sa": {
"title": "Identify relayfile relayauth changes for per-user governance",
"status": "completed",
"startedAt": "2026-05-04T10:22:29.278Z",
"completedAt": "2026-05-04T10:22:29.396Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_aomtlnb3g5sa.json"
},
"traj_5uxheavo6d3q": {
"title": "Write per-user relayfile governance spec",
"status": "completed",
"startedAt": "2026-05-04T10:25:24.905Z",
"completedAt": "2026-05-04T10:27:40.891Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_5uxheavo6d3q.json"
},
"traj_2nl6e3gqkvki": {
"title": "Document programmatic Notion connect interface",
"status": "completed",
"startedAt": "2026-05-04T10:38:33.363Z",
"completedAt": "2026-05-04T10:40:25.800Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_2nl6e3gqkvki.json"
},
"traj_v1un6n66y38i": {
"title": "Async createMount — issue #104",
"status": "completed",
"startedAt": "2026-05-08T17:27:24.218Z",
"completedAt": "2026-05-08T17:31:22.965Z",
"path": "/Users/will/Projects/relayfile/.claude/worktrees/issue-104-async-create-mount/.trajectories/completed/2026-05/traj_v1un6n66y38i.json"
"startedAt": "2026-05-08T22:58:04.332Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/active/traj_rbaf01z4kt7g.json"
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Trajectory index should not persist machine-local absolute paths.

This leaks local environment details and breaks portability in other clones/CI runners. Store a repository-relative path instead.

🛠️ Suggested fix
-      "path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/active/traj_rbaf01z4kt7g.json"
+      "path": ".trajectories/active/traj_rbaf01z4kt7g.json"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"traj_rbaf01z4kt7g": {
"title": "106-mount-layout-improvements-workflow",
"status": "active",
"startedAt": "2026-04-30T16:53:07.629Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/active/traj_mfyus7zfgxt2.json"
},
"traj_82lywlk9dcnc": {
"title": "Write SDK setup client workflow from spec",
"status": "completed",
"startedAt": "2026-04-30T16:43:24.651Z",
"completedAt": "2026-04-30T16:51:07.147Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_82lywlk9dcnc.json"
},
"traj_iuzm83ogm43k": {
"title": "Replace chokidar with @parcel/watcher in local-mount",
"status": "completed",
"startedAt": "2026-04-20T20:35:15.759Z",
"completedAt": "2026-04-20T20:58:15.412Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_iuzm83ogm43k.json"
},
"traj_nixaonkglri1": {
"title": "Migrate relayfile e2e and conformance scripts to RS256 local JWKS",
"status": "completed",
"startedAt": "2026-04-24T09:06:31.046Z",
"completedAt": "2026-04-24T09:10:42.425Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_nixaonkglri1.json"
},
"traj_i1f02867dkxn": {
"title": "Fix SDK setup workflow verify gate",
"status": "completed",
"startedAt": "2026-04-30T17:07:38.811Z",
"completedAt": "2026-04-30T17:10:18.837Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_i1f02867dkxn.json"
},
"traj_ubq95azheqpt": {
"title": "062-sdk-setup-client-workflow",
"status": "active",
"startedAt": "2026-04-30T17:12:22.684Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/active/traj_ubq95azheqpt.json"
},
"traj_dmoc4slub7ox": {
"title": "Fix SDK setup workflow evidence path",
"status": "completed",
"startedAt": "2026-04-30T17:33:11.390Z",
"completedAt": "2026-04-30T17:34:29.265Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_dmoc4slub7ox.json"
},
"traj_cojnals16pf9": {
"title": "062-sdk-setup-client-workflow",
"status": "active",
"startedAt": "2026-04-30T17:35:02.672Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/active/traj_cojnals16pf9.json"
},
"traj_qi3qmy5oveab": {
"title": "Resolve SDK setup review gate",
"status": "completed",
"startedAt": "2026-04-30T17:41:15.457Z",
"completedAt": "2026-04-30T17:43:16.297Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_qi3qmy5oveab.json"
},
"traj_em3hvzpg1xmx": {
"title": "062-sdk-setup-client-workflow",
"status": "completed",
"startedAt": "2026-04-30T17:43:56.110Z",
"completedAt": "2026-04-30T17:43:59.041Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_em3hvzpg1xmx.json"
},
"traj_cdist8i8vdmd": {
"title": "Address PR 65 feedback",
"status": "completed",
"startedAt": "2026-04-30T20:10:45.916Z",
"completedAt": "2026-04-30T20:11:29.126Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_cdist8i8vdmd.json"
},
"traj_wez7rl7pkfpn": {
"title": "Review PR 65 implementation against spec",
"status": "completed",
"startedAt": "2026-04-30T20:31:59.188Z",
"completedAt": "2026-04-30T20:31:59.361Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_wez7rl7pkfpn.json"
},
"traj_7x9nltybo08h": {
"title": "Update PR 65 usage instructions",
"status": "completed",
"startedAt": "2026-04-30T21:07:25.621Z",
"completedAt": "2026-04-30T21:08:20.135Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-04/traj_7x9nltybo08h.json"
},
"traj_z2klijcrwqed": {
"title": "Design simple agent workspace connect flow",
"status": "completed",
"startedAt": "2026-05-01T14:58:15.412Z",
"completedAt": "2026-05-01T15:06:23.351Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_z2klijcrwqed.json"
},
"traj_a6rfc30zag40": {
"title": "Draft agent workspace golden path spec",
"status": "completed",
"startedAt": "2026-05-01T15:09:58.013Z",
"completedAt": "2026-05-01T15:12:08.390Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_a6rfc30zag40.json"
},
"traj_hyqnsfininh5": {
"title": "Write agent workspace implementation workflow",
"status": "completed",
"startedAt": "2026-05-01T15:22:05.684Z",
"completedAt": "2026-05-01T15:27:12.578Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_hyqnsfininh5.json"
},
"traj_ailh4waboewf": {
"title": "Design relayfile low-friction cloud login and integration mount flow",
"status": "completed",
"startedAt": "2026-05-01T23:39:39.687Z",
"completedAt": "2026-05-01T23:45:39.611Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_ailh4waboewf.json"
},
"traj_ozxb98dy7hk5": {
"title": "Research relayfile positioning vs MCP and CLI",
"status": "completed",
"startedAt": "2026-05-04T10:00:09.507Z",
"completedAt": "2026-05-04T10:01:10.778Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_ozxb98dy7hk5.json"
},
"traj_rnldje4mr6nw": {
"title": "Research relayfile positioning vs MCP and CLI",
"status": "completed",
"startedAt": "2026-05-04T10:01:57.596Z",
"completedAt": "2026-05-04T10:01:57.776Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_rnldje4mr6nw.json"
},
"traj_78fn1fyq1m4d": {
"title": "Explain relayfile relayauth governance model",
"status": "completed",
"startedAt": "2026-05-04T10:16:51.523Z",
"completedAt": "2026-05-04T10:17:37.753Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_78fn1fyq1m4d.json"
},
"traj_aomtlnb3g5sa": {
"title": "Identify relayfile relayauth changes for per-user governance",
"status": "completed",
"startedAt": "2026-05-04T10:22:29.278Z",
"completedAt": "2026-05-04T10:22:29.396Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_aomtlnb3g5sa.json"
},
"traj_5uxheavo6d3q": {
"title": "Write per-user relayfile governance spec",
"status": "completed",
"startedAt": "2026-05-04T10:25:24.905Z",
"completedAt": "2026-05-04T10:27:40.891Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_5uxheavo6d3q.json"
},
"traj_2nl6e3gqkvki": {
"title": "Document programmatic Notion connect interface",
"status": "completed",
"startedAt": "2026-05-04T10:38:33.363Z",
"completedAt": "2026-05-04T10:40:25.800Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/completed/2026-05/traj_2nl6e3gqkvki.json"
},
"traj_v1un6n66y38i": {
"title": "Async createMount — issue #104",
"status": "completed",
"startedAt": "2026-05-08T17:27:24.218Z",
"completedAt": "2026-05-08T17:31:22.965Z",
"path": "/Users/will/Projects/relayfile/.claude/worktrees/issue-104-async-create-mount/.trajectories/completed/2026-05/traj_v1un6n66y38i.json"
"startedAt": "2026-05-08T22:58:04.332Z",
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relayfile/.trajectories/active/traj_rbaf01z4kt7g.json"
}
"traj_rbaf01z4kt7g": {
"title": "106-mount-layout-improvements-workflow",
"status": "active",
"startedAt": "2026-05-08T22:58:04.332Z",
"path": ".trajectories/active/traj_rbaf01z4kt7g.json"
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.trajectories/index.json around lines 5 - 10, The index entry
"traj_rbaf01z4kt7g" in .trajectories/index.json must not contain a machine-local
absolute "path"; change the writer to store a repository-relative path (e.g.,
".trajectories/active/traj_rbaf01z4kt7g.json") instead of "/Users/khaliqgant/…";
update the code that builds this index (the routine that writes the "path" field
for trajectory entries) to compute and persist path.relative(repoRoot, fullPath)
(or equivalent) and ensure any reader that loads "path" treats it as
repo-relative; also add a migration step or update existing entries to convert
absolute paths to relative ones when generating or updating the index.

Comment thread internal/mountfuse/layout_test.go
Comment thread internal/mountfuse/layout.go
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 3 additional findings.

Open in Devin Review

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
internal/mountsync/syncer_test.go (1)

2328-2333: ⚡ Quick win

Assert tracked state (syncer.state.Files) in addition to on-disk content/hash.

Current hash assertions only prove file bytes match expected content. To fully validate reconciliation behavior, add checks that tracked revision/hash were updated for these paths.

✅ Suggested assertion pattern
  if got, want := hashBytes(indexBytes), hashBytes([]byte(indexBody)); got != want {
  	t.Fatalf("_index.json hash = %s, want %s", got, want)
  }
+ trackedIndex, ok := syncer.state.Files["/notion/pages/_index.json"]
+ if !ok {
+ 	t.Fatalf("expected tracked state for /notion/pages/_index.json")
+ }
+ if trackedIndex.Revision != "rev_index" || trackedIndex.Hash != hashBytes([]byte(indexBody)) {
+ 	t.Fatalf("unexpected tracked state for index: %+v", trackedIndex)
+ }

  if got, want := hashBytes(layoutBytes), hashBytes([]byte(layoutBody)); got != want {
  	t.Fatalf(".layout.md hash = %s, want %s", got, want)
  }
+ trackedLayout, ok := syncer.state.Files["/notion/.layout.md"]
+ if !ok {
+ 	t.Fatalf("expected tracked state for /notion/.layout.md")
+ }
+ if trackedLayout.Revision != "rev_layout" || trackedLayout.Hash != hashBytes([]byte(layoutBody)) {
+ 	t.Fatalf("unexpected tracked state for layout: %+v", trackedLayout)
+ }

Also applies to: 2388-2390

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/mountsync/syncer_test.go` around lines 2328 - 2333, Add assertions
that the in-memory tracked state (syncer.state.Files) was updated to match the
on-disk content for the two files being tested: check that
syncer.state.Files["_index.json"].Hash equals hashBytes(indexBytes) (or
hashBytes([]byte(indexBody))) and that syncer.state.Files[".layout.md"].Hash
equals hashBytes(layoutBytes) (or hashBytes([]byte(layoutBody))); also assert
the Revision fields on those map entries reflect the expected revision (same
value used in other test expectations). Use the existing identifiers hashBytes,
indexBytes, layoutBytes, indexBody, layoutBody and the syncer.state.Files map to
locate and add these assertions adjacent to the existing hash checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@internal/mountsync/syncer_test.go`:
- Around line 2328-2333: Add assertions that the in-memory tracked state
(syncer.state.Files) was updated to match the on-disk content for the two files
being tested: check that syncer.state.Files["_index.json"].Hash equals
hashBytes(indexBytes) (or hashBytes([]byte(indexBody))) and that
syncer.state.Files[".layout.md"].Hash equals hashBytes(layoutBytes) (or
hashBytes([]byte(layoutBody))); also assert the Revision fields on those map
entries reflect the expected revision (same value used in other test
expectations). Use the existing identifiers hashBytes, indexBytes, layoutBytes,
indexBody, layoutBody and the syncer.state.Files map to locate and add these
assertions adjacent to the existing hash checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e1234138-ea90-40e8-b961-cb22af0ad87b

📥 Commits

Reviewing files that changed from the base of the PR and between 250eb25 and c6f289c.

📒 Files selected for processing (7)
  • internal/mountfuse/dir.go
  • internal/mountfuse/fs.go
  • internal/mountfuse/fuse_test.go
  • internal/mountfuse/layout.go
  • internal/mountfuse/layout_test.go
  • internal/mountsync/syncer.go
  • internal/mountsync/syncer_test.go
✅ Files skipped from review due to trivial changes (4)
  • internal/mountfuse/layout.go
  • internal/mountfuse/dir.go
  • internal/mountsync/syncer.go
  • internal/mountfuse/fs.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • internal/mountfuse/layout_test.go
  • internal/mountfuse/fuse_test.go

…106 PR 2)

Adds alias segment constants (by-title / by-id / by-name) plus
LayoutMarkdown sections that point integrations at their published
alias trees: linear/issues/by-id, notion/pages/by-title,
linear/users/by-name, github/repos/by-name. Threads alias-aware
lookups through DirNode.Lookup/Unlink via resolveDirectoryEntry,
and surfaces adapter symlink entries as readable files for forward
compat. Anchor test asserts every documented alias path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@khaliqgant khaliqgant force-pushed the feat/106-mount-semantic-aliases branch from c6f289c to 3be6ff5 Compare May 9, 2026 09:50
@khaliqgant khaliqgant merged commit 2fdc209 into main May 9, 2026
4 of 5 checks passed
@khaliqgant khaliqgant deleted the feat/106-mount-semantic-aliases branch May 9, 2026 09:51
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