woods 2.0.0.beta2 → 2.0.0.beta4
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +339 -1
- data/CONTRIBUTING.md +188 -12
- data/README.md +93 -174
- data/SECURITY.md +9 -6
- data/docs/AGENT_GUIDE.md +109 -8
- data/docs/AGENT_SETUP.md +98 -7
- data/docs/BACKEND_MATRIX.md +25 -0
- data/docs/CLIENT_HOOKS.md +111 -0
- data/docs/CONFIGURATION_REFERENCE.md +267 -16
- data/docs/CONSOLE_MCP_SETUP.md +80 -7
- data/docs/DOCKER_SETUP.md +22 -3
- data/docs/EVALUATION.md +464 -1
- data/docs/EXTRACTOR_REFERENCE.md +45 -6
- data/docs/FAQ.md +11 -12
- data/docs/GETTING_STARTED.md +17 -5
- data/docs/INCREMENTAL_EXTRACTION.md +147 -7
- data/docs/INDEX_LAYOUT.md +382 -0
- data/docs/INTERNALS.md +7 -2
- data/docs/MCP_SERVERS.md +276 -5
- data/docs/MCP_TOOL_COOKBOOK.md +37 -22
- data/docs/MCP_WORKTREE_SETUP.md +43 -83
- data/docs/NOTION_INTEGRATION.md +13 -0
- data/docs/OBSIDIAN_INTEGRATION.md +57 -9
- data/docs/PUBLISHED_INDEX.md +72 -0
- data/docs/README.md +7 -0
- data/docs/RETRIEVAL_GUIDE.md +273 -12
- data/docs/RUNTIME_TRACING.md +71 -0
- data/docs/SOURCE_FRESHNESS.md +143 -0
- data/docs/TROUBLESHOOTING.md +129 -18
- data/docs/UNBLOCKED_INTEGRATION.md +25 -0
- data/docs/UPGRADING_TO_2.md +48 -22
- data/docs/WATCH_DAEMON.md +277 -67
- data/exe/woods-agent-config +6 -0
- data/exe/woods-extract +5 -0
- data/exe/woods-hook-context +6 -0
- data/exe/woods-mcp-start +14 -9
- data/lib/generators/woods/pgvector_generator.rb +8 -2
- data/lib/generators/woods/templates/woods.rb.tt +1 -3
- data/lib/tasks/woods.rake +47 -397
- data/lib/woods/agent_configuration/applier.rb +135 -0
- data/lib/woods/agent_configuration/cli.rb +101 -0
- data/lib/woods/agent_configuration/cli_options.rb +29 -0
- data/lib/woods/agent_configuration/document.rb +105 -0
- data/lib/woods/agent_configuration/error.rb +7 -0
- data/lib/woods/agent_configuration/launcher.rb +75 -0
- data/lib/woods/agent_configuration/layout.rb +72 -0
- data/lib/woods/agent_configuration/managed_section.rb +62 -0
- data/lib/woods/agent_configuration/plan.rb +98 -0
- data/lib/woods/agent_configuration/plan_diff.rb +38 -0
- data/lib/woods/agent_configuration/planned_files.rb +61 -0
- data/lib/woods/agent_configuration/planner.rb +63 -0
- data/lib/woods/agent_configuration/planner_validation.rb +77 -0
- data/lib/woods/agent_configuration/preflight.rb +100 -0
- data/lib/woods/agent_configuration/recovery.rb +49 -0
- data/lib/woods/ast/node.rb +2 -0
- data/lib/woods/ast/parser.rb +38 -5
- data/lib/woods/builder.rb +21 -5
- data/lib/woods/cache/cache_middleware.rb +28 -7
- data/lib/woods/cache/cache_store.rb +4 -5
- data/lib/woods/change_set.rb +5 -4
- data/lib/woods/console/credential_index.rb +20 -2
- data/lib/woods/console/credential_scanner.rb +18 -17
- data/lib/woods/console/credential_scanner_registry.rb +36 -0
- data/lib/woods/console/dispatch_pipeline.rb +7 -0
- data/lib/woods/console/embedded_executor.rb +32 -10
- data/lib/woods/console/encrypted_credential_snapshot.rb +16 -0
- data/lib/woods/console/rack_middleware.rb +22 -13
- data/lib/woods/console/server.rb +18 -16
- data/lib/woods/console/sql_noise_stripper.rb +9 -7
- data/lib/woods/console/sql_table_scanner.rb +47 -7
- data/lib/woods/console/sql_validator.rb +49 -9
- data/lib/woods/console/sqlite_read_guard.rb +46 -0
- data/lib/woods/coordination/pipeline_lock.rb +3 -2
- data/lib/woods/dependency_graph.rb +65 -13
- data/lib/woods/embedding/corpus.rb +94 -0
- data/lib/woods/embedding/indexer.rb +114 -60
- data/lib/woods/embedding/openai.rb +17 -6
- data/lib/woods/evaluation/ablation_executor.rb +6 -1
- data/lib/woods/evaluation/ablation_timed_executor.rb +22 -4
- data/lib/woods/export/typed_reader.rb +56 -0
- data/lib/woods/extractor.rb +277 -149
- data/lib/woods/extractors/action_cable_extractor.rb +3 -1
- data/lib/woods/extractors/behavioral_profile.rb +9 -7
- data/lib/woods/extractors/caching_extractor.rb +3 -1
- data/lib/woods/extractors/concern_extractor.rb +64 -6
- data/lib/woods/extractors/configuration_extractor.rb +7 -3
- data/lib/woods/extractors/controller_extractor.rb +13 -4
- data/lib/woods/extractors/database_view_extractor.rb +3 -1
- data/lib/woods/extractors/declared_parent.rb +55 -0
- data/lib/woods/extractors/decorator_extractor.rb +3 -1
- data/lib/woods/extractors/engine_extractor.rb +3 -1
- data/lib/woods/extractors/event_extractor.rb +4 -2
- data/lib/woods/extractors/factory_extractor.rb +3 -1
- data/lib/woods/extractors/graphql_extractor.rb +10 -13
- data/lib/woods/extractors/i18n_extractor.rb +3 -1
- data/lib/woods/extractors/job_extractor.rb +6 -19
- data/lib/woods/extractors/lib_extractor.rb +13 -9
- data/lib/woods/extractors/mailer_extractor.rb +26 -15
- data/lib/woods/extractors/manager_extractor.rb +3 -1
- data/lib/woods/extractors/method_parameters.rb +53 -0
- data/lib/woods/extractors/middleware_argument.rb +65 -0
- data/lib/woods/extractors/middleware_extractor.rb +9 -3
- data/lib/woods/extractors/migration_extractor.rb +3 -1
- data/lib/woods/extractors/model_extractor.rb +26 -34
- data/lib/woods/extractors/package_extractor.rb +24 -4
- data/lib/woods/extractors/phlex_extractor.rb +3 -1
- data/lib/woods/extractors/policy_extractor.rb +3 -1
- data/lib/woods/extractors/poro_extractor.rb +13 -9
- data/lib/woods/extractors/pundit_extractor.rb +3 -1
- data/lib/woods/extractors/rails_source_extractor.rb +4 -2
- data/lib/woods/extractors/rake_task_extractor.rb +4 -2
- data/lib/woods/extractors/route_extractor.rb +3 -1
- data/lib/woods/extractors/route_helper_resolver.rb +10 -33
- data/lib/woods/extractors/scheduled_job_extractor.rb +41 -15
- data/lib/woods/extractors/serializer_extractor.rb +4 -2
- data/lib/woods/extractors/service_extractor.rb +3 -1
- data/lib/woods/extractors/shared_dependency_scanner.rb +2 -2
- data/lib/woods/extractors/shared_utility_methods.rb +48 -19
- data/lib/woods/extractors/source_nesting.rb +1 -1
- data/lib/woods/extractors/state_machine_extractor.rb +3 -1
- data/lib/woods/extractors/test_mapping_extractor.rb +3 -1
- data/lib/woods/extractors/validator_extractor.rb +3 -1
- data/lib/woods/extractors/view_component_extractor.rb +3 -1
- data/lib/woods/extractors/view_template_extractor.rb +3 -1
- data/lib/woods/gem_mapper.rb +2 -0
- data/lib/woods/git_history.rb +116 -0
- data/lib/woods/graph_analyzer.rb +35 -6
- data/lib/woods/hooks/context_cli.rb +54 -0
- data/lib/woods/hooks/context_event.rb +88 -0
- data/lib/woods/hooks/context_hint.rb +73 -0
- data/lib/woods/hooks/context_impact.rb +77 -0
- data/lib/woods/hooks/context_output.rb +47 -0
- data/lib/woods/hooks/context_state.rb +102 -0
- data/lib/woods/hooks/refresh.rb +79 -0
- data/lib/woods/hooks/rule_projection.rb +78 -0
- data/lib/woods/input_rules.rb +19 -0
- data/lib/woods/mcp/bearer_auth.rb +22 -13
- data/lib/woods/mcp/bootstrapper.rb +79 -4
- data/lib/woods/mcp/config_resolver.rb +2 -1
- data/lib/woods/mcp/index_reader.rb +334 -162
- data/lib/woods/mcp/initialization_guidance.rb +27 -0
- data/lib/woods/mcp/origin_guard.rb +17 -9
- data/lib/woods/mcp/published_lexical_retriever.rb +115 -0
- data/lib/woods/mcp/renderers/markdown_renderer.rb +22 -9
- data/lib/woods/mcp/renderers/plain_renderer.rb +18 -8
- data/lib/woods/mcp/search_results.rb +74 -0
- data/lib/woods/mcp/server.rb +178 -63
- data/lib/woods/mcp/tool_contract.rb +3 -1
- data/lib/woods/mcp/tool_response_renderer.rb +41 -0
- data/lib/woods/mcp/traversal_evidence.rb +113 -0
- data/lib/woods/mcp/traversal_evidence_index.rb +100 -0
- data/lib/woods/mcp/traversal_evidence_page.rb +41 -0
- data/lib/woods/mcp/traversal_evidence_text.rb +52 -0
- data/lib/woods/mcp/traversal_response.rb +22 -0
- data/lib/woods/notion/exporter.rb +56 -17
- data/lib/woods/obsidian/destination_plan.rb +98 -0
- data/lib/woods/obsidian/name_mapper.rb +19 -3
- data/lib/woods/obsidian/note_builder.rb +19 -10
- data/lib/woods/obsidian/vault_exporter.rb +88 -32
- data/lib/woods/operator/pipeline_guard.rb +18 -13
- data/lib/woods/path_dispatcher.rb +13 -6
- data/lib/woods/payload_store.rb +27 -26
- data/lib/woods/published_index/typed_unit_reader.rb +40 -3
- data/lib/woods/published_index.rb +2 -2
- data/lib/woods/railtie.rb +3 -3
- data/lib/woods/railtie_support.rb +12 -12
- data/lib/woods/rake_helpers.rb +382 -0
- data/lib/woods/resilience/graph_invariant_validator/membership_checks.rb +71 -0
- data/lib/woods/resilience/graph_invariant_validator/node_checks.rb +61 -0
- data/lib/woods/resilience/graph_invariant_validator/reverse_relationship_checks.rb +46 -0
- data/lib/woods/resilience/graph_invariant_validator.rb +119 -0
- data/lib/woods/resilience/index_validator/graph_checks.rb +80 -0
- data/lib/woods/resilience/index_validator.rb +112 -23
- data/lib/woods/retrieval/context_assembler.rb +50 -15
- data/lib/woods/retrieval/lexical_assembler.rb +84 -0
- data/lib/woods/retrieval/lexical_index.rb +120 -0
- data/lib/woods/retrieval/ranker.rb +4 -2
- data/lib/woods/retrieval/scope.rb +108 -0
- data/lib/woods/retrieval/scoped_graph_store.rb +32 -0
- data/lib/woods/retrieval/scoped_vector_store.rb +55 -0
- data/lib/woods/retrieval/search_executor.rb +86 -27
- data/lib/woods/retrieval/source_evidence.rb +200 -0
- data/lib/woods/retriever.rb +98 -22
- data/lib/woods/ruby_analyzer/trace_enricher.rb +77 -38
- data/lib/woods/session_tracer/file_store.rb +6 -1
- data/lib/woods/session_tracer/middleware.rb +10 -12
- data/lib/woods/session_tracer/redis_store.rb +22 -6
- data/lib/woods/session_tracer/session_flow_assembler.rb +23 -17
- data/lib/woods/session_tracer/solid_cache_coordination.rb +6 -4
- data/lib/woods/session_tracer/unit_resolver.rb +63 -0
- data/lib/woods/source_inputs/consumer_errors.rb +31 -0
- data/lib/woods/source_inputs/handoff.rb +102 -0
- data/lib/woods/source_inputs/launcher.rb +157 -0
- data/lib/woods/source_inputs/manifest.rb +124 -0
- data/lib/woods/source_inputs/private_key.rb +55 -0
- data/lib/woods/source_inputs/scanner.rb +171 -0
- data/lib/woods/source_inputs/scopes.rb +71 -0
- data/lib/woods/source_inputs/session.rb +214 -0
- data/lib/woods/source_inputs/status.rb +84 -0
- data/lib/woods/source_inputs/verifier.rb +107 -0
- data/lib/woods/storage/metadata_store.rb +25 -25
- data/lib/woods/storage/pgvector.rb +35 -10
- data/lib/woods/storage/qdrant.rb +17 -7
- data/lib/woods/storage/vector_store.rb +18 -6
- data/lib/woods/tasks.rb +3 -2
- data/lib/woods/temporal/json_snapshot_store.rb +58 -9
- data/lib/woods/unblocked/exporter.rb +59 -70
- data/lib/woods/version.rb +1 -1
- data/lib/woods/watch/boot_snapshot.rb +52 -0
- data/lib/woods/watch/daemon.rb +154 -32
- data/lib/woods/watch/listen_watcher.rb +4 -0
- data/lib/woods/watch/polling_watcher.rb +5 -1
- data/lib/woods/watch/status.rb +20 -15
- data/lib/woods/watch/tree_scan.rb +21 -13
- data/lib/woods/watch/watcher.rb +4 -1
- data/lib/woods.rb +50 -11
- data/plugin/.claude-plugin/plugin.json +1 -1
- data/plugin/hooks/adapters/normalize.jq +15 -0
- data/plugin/hooks/adapters/normalize.rb +63 -0
- data/plugin/hooks/hooks.json +20 -0
- data/plugin/hooks/woods-context.sh +50 -0
- data/plugin/hooks/woods-input-rules.sh +159 -0
- data/plugin/hooks/woods-opencode.mjs +65 -0
- data/plugin/hooks/woods-post-edit.sh +2 -225
- data/plugin/hooks/woods-refresh.sh +260 -0
- data/plugin/hooks/woods-session-start.sh +47 -55
- data/plugin/skills/woods-agent-enable/SKILL.md +19 -0
- data/plugin/skills/woods-diagnose/SKILL.md +319 -1
- data/plugin/skills/woods-investigate/SKILL.md +145 -0
- data/plugin/skills/woods-mcp-config/SKILL.md +90 -2
- data/plugin/skills/woods-setup/SKILL.md +110 -6
- metadata +87 -5
data/docs/AGENT_SETUP.md
CHANGED
|
@@ -40,13 +40,23 @@ If the worktree contains unrelated changes, preserve them. Do not overwrite an e
|
|
|
40
40
|
|
|
41
41
|
Use structural-only setup when the user wants code navigation, runtime Rails structure, dependencies, flows, or blast-radius analysis. Fourteen tools register in the normal packaged launch without an embedding provider.
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
If the user wants ranked discovery through `codebase_retrieve`, offer [explicit lexical mode](RETRIEVAL_GUIDE.md#embedding-free-lexical-retrieval) over the published index without a provider or embeddings. Check that the installed version supports it, set `WOODS_RETRIEVAL_MODE=lexical` in the MCP process environment, restart that server, and verify `woods_status.retriever.mode`. Keep structural-only setup as the default unless this mode is requested.
|
|
44
|
+
|
|
45
|
+
For semantic matching, discuss local Ollama or hosted OpenAI and the appropriate vector store separately; adding a provider still requires authorization. See [Backend matrix](BACKEND_MATRIX.md).
|
|
44
46
|
|
|
45
47
|
Do not infer permission to configure Console MCP from a request to “set up Woods” or “set up MCP.” The Index Server reads generated code context; the Console Server can read live data.
|
|
46
48
|
|
|
47
49
|
## 3. Install on a branch
|
|
48
50
|
|
|
49
|
-
Create or switch to the branch requested by the repository owner.
|
|
51
|
+
Create or switch to the branch requested by the repository owner. Select the
|
|
52
|
+
published version using the [installation guide](GETTING_STARTED.md#1-install-the-gem).
|
|
53
|
+
Before stable 2.x is published, use the exact published prerelease constraint
|
|
54
|
+
from the README release table; `~> 2.0` will not select a beta or release candidate.
|
|
55
|
+
Use the selected version's tag documentation and verify its capabilities before
|
|
56
|
+
configuring features described on `main`.
|
|
57
|
+
|
|
58
|
+
Add only the development dependency. The following constraint applies **after a
|
|
59
|
+
stable 2.x release is published**:
|
|
50
60
|
|
|
51
61
|
```ruby
|
|
52
62
|
# Gemfile
|
|
@@ -120,15 +130,94 @@ For Docker, extraction runs inside the Rails container. If Woods is installed on
|
|
|
120
130
|
|
|
121
131
|
Reconnect the client and call `woods_status`. Confirm a current generation and non-zero unit counts before claiming setup works.
|
|
122
132
|
|
|
133
|
+
### Managed Claude Code configuration
|
|
134
|
+
|
|
135
|
+
`woods-agent-config` is available from Woods `2.0.0.beta3`.
|
|
136
|
+
Check `bundle exec woods-agent-config --help` in the selected application bundle;
|
|
137
|
+
use the manual client configuration below when it is absent. The supported
|
|
138
|
+
client format is Claude Code (tested with 2.1.267).
|
|
139
|
+
|
|
140
|
+
Create a private plan, inspect its paths and diff, then apply that same plan:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
bundle exec woods-agent-config setup --client claude --scope project \
|
|
144
|
+
--root "$PWD" --instructions CLAUDE.md,AGENTS.md --plan /tmp/woods-setup.json --diff
|
|
145
|
+
bundle exec woods-agent-config apply /tmp/woods-setup.json \
|
|
146
|
+
--client claude --scope project --root "$PWD"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Choose a new, unused plan filename for each preview. Preview writes only the
|
|
150
|
+
requested plan file; it does not edit managed configuration. Plans contain the
|
|
151
|
+
complete replacement bytes, including unrelated settings, and use mode 0600:
|
|
152
|
+
keep them private and remove them when no longer needed. `show FILE` prints its
|
|
153
|
+
summary; `show FILE --diff` checks the original snapshots and prints a unified
|
|
154
|
+
diff. Applying a changed snapshot fails rather than replacing the new content.
|
|
155
|
+
A repeated identical setup makes no configuration edits.
|
|
156
|
+
|
|
157
|
+
| Selection | Managed files |
|
|
158
|
+
|---|---|
|
|
159
|
+
| `--scope project` | `<root>/.mcp.json`, explicitly selected `<root>/CLAUDE.md` and/or `AGENTS.md`, `<root>/.woods-agent-config.json` ownership receipt |
|
|
160
|
+
| `--scope user` | `~/.claude.json`, explicitly selected `~/.claude/CLAUDE.md`, application-specific receipt in `~/.claude/` |
|
|
161
|
+
|
|
162
|
+
With `CLAUDE_CONFIG_DIR`, user scope uses that directory's `.claude.json`,
|
|
163
|
+
`CLAUDE.md`, and receipt instead. Instruction edits are opt-in with
|
|
164
|
+
`--instructions`; existing selections carry forward on update. The command
|
|
165
|
+
configures the Index Server. Client trust and project approval remain Claude
|
|
166
|
+
Code settings; apply does not change them.
|
|
167
|
+
|
|
168
|
+
Preflight runs the selected installed bundle, validates its index, and checks
|
|
169
|
+
its actual registered capabilities. It does not boot Rails or contact an
|
|
170
|
+
embedding provider. The bundle must already resolve in frozen mode; prepare
|
|
171
|
+
its lockfile separately if Bundler reports a mismatch. Host mode uses the
|
|
172
|
+
application's absolute Gemfile and index paths. `--index tmp/woods` is relative
|
|
173
|
+
to the selected root. For Compose, also select `--mode compose --service web
|
|
174
|
+
--container-root /app`; run the configuration command where Docker Compose can
|
|
175
|
+
access that project. Preflight verifies the index and installed gem inside that
|
|
176
|
+
service. Both host and container subprocesses have time limits.
|
|
177
|
+
|
|
178
|
+
Use `update --plan FILE` with the same client/scope/root and the desired launch
|
|
179
|
+
options to change the owned entry or instruction selection. Update explicitly
|
|
180
|
+
records the current template and installed-gem evidence; background hooks never
|
|
181
|
+
update configuration. `remove --plan FILE` previews deletion of owned content
|
|
182
|
+
and does not require the application bundle or index to remain available.
|
|
183
|
+
Use `--name NAME` consistently if the installation uses a nondefault server name.
|
|
184
|
+
Apply each operation's saved plan with the same explicit client/scope/root.
|
|
185
|
+
|
|
186
|
+
Ownership comes from the receipt and exact managed section, not from a server
|
|
187
|
+
named `woods`. Existing unowned names, edited managed content, malformed JSON,
|
|
188
|
+
duplicate markers, symlinks, and concurrent edits cause conflicts. Preserve the
|
|
189
|
+
receipt for future update/removal. Unrelated servers, hooks, settings,
|
|
190
|
+
instruction text, permissions, and line-ending conventions are retained;
|
|
191
|
+
changing JSON may reformat its whitespace.
|
|
192
|
+
|
|
193
|
+
Unreleased after `2.0.0.beta3`: apply and recovery coordinate on the actual
|
|
194
|
+
managed file paths, including user configuration and shared instruction files.
|
|
195
|
+
Two application roots sharing those files cannot apply overlapping plans at the
|
|
196
|
+
same time. A competing operation reports a conflict; after it finishes, create a
|
|
197
|
+
fresh preview if the saved plan's snapshots changed. Both applications keep
|
|
198
|
+
their own ownership receipts. Do not delete an active coordination lock.
|
|
199
|
+
|
|
200
|
+
Writes use atomic replacement per file and a private recovery journal beside
|
|
201
|
+
the receipt. The plan summary names all adjacent `.woods.lock` files, the
|
|
202
|
+
receipt `.lock`, and the `.pending` journal;
|
|
203
|
+
a lock file may remain after completion. Multiple files are not one atomic
|
|
204
|
+
transaction. An ordinary write failure restores original files when safe; an
|
|
205
|
+
interruption or concurrent edit can retain the journal. Resolve reported
|
|
206
|
+
conflicts, then use `recover --client claude --scope project --root "$PWD"`
|
|
207
|
+
(or the original user scope). Recovery refuses to overwrite concurrent edits.
|
|
208
|
+
Keep journals private because they contain original configuration bytes. A plan
|
|
209
|
+
whose recovery journal would exceed 8 MiB is refused before any managed file
|
|
210
|
+
is changed; reduce the selected configuration before applying.
|
|
211
|
+
|
|
123
212
|
## 7. Verify useful behavior
|
|
124
213
|
|
|
125
214
|
Use a class known to exist in the application:
|
|
126
215
|
|
|
127
|
-
1. Call `search` to obtain its exact identifier.
|
|
128
|
-
2. Call `lookup` to confirm source and metadata are present.
|
|
216
|
+
1. Call `search` to obtain its exact identifier and type.
|
|
217
|
+
2. Call `lookup` with that identifier and type to confirm source and metadata are present.
|
|
129
218
|
3. Call `dependents` with depth 1 or 2 to confirm graph edges are queryable.
|
|
130
219
|
|
|
131
|
-
If `codebase_retrieve` reports that semantic search is disabled, that is expected for structural-only setup. Do not configure credentials merely to remove the message.
|
|
220
|
+
If `codebase_retrieve` reports that semantic search is disabled, that is expected for structural-only setup. Do not configure credentials merely to remove the message. If lexical retrieval was requested, verify its mode with `woods_status` and make one `codebase_retrieve` call against the published index.
|
|
132
221
|
|
|
133
222
|
## 8. Offer automatic index maintenance
|
|
134
223
|
|
|
@@ -184,7 +273,7 @@ Verified capabilities:
|
|
|
184
273
|
- Index Server connected: yes/no
|
|
185
274
|
- woods_status current: yes/no
|
|
186
275
|
- search/lookup/dependents checked: yes/no
|
|
187
|
-
-
|
|
276
|
+
- retrieval: disabled/lexical/semantic (provider when semantic)
|
|
188
277
|
- Console MCP: disabled/enabled (authorization)
|
|
189
278
|
- automatic structural updates: disabled/enabled (process manager)
|
|
190
279
|
|
|
@@ -195,10 +284,12 @@ Never report a capability as enabled solely because its schema exists in source.
|
|
|
195
284
|
|
|
196
285
|
## Copyable prompt for an installation agent
|
|
197
286
|
|
|
198
|
-
> Install Woods 2.x in this Rails repository using
|
|
287
|
+
> Install Woods 2.x in this Rails repository using https://github.com/lost-in-the/woods/blob/main/docs/AGENT_SETUP.md. Select a published version and follow that version's tag documentation and supported capabilities. Start with read-only preflight and preserve unrelated changes. Default to the structural Index Server; do not enable embeddings, Console MCP, HTTP transport, secrets, or purge overrides without asking me. Inspect generated files before migrating, run extraction and validation in the app's normal execution environment, configure a project-scoped MCP server in the same filesystem context as the application bundle and index, and verify `woods_status`, `search`, `lookup` with the discovered identifier and type, and `dependents`. Finish with the runbook's handoff report.
|
|
199
288
|
|
|
200
289
|
## Related guides
|
|
201
290
|
|
|
291
|
+
- [Edit client adapters](CLIENT_HOOKS.md) for separately opt-in Claude/OpenCode edit hooks; MCP setup does not enable them.
|
|
292
|
+
|
|
202
293
|
- [Getting started](GETTING_STARTED.md) for the human walkthrough.
|
|
203
294
|
- [MCP servers](MCP_SERVERS.md) for client-specific configuration and server boundaries.
|
|
204
295
|
- [Upgrade to Woods 2.0](UPGRADING_TO_2.md) for an existing 1.x installation.
|
data/docs/BACKEND_MATRIX.md
CHANGED
|
@@ -96,6 +96,11 @@ CREATE INDEX IF NOT EXISTS idx_woods_vectors_embedding_hnsw
|
|
|
96
96
|
ON woods_vectors USING hnsw (embedding vector_cosine_ops);
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
**Dimension limit:** Woods uses `vector_cosine_ops` HNSW, limited to 2,000 dimensions.
|
|
100
|
+
The default 3,072-dimensional `text-embedding-3-large` output needs an explicit
|
|
101
|
+
smaller provider output width or another backend. See the
|
|
102
|
+
[pgvector configuration contract](CONFIGURATION_REFERENCE.md#pgvector-postgresql).
|
|
103
|
+
|
|
99
104
|
**Performance notes:**
|
|
100
105
|
- HNSW: ~5ms search at 10K vectors, ~20ms at 100K. Memory: ~1.5x vector size.
|
|
101
106
|
- For codebase indexing (~1000-5000 units, potentially 5000-20000 chunks), HNSW is appropriate.
|
|
@@ -271,6 +276,12 @@ contract tests; it does not represent semantic quality. Other values raise
|
|
|
271
276
|
|
|
272
277
|
`build_metadata_store` accepts `:in_memory` and `:sqlite`. Nothing else is implemented.
|
|
273
278
|
|
|
279
|
+
Both adapters search Boolean fields as the JSON words `true` and `false`,
|
|
280
|
+
with case-insensitive substring matching. Numeric values `1` and `0` remain
|
|
281
|
+
separate from Booleans. Strings are searched without JSON quotes; objects and
|
|
282
|
+
arrays use JSON text. Null or absent fields never match a field-scoped query.
|
|
283
|
+
Whole-record search (`fields: nil`) searches serialized JSON, including keys.
|
|
284
|
+
|
|
274
285
|
### SQLite
|
|
275
286
|
|
|
276
287
|
**Best for:** Local development, zero-dependency setups, testing, and every shipped preset except pure in-memory.
|
|
@@ -284,6 +295,11 @@ contract tests; it does not represent semantic quality. Other values raise
|
|
|
284
295
|
- Single writer at a time
|
|
285
296
|
- No network access
|
|
286
297
|
|
|
298
|
+
Metadata search uses literal, ASCII-case-insensitive substring matching. Selected
|
|
299
|
+
string fields include embedded NUL characters in the searchable text. With no
|
|
300
|
+
field selection, search operates on serialized JSON, where NUL is represented
|
|
301
|
+
as `\u0000`; a literal NUL query therefore does not match that escaped text.
|
|
302
|
+
|
|
287
303
|
### In-memory
|
|
288
304
|
|
|
289
305
|
**Best for:** Testing, evaluation, small codebases.
|
|
@@ -318,6 +334,15 @@ A recursive-CTE graph store (MySQL 8.0+ or PostgreSQL, storing edges in a table
|
|
|
318
334
|
|
|
319
335
|
Indexing can be triggered synchronously (rake task, inline) or from a background job. The pipeline itself is job-system-agnostic, it's synchronous Ruby, and the wrapper below is just scheduling and concurrency control. Use `Woods.extract!` for a full run; incremental runs need a changed-file list, so a job usually just shells out to `rake woods:incremental` (which computes that list from git) rather than calling `Woods.extract_changed!` directly.
|
|
320
336
|
|
|
337
|
+
Both Ruby helpers hold the same heartbeat-maintained extraction lock as the
|
|
338
|
+
tasks and watch daemon. `WOODS_LOCK_WAIT` controls the wait (600 seconds by
|
|
339
|
+
default); timeout raises `Woods::Coordination::LockError`. Failed generation
|
|
340
|
+
publication raises `Woods::ExtractionError`, allowing job retries instead of
|
|
341
|
+
reporting unpublished work as success. The low-level `Woods::Extractor` remains
|
|
342
|
+
an orchestration building block: callers using it directly own locking and
|
|
343
|
+
publication-failure handling. Do not wrap the public helpers in a second Woods
|
|
344
|
+
extraction lock.
|
|
345
|
+
|
|
321
346
|
### Sidekiq
|
|
322
347
|
|
|
323
348
|
```ruby
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Edit hooks for Claude Code and OpenCode
|
|
2
|
+
|
|
3
|
+
Edit hooks are optional. MCP reads and `woods:watch` work independently of them.
|
|
4
|
+
Check the installed gem exposes `woods:hook_refresh` before enabling these
|
|
5
|
+
unreleased adapters; updating the plugin does not update the application gem.
|
|
6
|
+
Start the client from the Rails application root, with an existing index.
|
|
7
|
+
|
|
8
|
+
## Supported client contracts
|
|
9
|
+
|
|
10
|
+
| Client | Verified version | Events covered |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| Claude Code | 2.1.267 | Successful `PostToolUse` for `Write` and `Edit`, using `tool_input.file_path` |
|
|
13
|
+
| Claude legacy compatibility | Existing single-file `MultiEdit` shape | One `tool_input.file_path`; this is not multi-file patch support |
|
|
14
|
+
| OpenCode | 1.18.27 | `tool.execute.after` for `apply_patch`, `write`, and `edit` |
|
|
15
|
+
|
|
16
|
+
The OpenCode patch adapter reads the successful tool's `metadata.files` array.
|
|
17
|
+
It includes every add, update, delete and move; a move becomes deletion of the
|
|
18
|
+
old path plus addition of the new path. `write` uses `metadata.filepath` and
|
|
19
|
+
`metadata.exists`; `edit` uses `metadata.filediff.file`. Patch text, source bytes,
|
|
20
|
+
diagnostics, session identifiers and arbitrary shell commands are not parsed
|
|
21
|
+
or placed in the queue. Actual client captures and their provenance live under
|
|
22
|
+
`spec/fixtures/hooks/`; the exact metadata contract is pinned to
|
|
23
|
+
[OpenCode v1.18.27 source](https://github.com/anomalyco/opencode/tree/v1.18.27/packages/opencode/src/tool).
|
|
24
|
+
See the primary [Claude hook reference](https://code.claude.com/docs/en/hooks)
|
|
25
|
+
and [OpenCode plugin reference](https://opencode.ai/docs/plugins/).
|
|
26
|
+
|
|
27
|
+
Other clients and arbitrary mutation tools are unsupported. Unknown shapes for
|
|
28
|
+
registered edit tools produce a short diagnostic instead of claiming refresh.
|
|
29
|
+
Use the resident watcher or an explicit extraction for unsupported operations.
|
|
30
|
+
OpenCode session-start/context hooks are not provided by this edit adapter.
|
|
31
|
+
|
|
32
|
+
## Claude Code registration
|
|
33
|
+
|
|
34
|
+
The Woods Claude plugin registers `woods-post-edit.sh` through its existing
|
|
35
|
+
`hooks/hooks.json`. The wrapper selects the explicit Claude parser, then the
|
|
36
|
+
shared runner handles queueing and extraction. Do not install a second copy of
|
|
37
|
+
the same hook. Existing single-file `MultiEdit` compatibility remains registered.
|
|
38
|
+
|
|
39
|
+
Enable the existing environment settings in the process launching the client:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
export WOODS_HOOKS_ENABLED=1
|
|
43
|
+
# Optional; relative to the application root:
|
|
44
|
+
export WOODS_OUTPUT=tmp/woods
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`WOODS_HOOKS_DISABLED=1` always wins. Enablement does not authorize Console MCP,
|
|
48
|
+
provider calls, user configuration writes, or daemon lifecycle changes.
|
|
49
|
+
|
|
50
|
+
## OpenCode project registration
|
|
51
|
+
|
|
52
|
+
Keep the complete Woods `plugin/` directory at a stable path visible to the
|
|
53
|
+
client. The Claude marketplace registration does not install a native OpenCode
|
|
54
|
+
plugin. Create a project-local `.opencode/plugins/woods.js` containing this one
|
|
55
|
+
import, replacing the path with that stable plugin location:
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
export { default } from "/absolute/path/to/woods/plugin/hooks/woods-opencode.mjs";
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
OpenCode automatically loads project `.js` and `.ts` plugin files at startup.
|
|
62
|
+
Use the `.js` wrapper name above; copying a standalone `.mjs` file into the
|
|
63
|
+
autoload directory does not register it. The wrapper imports the complete
|
|
64
|
+
adapter and shared runner; copying only the shell entry point is insufficient.
|
|
65
|
+
Restart OpenCode after registration and set `WOODS_HOOKS_ENABLED=1` in its launch
|
|
66
|
+
environment. This setup does not require npm packages or a host Rails bundle.
|
|
67
|
+
|
|
68
|
+
The adapter uses OpenCode's `directory` as the application root and verifies
|
|
69
|
+
that it belongs to the supplied git `worktree`. A Rails application nested
|
|
70
|
+
inside a repository therefore uses its own index. Each affected path must stay
|
|
71
|
+
inside that application root. Linked worktrees keep separate queues and indexes.
|
|
72
|
+
|
|
73
|
+
## Queue, paths and recovery
|
|
74
|
+
|
|
75
|
+
Both adapters use the same extraction eligibility, queue, command prefix,
|
|
76
|
+
deadline, locks and active-daemon behavior described in
|
|
77
|
+
[watch hook operation](WATCH_DAEMON.md#hooks-for-agent-sessions).
|
|
78
|
+
`WOODS_HOOK_RAKE="docker compose exec -T app bundle exec rake"` runs extraction
|
|
79
|
+
inside the application container. The host needs Bash 3.2 or later, Unix tools,
|
|
80
|
+
and either jq or Ruby; OpenCode supplies its own JavaScript runtime.
|
|
81
|
+
|
|
82
|
+
The complete event is validated before queueing. Empty/NUL paths, traversal,
|
|
83
|
+
foreign-project paths and symlink path components are rejected. Deleted paths
|
|
84
|
+
need not exist; contained symlinks are deliberately unsupported too. Spaces,
|
|
85
|
+
commas, newlines and Unicode paths remain intact. Adapter input is limited to
|
|
86
|
+
1 MiB and 1,000 affected paths; the OpenCode handoff is additionally limited to
|
|
87
|
+
48 KiB. An unsupported oversized event requires explicit extraction or watch.
|
|
88
|
+
Raw input uses a private temporary file during validation so the shell cannot
|
|
89
|
+
silently remove bytes. The runner removes that file before publishing the
|
|
90
|
+
path-only queue record, and cleans it up on handled exits.
|
|
91
|
+
|
|
92
|
+
One immutable queue file holds a multi-file event. The owner batches up to
|
|
93
|
+
16 files, 1,000 paths and 48 KiB without splitting an event. Existing single-path
|
|
94
|
+
queue records remain readable. A successful task, including a confirmed no-op,
|
|
95
|
+
acknowledges the batch; failure, timeout or daemon exit 75 retains every path.
|
|
96
|
+
At-least-once delivery can repeat work after a crash or event replay.
|
|
97
|
+
|
|
98
|
+
The OpenCode callback hands the event to a detached runner, which owns its
|
|
99
|
+
existing deadline. Callback completion means handoff, not index publication.
|
|
100
|
+
Inspect `<output>/hook.log`, the pending queue and the published generation to
|
|
101
|
+
confirm refresh. Malformed input diagnostics omit the original tool payload.
|
|
102
|
+
For rollback, disable hooks before removing registration; preserve pending
|
|
103
|
+
multi-file records until a compatible runner has consumed them.
|
|
104
|
+
|
|
105
|
+
## Optional Claude context
|
|
106
|
+
|
|
107
|
+
Claude has a separate opt-in for bounded synchronous orientation and change-impact
|
|
108
|
+
reminders. It does not change either client’s refresh queue contract and is not
|
|
109
|
+
enabled by `WOODS_HOOKS_ENABLED`. Check the installed helper, timing, path-mapping
|
|
110
|
+
and uncertainty contract in [bounded context hints](WATCH_DAEMON.md#optional-bounded-context-hints).
|
|
111
|
+
OpenCode refresh support does not imply context delivery support.
|