Repository navigation
Description
Post-merge QA follow-up (#354)
Source: #354 — feat(lifecycle): update and uninstall directory targets via recorded ownership
Lens: evidence + test design.
The merge covers #342 with real end-to-end evidence: directoryLifecycleInstall drives the production dispatch to a genuinely installed state, and the three tests then check the plan writes nothing, apply actually changes the projected skill, an uninstalled target refuses instead of becoming a first install, and uninstall keeps a foreign file while removing the state file and every owned skill. The ownership wiring (NewUninstallRoot, the RuntimeDirectory arm in validUninstallRoot, the runtimeRank entry) is small and consistent with the existing tables, and the --target-dir/--runtime mutual exclusion in parseUpdateArgs holds.
Two defects and two evidence gaps. The main one: runDirectoryUpdate maps every candidate-build failure to invalid_catalog, and the candidate build also fails when the target path is not absolute, so the documented relative-path invocation of update reports a catalog error that has nothing to do with the catalog. Separately, this PR drops a still-true assertion (docs/README.md listed in the root README) from test_foundation_documents_state_clean_target_status — unrelated to directory lifecycle and unexplained in the PR body. On the evidence side, the update test never checks the manifest refresh the acceptance criteria name, and its ../../catalog fixture resolves only because Go runs the package test with internal/cli as the working directory.
Blocking findings
- A relative or malformed
--target-diris reported asinvalid_catalog(internal/cli/update.go:245):buildDirectoryUpdateCandidatefails for two unrelated reasons: the catalog cannot be built, orskillroot.ResolveIntoDirectoryrejects the target (itsvalidPathrequiresfilepath.IsAbs). Both collapse intowriteError(stderr, "invalid_catalog")with exit 1.runUninstallCommandgets this right —NewUninstallRootreturnsinvalid_targetfor the same class of path — so update now contradicts its sibling command and the operating guide, which documents./agent-skillsstyle paths as usable.- Failure scenario: An installed target at
./agent-skillswith a valid./catalog.cortex update --target-dir ./agent-skills --catalog ./catalogpassesos.Stat, thenResolveIntoDirectoryrefuses the non-absolute root, and the command printserror=invalid_catalogand exits 1. The operator hunts a catalog problem that does not exist, and no diagnostic mentions the path.
- Failure scenario: An installed target at
Acceptance criteria
- Fixed: A relative or malformed
--target-diris reported asinvalid_catalog(internal/cli/update.go:245). The scenario below no longer reproduces: An installed target at./agent-skillswith a valid./catalog.cortex update --target-dir ./agent-skills --catalog ./catalogpassesos.Stat, thenResolveIntoDirectoryrefuses the non-absolute root, and the command printserror=invalid_catalogand exits 1. The operator hunts a catalog problem that does not exist, and no diagnostic mentions the path.
Activity
barbatdev commentedon Oct 24, 2026
Fleet issue review (glm)
Recommendation: approve
Well-formed QA follow-up: it isolates one concrete defect (runDirectoryUpdate collapses the non-absolute-target failure of skillroot.ResolveIntoDirectory into invalid_catalog at internal/cli/update.go:245), quotes a reproducible failure scenario, and its single acceptance criterion is directly testable by rerunning the documented relative-path update invocation. The named code paths (internal/cli/update.go, docs/README.md) exist on the default branch, and the referenced sibling behavior (runUninstallCommand returning invalid_target) gives a clear consistency target. No open questions remain in the body or comments.
Juan merges; the fleet applies the
status:approvedlabel when a review recommendsapprove.barbatdev commentedon Nov 12, 2026
Fixed by #388 (merged 46f2870):
update --target-dirrefuses relative or malformed targets asinvalid_targetbefore reading the catalog (update.go:245-246). Covered byTestDirectoryTargetCommandsRefuseRelativeTargetswith a valid absolute catalog and--apply, which passes on main.