feat(cwd-anchored): drop CTX_DIR + ctx activate/deactivate; jumbo#90
Merged
Conversation
Implements specs/cwd-anchored-context.md end-to-end across two
sessions. `ctx` is now anchored to its working directory: every
resolver reads $PWD/.context/, and there is no env-var or
walk-up. Mental model matches zensical (zensical.toml),
terraform (.tf), and Claude Code (CLAUDE_PROJECT_DIR): the tool
anchors to a config location, not a parallel declaration
channel.
Net: 283 files changed, +6004 / -11546 (~5500 net deletion).
== Steps 1+2 (prior session, included here): ==
* rc.ContextDir collapses to filepath.Join(cwd, dir.Context)
after a single os.Stat; basename guard, env channel,
ScanCandidates, ErrDirNotDeclared/ErrRelativeNotAllowed/
ErrNonCanonicalBasename all removed.
* gitmeta.RequireGitTree collapses to os.Stat($PWD/.git);
upward walk gone.
* internal/cli/initialize/core/envmatch/ deleted (the env-vs-CWD
mismatch guard becomes vestigial).
* ctx init drops the env-vs-CWD branch; always targets
$PWD/.context.
== Step 3 - Hook cd migration: ==
* internal/assets/claude/hooks/hooks.json migrated from
`CTX_DIR="${CLAUDE_PROJECT_DIR:?...}/.context" ctx system <verb>`
to `cd "${CLAUDE_PROJECT_DIR:?...}" && ctx system <verb>`
across all 22 hook commands.
* check-anchor-drift hook entry removed (the drift it detected
cannot occur under cwd-anchored).
* Trace hooks (post-commit.sh, prepare-commit-msg.sh) and
copilot-cli scripts already cwd-correct; no migration needed.
== Step 4 - activate/deactivate/anchor-drift deletion: ==
Packages deleted:
* internal/cli/activate/ (whole subtree)
* internal/cli/deactivate/ (whole subtree)
* internal/write/activate/
* internal/err/activate/
* internal/cli/system/cmd/checkanchordrift/
* internal/cli/system/core/anchor/
* internal/config/shell/
Files deleted:
* internal/config/embed/text/err_activate.go
* internal/config/embed/text/check_anchor.go
* internal/config/embed/flag/activate.go
* internal/rc/candidates.go
Constants removed:
* env.CtxDir, env.CtxDirInherited, env.Shell
* hook.CheckAnchorDrift
* flag.Shell
* cmd.UseActivate / UseDeactivate / DescKeyActivate /
DescKeyDeactivate
* cmd.UseSystemCheckAnchorDrift / DescKeySystemCheckAnchorDrift
* text.DescKeyErrActivateNoLocalContext,
text.DescKeyCheckAnchorDrift*,
text.DescKeyWriteInitActivateHint
Registrations trimmed:
* bootstrap/group.go: activate/deactivate imports + getting-started
entries removed.
* cli/system/system.go: checkanchordrift import + Cmd() entry
removed.
YAML pruned:
* commands.yaml: activate, deactivate, system.checkanchordrift
* examples.yaml: activate, deactivate, system.checkanchordrift
* flags.yaml: activate.shell
* errors.yaml: err.activate.no-local-context
* hooks.yaml: check-anchor-drift.* (4 keys)
* write.yaml: write.init-activate-hint + reflow of
write.init-anatomy-preamble
== Step 5 - Docs sweep: ==
Recipes deleted (no longer applicable under cwd-anchored):
* docs/recipes/activating-context.md
* docs/recipes/external-context.md
Recipes updated (warning-block removal + eval-line removal,
some prose rewrites): 22 recipes across hub, session, knowledge,
permission, journal, scratchpad families. Bulk pattern was the
`!!! warning "Activate the Project First"` boilerplate plus
inline `eval "$(ctx activate)"` snippets.
Home docs updated: getting-started.md (steps renumbered),
first-session.md, joining-a-project.md, is-ctx-right.md,
configuration.md (External `.context/` example removed,
CTX_DIR env-var table row removed), opencode.md, vscode.md.
CLI docs updated: cli/index.md (activate/deactivate command
rows removed, env-var table row removed, declaration-model
preamble rewritten), cli/init-status.md (activate/deactivate
sections deleted), cli/bootstrap.md, cli/mcp.md.
Operations docs updated: integrations.md, autonomous-loop.md,
migration.md, upgrading.md, and 5 runbooks
(architecture-exploration.md, breaking-migration.md,
hub-deployment.md, new-contributor.md, release-checklist.md).
AI-facing templates updated:
* assets/claude/CLAUDE.md, assets/integrations/copilot-cli/INSTRUCTIONS.md,
CLAUDE.md: ctx.ist/recipes/activating-context/ URL repointed
to ctx.ist/home/getting-started/.
* assets/integrations/opencode/plugin/index.ts: shell.env hook
now sets output.cwd instead of injecting CTX_DIR; ctx.$ uses
.cwd(ctx.directory).
* 4 journal-enrich SKILL.md files: local var renamed
CTX_DIR -> CTX_PATH (cosmetic; the var was already local-only).
Spec status updates:
* specs/activate-strict-cwd.md: marked superseded by this spec.
* specs/single-source-context-anchor.md: marked superseded
(large sections; basename-guard rationale and no-walk-up
principle survive in stronger form).
== Tests: ==
Cleaned dead t.Setenv("CTX_DIR", ...) calls from:
init_test.go (16 calls), pad_test.go (3), remind_test.go,
checkreminder/run_test.go, notify_test.go, cli_test.go,
change/core/cmd_test.go (replaced with t.Chdir + mkdir
.context), drift/check_ext_test.go (mkdir .context),
mcp/server/server_test.go.
mcp/cmd/root/cmd_test.go rewritten:
TestMcpServe_FailsClosedOnUnsetCTXDIR ->
TestMcpServe_FailsClosedWhenNoDotContext: now uses
t.Chdir(t.TempDir()) and asserts the fail-closed behaviour
under cwd-anchored.
User-facing warning updated: config/warn/warn.go's
RCNoContextDir message changed from
"rc.RC: no CTX_DIR declared" to "rc.RC: no .context/ at $PWD".
== Also in this jumbo (prior + this session): ==
* AI backend spec scaffolding (block A contract + block B+C
sketched-not-contracted):
- .context/briefs/20260522T001011Z-ctx-ai-backend.md
- specs/ctx-ai-backend.md (with paste-ready task breakdown
appended)
- specs/ctx-ai-extraction-and-recall.md
* KB editorial pipeline scaffolding (Phase KB landed in
prior session):
- .context/kb/ (topic pages, index, source-coverage,
evidence-index)
- .context/ingest/ (KB-RULES.md, OPERATOR.md, PROMPT.md,
SESSION_LOG.md, schemas)
- .context/archive/closeouts/ (folded closeouts)
- first kb topic: .context/kb/topics/vllm/index.md
(contrastive study of vLLM's example landing page vs ctx's
recipe surface)
* Substrate-vs-artifact placement convention codified:
CONVENTIONS.md entry under File Organization plus a
DECISIONS.md entry capturing the three coupling tests
(consumed via ctx-mediated paths; tightly coupled to ctx
pipeline machinery; authored under ctx skill discipline)
and the three rejected alternatives.
* Handover artifact migration (prior sessions):
- .context/HANDOVER-2026-04-22.md removed (legacy flat shape)
- .context/handovers/ now uses timestamped <TS>-<slug>.md
(20260521T045353Z, 20260521T211326Z)
* CI/lint helpers:
- hack/lint-shellcheck.sh, hack/lint-powershell.sh
- .github/workflows/ci.yml gains shellcheck + powershell jobs
* Typography guide:
- .context/typography.md (contributor/agent surface for Title
Case, monotype ctx, banner shape, recipe Problem->TL;DR arc)
* Many small assets edits (test surface fallout, skill polish,
YAML key renames captured in prior commits, leftover here).
* docs/ site/ regenerated to match prose edits.
== Verification: ==
* golangci-lint run: 0 issues.
* go test ./...: all packages green, no failures.
== Provenance: ==
Two-session work on feat/cwd-anchored-context; the user's
jumbo strategy explicitly accumulates across sessions until a
single comprehensive commit lands. Not pushed.
Spec: specs/cwd-anchored-context.md
Spec: specs/ctx-ai-backend.md
Spec: specs/ctx-ai-extraction-and-recall.md
Spec: specs/activate-strict-cwd.md (superseded)
Spec: specs/single-source-context-anchor.md (superseded)
Signed-off-by: Jose Alekhinne <jose@ctx.ist>
Deploying ctx with
|
| Latest commit: |
a1f23fc
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://8a113814.ctx-bhl.pages.dev |
| Branch Preview URL: | https://feat-cwd-anchored-context.ctx-bhl.pages.dev |
Earlier cwd-anchored refactor mutated `output.cwd = input.cwd` in the shell.env hook, but the OpenCode SDK type for that hook's output exposes only `env`, not `cwd` — `npx tsc --noEmit` failed with TS2339. Removed the shell.env handler entirely: - Under cwd-anchored there are no env vars to inject (ctx no longer reads CTX_DIR or any sibling). - The SDK does not expose a way to force the agent's shell cwd from the plugin, so the hook cannot serve its original purpose (anchoring the agent's shell at the project root). - Plugin-internal subprocess calls remain anchored via `ctx.$.cwd(ctx.directory)`; only the agent-side shell tool is affected. User-visible consequence (documented in the leading comment): users must launch OpenCode from the project root for agent-issued `ctx` commands to resolve. The recipe (docs/home/opencode.md) already reflects this in its setup section. Verified locally with `cd tools/typecheck/opencode && npx tsc --noEmit` (clean). golangci-lint and go test ./... unchanged (green). Spec: specs/cwd-anchored-context.md Signed-off-by: Jose Alekhinne <jose@ctx.ist>
Signed-off-by: Jose Alekhinne <jose@ctx.ist>
Signed-off-by: Jose Alekhinne <jose@ctx.ist>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements specs/cwd-anchored-context.md end-to-end across two sessions.
ctxis now anchored to its working directory: every resolver reads $PWD/.context/, and there is no env-var or walk-up. Mental model matches zensical (zensical.toml), terraform (.tf), and Claude Code (CLAUDE_PROJECT_DIR): the tool anchors to a config location, not a parallel declaration channel.Net: 283 files changed, +6004 / -11546 (~5500 net deletion).
== Steps 1+2 (prior session, included here): ==
== Step 3 - Hook cd migration: ==
CTX_DIR="${CLAUDE_PROJECT_DIR:?...}/.context" ctx system <verb>tocd "${CLAUDE_PROJECT_DIR:?...}" && ctx system <verb>across all 22 hook commands.== Step 4 - activate/deactivate/anchor-drift deletion: ==
Packages deleted:
Files deleted:
Constants removed:
Registrations trimmed:
YAML pruned:
== Step 5 - Docs sweep: ==
Recipes deleted (no longer applicable under cwd-anchored):
Recipes updated (warning-block removal + eval-line removal, some prose rewrites): 22 recipes across hub, session, knowledge, permission, journal, scratchpad families. Bulk pattern was the
!!! warning "Activate the Project First"boilerplate plus inlineeval "$(ctx activate)"snippets.Home docs updated: getting-started.md (steps renumbered), first-session.md, joining-a-project.md, is-ctx-right.md, configuration.md (External
.context/example removed, CTX_DIR env-var table row removed), opencode.md, vscode.md.CLI docs updated: cli/index.md (activate/deactivate command rows removed, env-var table row removed, declaration-model preamble rewritten), cli/init-status.md (activate/deactivate sections deleted), cli/bootstrap.md, cli/mcp.md.
Operations docs updated: integrations.md, autonomous-loop.md, migration.md, upgrading.md, and 5 runbooks
(architecture-exploration.md, breaking-migration.md, hub-deployment.md, new-contributor.md, release-checklist.md).
AI-facing templates updated:
Spec status updates:
== Tests: ==
Cleaned dead t.Setenv("CTX_DIR", ...) calls from:
init_test.go (16 calls), pad_test.go (3), remind_test.go, checkreminder/run_test.go, notify_test.go, cli_test.go, change/core/cmd_test.go (replaced with t.Chdir + mkdir .context), drift/check_ext_test.go (mkdir .context), mcp/server/server_test.go.
mcp/cmd/root/cmd_test.go rewritten:
TestMcpServe_FailsClosedOnUnsetCTXDIR ->
TestMcpServe_FailsClosedWhenNoDotContext: now uses t.Chdir(t.TempDir()) and asserts the fail-closed behaviour under cwd-anchored.
User-facing warning updated: config/warn/warn.go's RCNoContextDir message changed from
"rc.RC: no CTX_DIR declared" to "rc.RC: no .context/ at $PWD".
== Also in this jumbo (prior + this session): ==
AI backend spec scaffolding (block A contract + block B+C sketched-not-contracted):
KB editorial pipeline scaffolding (Phase KB landed in prior session):
Substrate-vs-artifact placement convention codified: CONVENTIONS.md entry under File Organization plus a DECISIONS.md entry capturing the three coupling tests (consumed via ctx-mediated paths; tightly coupled to ctx pipeline machinery; authored under ctx skill discipline) and the three rejected alternatives.
Handover artifact migration (prior sessions):
CI/lint helpers:
Typography guide:
Many small assets edits (test surface fallout, skill polish, YAML key renames captured in prior commits, leftover here).
docs/ site/ regenerated to match prose edits.
== Verification: ==
== Provenance: ==
Two-session work on feat/cwd-anchored-context; the user's jumbo strategy explicitly accumulates across sessions until a single comprehensive commit lands. Not pushed.
Spec: specs/cwd-anchored-context.md
Spec: specs/ctx-ai-backend.md
Spec: specs/ctx-ai-extraction-and-recall.md
Spec: specs/activate-strict-cwd.md (superseded)
Spec: specs/single-source-context-anchor.md (superseded)