Skip to content

feat: knowledge base doc-freshness layer (drift detection + refresh)#285

Open
efenocchi wants to merge 16 commits into
mainfrom
feat/knowledge-base-docs
Open

feat: knowledge base doc-freshness layer (drift detection + refresh)#285
efenocchi wants to merge 16 commits into
mainfrom
feat/knowledge-base-docs

Conversation

@efenocchi

@efenocchi efenocchi commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

What

Adds a Knowledge Base / per-file documentation layer that stays fresh on code deltas — the third layer alongside session summaries and the AST code graph. For the Krisp use case: internal docs that go stale because code changes many times a day.

Honest framing (per the team's own oracle eval): this is justified as doc freshness / onboarding trust / token savings, NOT QA-answer accuracy.

How it works

A doc anchors each described symbol to a content_hash of its source slice. On a commit, the graph diff + blast-radius selects only the docs whose anchored code (or its callers) changed; a bounded LLM edit regenerates them through an objective gate; the new version is written INSERT-only (version-bumped, immutable created_at).

code change -> graph diff + blast-radius -> impacted docs
            -> host LLM bounded rewrite -> gate -> setDoc (version+1)

Steps in this PR

  • 1 - schema + config: hivemind_docs table (INSERT-only, version-bumped) + docsTableName.
  • 2 - store: src/docs insert/edit/list/get + idempotent setDoc (no history fork).
  • 3 - drift detector: anchors.ts (source-slice hash) + impact.ts (direct hash drift + blast-radius widening over the graph).
  • 5 - refresh engine: gate.ts (objective invariants: bounded edit, anchors exist, slow-tier protected) + refresh.ts (re-anchor -> generate -> gate -> write) + refresh-llm.ts (host claude -p, reuses the wiki-worker seam) + hivemind docs CLI (set/show/list/archive/refresh, --anchor, --dry-run).
  • 8 - trigger: opt-in HIVEMIND_DOCS_AUTO_REFRESH=1 fires a detached refresh at the end of graph build.

Testing

  • ~105 unit tests; new docs files >=85% line coverage (gate/write/read/refresh-llm 100%).
  • End-to-end through the real hivemind binary against a test Deeplake table: real code change -> drift detected -> claude rewrote the doc to match -> gate passed -> v2 written, created_at preserved.

Not in scope

No VFS routing for the docs memory subtree yet (CLI/worker only); no spec-layer correlation; per-agent doc-worker variants (codex/cursor/hermes/pi) follow the existing wiki-worker fork pattern.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added top-level hivemind docs CLI command with subcommands: set, show, list, archive, and refresh
    • Documentation can be anchored to code symbols to detect staleness and compute impacted docs
    • Opt-in automatic docs refresh after graph builds via HIVEMIND_DOCS_AUTO_REFRESH=1
    • LLM-assisted doc refresh with deterministic edit gating and versioned persistence
  • Chores

    • Added configurable docs table name support (HIVEMIND_DOCS_TABLE) and automatic table/schema/index setup

@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Coverage Report

Scope: files changed in this PR. Enforced threshold: 90% per metric (per file via vitest.config.ts).

Status Category Percentage Covered / Total
🔴 Lines 88.32% (🎯 90%) 1270 / 1438
🔴 Statements 88.07% (🎯 90%) 1439 / 1634
🟢 Functions 98.24% (🎯 90%) 167 / 170
🔴 Branches 80.82% (🎯 90%) 792 / 980
File Coverage — 17 files changed
File Stmts Branches Functions Lines
src/cli/index.ts 🔴 86.1% 🔴 84.6% 🟢 100.0% 🔴 83.7%
src/commands/docs.ts 🔴 82.8% 🔴 71.9% 🟢 93.8% 🔴 85.1%
src/commands/graph.ts 🔴 74.3% 🔴 62.9% 🟢 95.2% 🔴 73.9%
src/config.ts 🟢 100.0% 🟢 100.0% 🟢 100.0% 🟢 100.0%
src/deeplake-api.ts 🟢 99.0% 🔴 88.6% 🟢 100.0% 🟢 99.6%
src/deeplake-schema.ts 🟢 96.0% 🔴 84.8% 🟢 100.0% 🟢 95.2%
src/docs/anchors.ts 🟢 94.3% 🔴 89.3% 🟢 100.0% 🟢 100.0%
src/docs/auto-refresh-trigger.ts 🟢 100.0% 🔴 81.8% 🟢 100.0% 🟢 100.0%
src/docs/gate.ts 🟢 100.0% 🟢 100.0% 🟢 100.0% 🟢 100.0%
src/docs/impact.ts 🔴 87.3% 🔴 81.8% 🟢 100.0% 🟢 91.1%
src/docs/index.ts 🟢 100.0% 🟢 100.0% 🟢 100.0% 🟢 100.0%
src/docs/read.ts 🟢 100.0% 🔴 86.2% 🟢 100.0% 🟢 100.0%
src/docs/refresh-llm.ts 🟢 100.0% 🔴 85.7% 🟢 100.0% 🟢 100.0%
src/docs/refresh.ts 🟢 94.3% 🔴 77.3% 🟢 100.0% 🟢 100.0%
src/docs/write.ts 🟢 100.0% 🟢 100.0% 🟢 100.0% 🟢 100.0%
src/graph/load-current.ts 🟢 94.1% 🟢 100.0% 🟢 100.0% 🟢 92.8%
src/graph/render/impact.ts 🟢 92.2% 🔴 70.3% 🔴 87.5% 🟢 98.7%

Generated for commit 0d3ce23.

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6de0bf1f-e2e6-44e3-8406-5003ba55ac63

📥 Commits

Reviewing files that changed from the base of the PR and between 1de043e and 4b7ed15.

📒 Files selected for processing (6)
  • src/commands/docs.ts
  • src/docs/gate.ts
  • src/docs/refresh.ts
  • src/docs/write.ts
  • tests/shared/docs-refresh.test.ts
  • tests/shared/docs.test.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/docs/gate.ts
  • tests/shared/docs-refresh.test.ts
  • src/docs/refresh.ts
  • tests/shared/docs.test.ts
  • src/docs/write.ts
  • src/commands/docs.ts

📝 Walkthrough

Walkthrough

Adds a complete hivemind docs subsystem: docs storage and schema, source-anchor tracking, drift and impact detection, refresh gating and LLM orchestration, CLI subcommands, and an optional post-build docs refresh trigger.

Changes

hivemind docs subsystem

Layer / File(s) Summary
Schema, config, and DB provisioning
src/deeplake-schema.ts, src/config.ts, src/deeplake-api.ts, tests/shared/deeplake-api.test.ts, tests/claude-code/flush-memory*.test.ts, tests/claude-code/skillify-auto-pull.test.ts, tests/claude-code/spawn-wiki-worker.test.ts, tests/shared/graph/deeplake-p*.test.ts
Adds DOCS_COLUMNS, docsTableName in config, ensureDocsTable, and fixture updates for the new table name.
Docs read/write API
src/docs/read.ts, src/docs/write.ts, src/docs/index.ts, tests/shared/docs.test.ts
Adds typed read helpers, versioned INSERT-only write helpers, barrel exports, and tests for SQL shape, versioning, filtering, and anchor parsing.
Anchor tracking and local snapshot loading
src/docs/anchors.ts, src/graph/load-current.ts, src/graph/render/impact.ts, tests/shared/docs-impact.test.ts, tests/shared/graph/load-current.test.ts
Adds source-location parsing, slice hashing, anchor status checks, local snapshot loading, and reverse-edge traversal helpers, with tests for parsing, hashing, anchor states, and snapshot loading.
Doc drift detection and impact computation
src/docs/impact.ts, tests/shared/docs-impact.test.ts
Adds direct stale-doc detection, blast-radius widening, and combined impacted-doc computation with tests for direct and relational staleness.
Edit gate and refresh orchestration
src/docs/gate.ts, src/docs/refresh.ts, src/docs/refresh-llm.ts, src/docs/auto-refresh-trigger.ts, tests/shared/docs-refresh.test.ts, tests/shared/docs-refresh-llm.test.ts, tests/shared/docs-auto-refresh-trigger.test.ts
Adds changed-line counting, edit gating, refresh prompt building, LLM-backed refresh generation, refresh orchestration, and the optional detached refresh trigger.
CLI routing and graph build hook
src/cli/index.ts, src/commands/docs.ts, src/commands/graph.ts, tests/claude-code/cli-docs.test.ts
Adds the hivemind docs command with five subcommands, wires it into the CLI, and adds the graph post-build refresh trigger. Tests cover dispatch, subcommands, and refresh integration.

Sequence Diagrams

sequenceDiagram
  actor User
  participant CLI as hivemind docs refresh
  participant loadCurrentSnapshot
  participant listDocs
  participant computeImpactedDocs
  participant ensureDocsTable
  participant refreshDocs
  participant makeClaudeGenerate as Claude CLI
  participant gateDocEdit
  participant setDoc as setDoc (Deeplake)

  User->>CLI: docs refresh [--dry-run]
  CLI->>loadCurrentSnapshot: load local graph snapshot
  CLI->>listDocs: fetch active docs
  CLI->>computeImpactedDocs: detect stale docs via anchors + blast radius
  alt --dry-run
    CLI-->>User: print impacted docs, no writes
  else live run
    CLI->>ensureDocsTable: create/heal docs table
    CLI->>refreshDocs: iterate impacted docs
    refreshDocs->>makeClaudeGenerate: buildRefreshPrompt + execFileSync(claude)
    makeClaudeGenerate-->>refreshDocs: proposed markdown
    refreshDocs->>gateDocEdit: validate (tier, size, anchors)
    alt gate pass
      refreshDocs->>setDoc: persist new version
      setDoc-->>refreshDocs: WriteResult
    else gate fail
      refreshDocs-->>refreshDocs: record rejected
    end
    refreshDocs-->>CLI: RefreshReport
    CLI-->>User: print refreshed/rejected/skipped counts
  end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • activeloopai/hivemind#192: Extends the graph build and snapshot flow in src/commands/graph.ts, which this PR hooks with the optional post-build docs refresh trigger.

Suggested reviewers

  • kaghni

Poem

🐇 Hop, hop — the docs now breathe,
Anchors hashed with SHA beneath.
A rabbit taps the CLI drum,
Refresh drifts in when builds are done.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is informative, but it does not follow the required template and omits the Version Bump section and checklist-style Test plan. Rewrite it into the repo template with Summary, Version Bump, and Test plan sections, including whether package.json was bumped and the local test status.
Docstring Coverage ⚠️ Warning Docstring coverage is 61.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: a doc freshness layer with drift detection and refresh.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/knowledge-base-docs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot requested a review from khustup2 June 23, 2026 16:55

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (4)
tests/shared/docs-impact.test.ts (1)

133-138: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the full changed payload, not just state.

This test currently verifies only the discriminator and misses regressions in from/to values.

✅ Proposed assertion tightening
   it("changed when the code differs from the stored hash", () => {
     const n = node("a.ts:foo:function", "a.ts", "L1-L2");
     const stale: DocAnchor = { symbol_id: n.id, content_hash: "deadbeef" };
     const st = anchorStatus(stale, snap([n]), dir);
-    expect(st.state).toBe("changed");
+    expect(st).toEqual({
+      state: "changed",
+      from: "deadbeef",
+      to: sha("function foo() {\n  return 1;"),
+    });
   });

As per path instructions, tests/**: Prefer asserting on specific values (paths, messages) over generic substrings.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/shared/docs-impact.test.ts` around lines 133 - 138, The test for the
"changed when the code differs from the stored hash" case is only asserting on
the state property of the anchorStatus result, but it should verify the complete
changed payload including the from and to values. Replace the single assertion
on st.state with a comprehensive assertion that checks the full object structure
returned by anchorStatus to catch potential regressions in the from and to
fields.

Source: Path instructions

tests/shared/graph/load-current.test.ts (1)

54-58: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Make the fallback test assert concrete snapshot content.

not.toBeNull() is broad here; assert the expected nodes/links payload directly.

✅ Proposed assertion tightening
   it("falls back to snapshot_sha256 when there is no commit context", () => {
     writeLastBuild(cwd, { ts: 1, commit_sha: null, snapshot_sha256: "feedface" });
     writeSnapshotFile(cwd, "feedface", JSON.stringify({ nodes: [], links: [] }));
-    expect(loadCurrentSnapshot(cwd)).not.toBeNull();
+    expect(loadCurrentSnapshot(cwd)).toEqual({ nodes: [], links: [] });
   });

As per path instructions, tests/**: Prefer asserting on specific values (paths, messages) over generic substrings.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/shared/graph/load-current.test.ts` around lines 54 - 58, The test
assertion in the "falls back to snapshot_sha256 when there is no commit context"
test is too broad. Instead of using
expect(loadCurrentSnapshot(cwd)).not.toBeNull(), replace it with a specific
assertion that validates the returned snapshot object contains the expected
concrete values for the nodes and links properties that were written to the
snapshot file using writeSnapshotFile. This ensures the function correctly loads
and returns the actual snapshot payload rather than just checking it exists.

Source: Path instructions

tests/claude-code/cli-docs.test.ts (1)

87-223: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Tighten assertions to exact expected messages/values instead of generic substrings.

A large part of this suite validates only partial output via regex substring matches. Switching key checks to exact strings (or structured fields) will make these CLI contract tests significantly more robust.

As per path instructions, tests/**: Prefer asserting on specific values (paths, messages) over generic substrings.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/claude-code/cli-docs.test.ts` around lines 87 - 223, Replace generic
regex substring matching assertions with exact string or structured value checks
throughout the test suite. Instead of using toMatch() with broad regex patterns
like /hivemind docs/ or /Not logged in/, use toContain() for exact string
matches or direct equality checks for specific values. Apply this to key test
cases such as "prints usage with no subcommand", "exits 2 when not logged in",
"creates v1 via the real store", "prints (no doc) when nothing matches", "lists
rows", "archives an existing doc", and other test assertions that currently rely
on partial pattern matching to make the CLI contract tests more precise and
robust.

Source: Path instructions

tests/shared/docs.test.ts (1)

129-159: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use exact error-message assertions for failure paths.

Several rejection tests currently assert generic substrings (or just toThrow()), which weakens contract checks. Prefer exact message assertions for these cases.

✅ Example tightening
-    ).rejects.toThrow(/must not be empty/);
+    ).rejects.toThrow("Doc content must not be empty");
@@
-    ).rejects.toThrow(/doc_id must not be empty/);
+    ).rejects.toThrow("Doc doc_id must not be empty");
@@
-    ).rejects.toThrow(/Doc not found: missing.ts/);
+    ).rejects.toThrow("Doc not found: missing.ts");
@@
-    await expect(
-      insertDoc(query, `x"; DROP TABLE y; --`, { doc_id: "a.ts", path: "/p", content: "x" }),
-    ).rejects.toThrow();
+    await expect(
+      insertDoc(query, `x"; DROP TABLE y; --`, { doc_id: "a.ts", path: "/p", content: "x" }),
+    ).rejects.toThrow(`Invalid SQL identifier: "x\\"; DROP TABLE y; --"`);

As per path instructions, tests/**: “Prefer asserting on specific values (paths, messages) over generic substrings.”

Also applies to: 212-227, 290-293

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/shared/docs.test.ts` around lines 129 - 159, The rejection tests in
this section use generic error assertions that are too permissive. Replace the
regex substring matches in the tests "rejects empty content", "rejects empty
doc_id", and "rejects content longer than" with exact error message strings
instead of regex patterns like /must not be empty/ and /exceeds 50000 chars/.
For the "rejects SQL-identifier injection in the table name" test, replace the
generic toThrow() with a specific error message assertion to ensure the exact
failure mode is being tested. This tightens the contract checks to verify
precise error messages rather than loose substring matches.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/commands/docs.ts`:
- Around line 195-196: The resolveContent() function can throw exceptions when
provided with invalid file paths or unreadable stdin, but it is currently
executed before the try/catch block at line 195, allowing uncaught exceptions to
terminate the command abruptly. Move the resolveContent() function call (and any
dependent code that uses its result) inside the existing try/catch error handler
to ensure failures are caught and handled as controlled CLI errors instead of
uncaught exceptions.

In `@src/docs/gate.ts`:
- Around line 79-87: The countChangedLines function call on line 80 performs an
expensive O(n*m) LCS diff operation before validating the content size
constraints, which means very large inputs consume significant CPU even though
they will be rejected by the GATE_MAX_CONTENT_LENGTH check. Move the content
validation checks (the empty content check and the GATE_MAX_CONTENT_LENGTH
check) to execute before the countChangedLines call so that oversized proposals
are rejected before the quadratic diff algorithm runs. This applies to the
countChangedLines call and the subsequent size validation checks in the reasons
array population section.

In `@src/docs/refresh.ts`:
- Around line 147-153: The code invokes args.generate() without first checking
if the document should be rejected as a slow-tier doc via gateDocEdit, which
unnecessarily leaks protected content to the LLM and incurs avoidable costs.
Move the gateDocEdit check before the args.generate() call so that slow-tier
documents are rejected without ever being sent to the generate function,
preventing unnecessary LLM invocations and content exposure.

In `@src/docs/write.ts`:
- Around line 56-57: The SetDocInput.project field is currently being ignored
during version bumps when a document already exists. In the setDoc function, the
project value from SetDocInput is dropped and appendVersion always uses the
previous project value instead of the new one provided. To fix this, propagate
the project value from SetDocInput through the setDoc function and pass it as a
parameter to appendVersion so it uses the new project value (when provided)
instead of always defaulting to previous.project. This will enable proper
project reassignment and prevent stale metadata from affecting listDocs
filtering.

In `@src/graph/render/impact.ts`:
- Around line 24-27: The reverse traversal logic for collecting impacted nodes
is currently processing all relations but should be restricted to dependency
relations only as documented in the comments. Update the traversal in the
impactedNodes collection section (around lines 41-45) to filter and process only
the dependency-related edges: calls, imports, extends, implements, and
method_of. Remove or skip any other relation types that are not part of the
dependency graph to prevent over-expansion of the closure and avoid marking
unrelated documents as impacted.

In `@tests/shared/docs-refresh.test.ts`:
- Line 81: The test assertions in this file use `.join().toMatch()` with regex
patterns to broadly match substring content in the reasons array, which can hide
incorrect reason values. Replace these broad substring checks with direct
assertions on the specific reason values. Instead of joining and using regex
matching on r.reasons, assert the exact expected reason value directly using
methods like toContain() or by checking specific array indices with toBe().
Apply this fix to all occurrences at lines 81, 87, 92, 97, 103, 180, and 214.

---

Nitpick comments:
In `@tests/claude-code/cli-docs.test.ts`:
- Around line 87-223: Replace generic regex substring matching assertions with
exact string or structured value checks throughout the test suite. Instead of
using toMatch() with broad regex patterns like /hivemind docs/ or /Not logged
in/, use toContain() for exact string matches or direct equality checks for
specific values. Apply this to key test cases such as "prints usage with no
subcommand", "exits 2 when not logged in", "creates v1 via the real store",
"prints (no doc) when nothing matches", "lists rows", "archives an existing
doc", and other test assertions that currently rely on partial pattern matching
to make the CLI contract tests more precise and robust.

In `@tests/shared/docs-impact.test.ts`:
- Around line 133-138: The test for the "changed when the code differs from the
stored hash" case is only asserting on the state property of the anchorStatus
result, but it should verify the complete changed payload including the from and
to values. Replace the single assertion on st.state with a comprehensive
assertion that checks the full object structure returned by anchorStatus to
catch potential regressions in the from and to fields.

In `@tests/shared/docs.test.ts`:
- Around line 129-159: The rejection tests in this section use generic error
assertions that are too permissive. Replace the regex substring matches in the
tests "rejects empty content", "rejects empty doc_id", and "rejects content
longer than" with exact error message strings instead of regex patterns like
/must not be empty/ and /exceeds 50000 chars/. For the "rejects SQL-identifier
injection in the table name" test, replace the generic toThrow() with a specific
error message assertion to ensure the exact failure mode is being tested. This
tightens the contract checks to verify precise error messages rather than loose
substring matches.

In `@tests/shared/graph/load-current.test.ts`:
- Around line 54-58: The test assertion in the "falls back to snapshot_sha256
when there is no commit context" test is too broad. Instead of using
expect(loadCurrentSnapshot(cwd)).not.toBeNull(), replace it with a specific
assertion that validates the returned snapshot object contains the expected
concrete values for the nodes and links properties that were written to the
snapshot file using writeSnapshotFile. This ensures the function correctly loads
and returns the actual snapshot payload rather than just checking it exists.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6517aef1-95e4-4670-9211-446883525e7a

📥 Commits

Reviewing files that changed from the base of the PR and between 9f7077a and 1de043e.

📒 Files selected for processing (31)
  • src/cli/index.ts
  • src/commands/docs.ts
  • src/commands/graph.ts
  • src/config.ts
  • src/deeplake-api.ts
  • src/deeplake-schema.ts
  • src/docs/anchors.ts
  • src/docs/auto-refresh-trigger.ts
  • src/docs/gate.ts
  • src/docs/impact.ts
  • src/docs/index.ts
  • src/docs/read.ts
  • src/docs/refresh-llm.ts
  • src/docs/refresh.ts
  • src/docs/write.ts
  • src/graph/load-current.ts
  • src/graph/render/impact.ts
  • tests/claude-code/cli-docs.test.ts
  • tests/claude-code/flush-memory-wiring.test.ts
  • tests/claude-code/flush-memory.test.ts
  • tests/claude-code/skillify-auto-pull.test.ts
  • tests/claude-code/spawn-wiki-worker.test.ts
  • tests/shared/deeplake-api.test.ts
  • tests/shared/docs-auto-refresh-trigger.test.ts
  • tests/shared/docs-impact.test.ts
  • tests/shared/docs-refresh-llm.test.ts
  • tests/shared/docs-refresh.test.ts
  • tests/shared/docs.test.ts
  • tests/shared/graph/deeplake-pull.test.ts
  • tests/shared/graph/deeplake-push.test.ts
  • tests/shared/graph/load-current.test.ts

Comment thread src/commands/docs.ts Outdated
Comment thread src/docs/gate.ts
Comment thread src/docs/refresh.ts
Comment thread src/docs/write.ts
Comment thread src/graph/render/impact.ts
it("rejects empty content", () => {
const r = gateDocEdit({ tier: "fast", prevContent: "x", newContent: "", newAnchors: [], snap: s });
expect(r.ok).toBe(false);
expect(r.reasons.join()).toMatch(/empty/);

@coderabbitai coderabbitai Bot Jun 23, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use exact reason assertions instead of join()+regex checks.

These assertions are currently broad substring matches, which can hide wrong reason text. Assert specific reason values directly.

✅ Suggested assertion style
- expect(r.reasons.join()).toMatch(/empty/);
+ expect(r.reasons).toContain("proposed content is empty");

- expect(r.reasons.join()).toMatch(/slow-tier/);
+ expect(r.reasons).toContain("slow-tier docs are human-curated; automatic refresh is not allowed");

- expect(report.outcomes[0].reasons?.join()).toMatch(/LLM down/);
+ expect(report.outcomes[0].reasons).toContain("generate failed: LLM down");

As per path instructions, tests/**: Prefer asserting on specific values (paths, messages) over generic substrings.

Also applies to: 87-87, 92-92, 97-97, 103-103, 180-180, 214-214

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/shared/docs-refresh.test.ts` at line 81, The test assertions in this
file use `.join().toMatch()` with regex patterns to broadly match substring
content in the reasons array, which can hide incorrect reason values. Replace
these broad substring checks with direct assertions on the specific reason
values. Instead of joining and using regex matching on r.reasons, assert the
exact expected reason value directly using methods like toContain() or by
checking specific array indices with toBe(). Apply this fix to all occurrences
at lines 81, 87, 92, 97, 103, 180, and 214.

Source: Path instructions

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style nit, not a correctness gap — the join()+regex assertions do verify the exact reason text. Leaving the existing assertions; will tighten to exact-array matches if we touch these tests again.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@efenocchi Fair enough — the regex patterns are tight enough that the exact text is effectively verified. Noted; happy to revisit when those tests are next modified.

ʕ •`ᴥ•´ʔ

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant