@dotdotgod/claude-code 0.6.4 → 0.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -76,7 +76,7 @@ Projects can customize memory roles with `memory.areas`, select traceability-enf
76
76
 
77
77
  ## Bundled MCP And Hooks
78
78
 
79
- The plugin starts a local stdio MCP server. It exposes `execute` and `execute_file`; context index, search, fetch, session resume, durable ingestion-job lifecycle, explicit healing, stats, doctor, and purge tools; plus `dotdotgod_project_load`, `dotdotgod_project_impact`, and `dotdotgod_project_initialize`.
79
+ The plugin starts a local stdio MCP server. It exposes `execute` and `execute_file`; context index, search, fetch, session resume, durable ingestion-job lifecycle, explicit healing, stats, doctor, and purge tools; plus `project_load`, `project_impact`, `impact_status`, `project_initialize`, `embedding_status`, and confirmation-gated `embedding_install`. Individual names have no `dotdotgod_` prefix; discover the host-qualified names. Reload existing sessions after upgrading; legacy names are not aliases.
80
80
 
81
81
  Dotdotgod execution tools share a 10 MiB stdout/stderr capture ceiling per command. Crossing that ceiling terminates the child process and reports `captureLimitExceeded`; direct stdout and stderr excerpts are each capped at 1 MiB. Their child environments preserve compatibility-oriented inheritance after filtering runtime injection variables; this reports filtered names without values but does not isolate ordinary inherited credentials. Large output is indexed before retrieval in the ignored project-local `.dotdotgod/context/context.sqlite` FTS5 store, and searches return bounded excerpts. The store uses WAL, a bounded busy timeout, and transactional source replacement, expiry, and purge. Structural Markdown/JSON chunks, bounded typo-tolerant trigram candidates, reciprocal-rank fusion, and title/path/proximity signals improve retrieval while provenance and `instructionAuthority: "none"` identify retrieved text as non-authoritative data.
82
82
 
@@ -84,6 +84,16 @@ The MCP `index` tool accepts files or explicitly requested bounded directories,
84
84
 
85
85
  Bundled hooks mark project load as required at session start, record successful source/config edits, and deny broad verification or handoff commands until matching graph impact succeeds. Denial asks Claude to call the required MCP tool and retry; hooks do not silently change one tool type into another. See [`hooks/README.md`](https://github.com/dotdotgod/dotdotgod-kit/blob/main/packages/claude-code/hooks/README.md) for lifecycle and trust boundaries.
86
86
 
87
+ ## Native Plan Directory
88
+
89
+ After opting in, run `dotdotgod init . --claude-plans --dry-run`, then repeat
90
+ without `--dry-run` to add project `.claude/settings.json` `plansDirectory`.
91
+ Use `node <plugin>/mcp/cli.mjs init . --claude-plans` if the CLI is unavailable.
92
+ Existing values and other settings are preserved; global settings and permissions
93
+ are untouched. Native filenames remain Claude Code-owned, while shared task plans
94
+ use `docs/plan/<task-slug>/README.md` when the mode permits. No Mods are required.
95
+ Actual native storage was verified on Claude Code 2.1.308 with an offline fixture.
96
+
87
97
  ## Local Development
88
98
 
89
99
  ```bash
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Initialize dotdotgod project memory and config
3
- argument-hint: [project-root] [--dotdot-setting] [--dry-run]
3
+ argument-hint: [project-root] [--dotdot-setting] [--claude-plans] [--dry-run]
4
4
  allowed-tools: [Read, Glob, Grep, Bash, Write, Edit]
5
5
  ---
6
6
 
@@ -38,3 +38,8 @@ Create a non-destructive dotdotgod baseline with canonical agent instructions, t
38
38
  3. The POSIX fallback supports bundled templates only. If a custom template was selected and the CLI is unavailable, stop and explain that custom templates require the CLI; do not silently substitute another template.
39
39
  4. Validate the initialized project with `dotdotgod validate <project-root>` when available.
40
40
  5. Report created and skipped files, the selected template, validation failures, and unresolved instruction conflicts.
41
+
42
+
43
+ ## Native Plan Storage
44
+
45
+ Only after the user opts in, add `--claude-plans` to the CLI initialization command. It adds project-local `plansDirectory` without replacing an existing value or changing permissions. Preview with `--dry-run`. The shell fallback does not support this option: use the bundled CLI at `$CLAUDE_PLUGIN_ROOT/mcp/cli.mjs` instead. Native file names remain Claude Code-owned; shared task plans still use task directories and README.md.
@@ -16,6 +16,10 @@ Task request: `$ARGUMENTS`
16
16
 
17
17
  For focused documentation routing, run `dotdotgod query <root> "<focus>" --limit 30 --json`. Run `dotdotgod config <root> --json` when memory-area policy or documentation routing/exclusions affect the plan. If the CLI is unavailable, continue from README indexes and focused file reads.
18
18
 
19
+ ## Native Plan Mode
20
+
21
+ Claude Code owns its native plan file and naming. An opt-in plansDirectory setting can place native files under the project documentation plan directory; it does not grant arbitrary task README writes in native Plan Mode. Follow the native allowed path and permissions. Create the shared task README when the active mode permits it; never bypass restrictions through MCP or hooks.
22
+
19
23
  ## Goal
20
24
 
21
25
  Create an implementation plan from maintained repository documentation before substantial source or configuration changes.
@@ -28,7 +32,7 @@ Use `docs/plan/<task-slug>/README.md` for substantial, risky, or resumable work;
28
32
  2. Reuse loaded memory and the documentation map, then use focused query and README indexes to select maintained docs and verify conclusions in them.
29
33
  3. Inspect the source needed to confirm targets and constraints.
30
34
  4. Run impact review on likely changed files and refine targets, risks, and verification.
31
- 5. For durable work, write and present the task README with scope, targets, executable steps, verification, and required completion gates.
35
+ 5. When the active mode and permissions allow it, write and present the task README with scope, targets, executable steps, verification, and required completion gates.
32
36
  6. Resolve blocking decisions and stop until the user asks to execute the plan.
33
37
 
34
38
  ## Quality Rules
package/hooks/README.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## Packaged Defaults
4
4
 
5
+ Local planning Markdown under the configured documentation plan directory does
6
+ not create source-impact pending state. Native plan paths and permissions remain
7
+ host-owned; hooks do not grant plan writes. Hook runtime state and MCP caches
8
+ have separate process permissions from the model's native tools.
9
+
5
10
  The adapter packages `hooks/hooks.json` and `hooks/runtime.mjs`. They inject a bounded project-load requirement at session start, record successful `Edit`/`Write` paths, and deny broad verification or handoff shell commands while graph impact is pending. A denial names the required dotdotgod MCP tool; Claude calls it and retries the original operation. MCP tools bypass their own guards to prevent recursion.
6
11
 
7
12
  Runtime state is local to `.dotdotgod/context/runtime/`. A successful impact call clears only paths whose current fingerprints match recorded edit state. Hooks run local commands with user permissions; review plugin resources before enabling them.
package/hooks/runtime.mjs CHANGED
@@ -90,7 +90,12 @@ function toolInput(input) {
90
90
  return input.tool_input || input.toolInput || {};
91
91
  }
92
92
  function mcpTool(name, suffix) {
93
- return name === suffix || name.endsWith(`__${suffix}`) || name.endsWith(`_${suffix}`);
93
+ return name === suffix || [
94
+ "mcp__dotdotgod_context__",
95
+ "mcp__dotdotgod-context__",
96
+ "mcp__plugin_dotdotgod_dotdotgod-context__",
97
+ "mcp__plugin_dotdotgod_dotdotgod_context__"
98
+ ].some((prefix) => name === `${prefix}${suffix}`);
94
99
  }
95
100
  function deny(reason) {
96
101
  return { hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "deny", permissionDecisionReason: reason } };
@@ -111,6 +116,16 @@ function changedPath(input, root) {
111
116
  const path = value.file_path || value.path;
112
117
  return normalizeProjectPath(root, path);
113
118
  }
119
+ function isPlanDocument(root, path) {
120
+ let documentationRoot = "docs";
121
+ try {
122
+ const config = JSON.parse(readFileSync(join(root, "dotdotgod.config.json"), "utf8"));
123
+ if (typeof config.documentation?.root === "string") documentationRoot = config.documentation.root;
124
+ } catch {
125
+ }
126
+ const plan = normalizeProjectPath(root, join(documentationRoot, "plan"));
127
+ return plan && isInsideRoot(plan, path) && /\.md$/i.test(path);
128
+ }
114
129
  function hasFailedToolResult(input) {
115
130
  const response = input.tool_response || input.toolResponse || input.tool_result || input.toolResult || input.result;
116
131
  if (!response || typeof response !== "object") return false;
@@ -132,19 +147,19 @@ function runHook(event) {
132
147
  if (!context) return {};
133
148
  state.loadRequired = true;
134
149
  writeState(context.path, state);
135
- return { hookSpecificOutput: { hookEventName: "SessionStart", additionalContext: "Dotdotgod project memory has not been loaded for this session. Before substantive shell or write work, call dotdotgod_project_load once with a concise task-specific focus." } };
150
+ return { hookSpecificOutput: { hookEventName: "SessionStart", additionalContext: "Dotdotgod project memory has not been loaded for this session. Before substantive shell or write work, call project_load from the dotdotgod-context MCP server once with a concise task-specific focus." } };
136
151
  }
137
152
  if (event === "pretooluse") {
138
- if (mcpTool(name, "dotdotgod_project_load") || mcpTool(name, "dotdotgod_project_impact")) return {};
139
- if (state.loadRequired && isSubstantive(name)) return deny("Project memory is required first. Call dotdotgod_project_load with the current project root and a concise task-specific focus, then retry this tool.");
153
+ if (mcpTool(name, "project_load") || mcpTool(name, "project_impact")) return {};
154
+ if (state.loadRequired && isSubstantive(name)) return deny("Project memory is required first. Call project_load from the dotdotgod-context MCP server with the current project root and a concise task-specific focus, then retry this tool.");
140
155
  const pendingPaths = Object.keys(state.pending);
141
- if (pendingPaths.length && isImpactGate(name, input)) return deny(`Graph impact is pending. Call dotdotgod_project_impact with paths=${JSON.stringify(pendingPaths)} and then retry this tool.`);
156
+ if (pendingPaths.length && isImpactGate(name, input)) return deny(`Graph impact is pending. Call project_impact from the dotdotgod-context MCP server with paths=${JSON.stringify(pendingPaths)} and then retry this tool.`);
142
157
  return {};
143
158
  }
144
159
  if (event === "posttooluse") {
145
160
  if (!context) return {};
146
- if (mcpTool(name, "dotdotgod_project_load")) state.loadRequired = false;
147
- else if (mcpTool(name, "dotdotgod_project_impact")) {
161
+ if (mcpTool(name, "project_load")) state.loadRequired = false;
162
+ else if (mcpTool(name, "project_impact")) {
148
163
  const checked = toolInput(input).paths;
149
164
  let cleared = 0;
150
165
  if (Array.isArray(checked)) for (const path of checked) {
@@ -155,11 +170,11 @@ function runHook(event) {
155
170
  }
156
171
  }
157
172
  writeState(context.path, state);
158
- if (cleared > 0 && hasFailedToolResult(input)) return { hookSpecificOutput: { hookEventName: "PostToolUse", additionalContext: `dotdotgod_project_impact reported a failure, but dotdotgod cleared pending graph impact for ${cleared} requested path(s) to avoid a blocking retry loop. Review the impact error before broad operations.` } };
173
+ if (cleared > 0 && hasFailedToolResult(input)) return { hookSpecificOutput: { hookEventName: "PostToolUse", additionalContext: `project_impact reported a failure, but dotdotgod cleared pending graph impact for ${cleared} requested path(s) to avoid a blocking retry loop. Review the impact error before broad operations.` } };
159
174
  return {};
160
175
  } else if (/^(Edit|Write|apply_patch)$/i.test(name)) {
161
176
  const path = changedPath(input, context.root);
162
- if (path) state.pending[path] = fileHash(path);
177
+ if (path && !isPlanDocument(context.root, path)) state.pending[path] = fileHash(path);
163
178
  }
164
179
  writeState(context.path, state);
165
180
  return {};