feat(runtime): add project-visible runtime roots#191
Conversation
Eval Smoke Results✅ Smoke evals clean — 0 regressions, 5 improvements
Posted by Specwright eval-smoke workflow. This comment is updated on each push. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ec3ecbabe1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Review: feat(runtime) — add project-visible runtime rootsOverviewThis PR introduces a two-mode runtime-root policy ( However, there is a functional divergence between the Critical —
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2460169aaa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (linkedWorktreeId && linkedWorktreeId !== PRIMARY_WORKTREE_ID) { | ||
| return linkedWorktreeId; |
There was a problem hiding this comment.
Keep linked
main-worktree ID stable in git-admin mode
When a linked worktree is literally named main-worktree (which Git permits), this new guard skips that directory name and forces a hashed worktreeId. In default git-admin mode, session discovery still keys that same worktree as main-worktree from .git/worktrees/<name>, so findSelectedWorkOwnerConflict compares two different IDs for the same checkout and reports a false “owned by another worktree” conflict. This produces incorrect adopt/takeover warnings in session-start for a single active worktree.
Useful? React with 👍 / 👎.
Summary
This unit adds the runtime-root foundation for the workflow legibility and operator-devex workstream. It introduces an explicit
git.runtime.mode/git.runtime.projectVisibleRootpolicy surface, teaches the shared resolver to support bothgit-adminandproject-visiblelayouts, and proves the new mode fails closed on unsafe roots without weakening verify strictness or tracked work-artifact separation.Because this repository uses clone-local work artifacts, the reviewer-usable audit summary is inlined below instead of depending on local-only
.git/specwright/...paths.Approval Lineage
/sw-plan. The current design artifact set still matches the recorded approval hash.02-project-visible-runtime-foundation: STALE (artifact-set-changed) from/sw-build.plan.mdchanged after approval when build appended the as-built notes.What Changed
.specwright/config.jsonnow defines the runtime-root policy surface throughgit.runtime.modeandgit.runtime.projectVisibleRootwhile leavinggit.workArtifactsas the separate publication-policy surface.core/protocols/context.mdnow documents both runtime modes, the five logical roots, and the project-visible guardrails that keep clone-local runtime state out of.gitand tracked artifacts.adapters/shared/specwright-state-paths.mjsnow resolvesgit-adminandproject-visibleruntime roots, keys linked worktrees byworktreeId, preserves tracked work-artifact overrides, and rejects unsafe project-visible roots..gitignorenow excludes/.specwright-local/so the project-visible runtime root stays untracked by default.evals/tests/test_runtime_mode_paths.pynow locks the runtime contract with real Git temp repos, linked-worktree coverage, tracked-root override coverage, and invalid-root rejection coverage.Why The Agent Implemented It This Way
adapters/shared/specwright-state-paths.mjsso every existing hook and helper keeps consuming one shared resolver.Acceptance Criteria
Implementation:
.specwright/config.json:40-46;core/protocols/context.md:12-14,21-54Evidence:
evals/tests/test_runtime_mode_paths.py:252-337(TestRuntimeModeConfigDefaults,TestRuntimeModeContextProtocol)Implementation:
adapters/shared/specwright-state-paths.mjs:246-370,409-465,652-689Evidence:
evals/tests/test_runtime_mode_paths.py:343-419(TestRuntimeModeResolverPaths::test_git_admin_primary_worktree_keeps_runtime_under_git_admin,::test_project_visible_primary_worktree_moves_runtime_out_of_git,::test_project_visible_linked_worktree_keys_state_by_worktree_id)Implementation:
adapters/shared/specwright-state-paths.mjs:373-406,458-464,749-780Evidence:
evals/tests/test_runtime_mode_paths.py:420-450(TestRuntimeModeResolverPaths::test_tracked_work_artifacts_override_stays_independent_in_project_visible_mode)Implementation:
adapters/shared/specwright-state-paths.mjs:1-4,180-209,259-333Evidence:
evals/tests/test_runtime_mode_paths.py:459-503(TestRuntimeModeSafetyProof::test_project_visible_root_inside_git_is_rejected,::test_project_visible_root_inside_project_artifacts_is_rejected,::test_project_visible_root_symlinked_into_git_is_rejected)Implementation:
.gitignore:1-15;adapters/shared/specwright-state-paths.mjs:338-370,652-689Evidence:
evals/tests/test_runtime_mode_paths.py:369-394,456-522(TestRuntimeModeResolverPaths::test_project_visible_primary_worktree_moves_runtime_out_of_git,TestRuntimeModeSafetyProof::test_gitignore_excludes_project_visible_runtime_root_by_default,::test_legacy_git_admin_install_still_loads_when_runtime_block_is_absent)Spec Conformance
gate-spec: PASS. AC-1 through AC-5 passed in the canonical compliance matrix for this unit.Gate Summary
bash build/build.shpassed, and the configuredcommands.testtier passed with the full eval suite plus the Claude Code build regressions.Remaining Attention
unit-specapproval lineage is stale becauseplan.mdchanged after/sw-buildrecorded approval.Evidence Links
.specwright/config.json,core/protocols/context.md,adapters/shared/specwright-state-paths.mjs,.gitignoreevals/tests/test_runtime_mode_paths.py