Skip to content

feat: v0.3.0 — agent integration foundation (schema + exports)#39

Open
jnahian wants to merge 35 commits into
mainfrom
feat/v0.3-agent-integration
Open

feat: v0.3.0 — agent integration foundation (schema + exports)#39
jnahian wants to merge 35 commits into
mainfrom
feat/v0.3-agent-integration

Conversation

@jnahian

@jnahian jnahian commented May 16, 2026

Copy link
Copy Markdown
Owner

Summary

Ships v0.3.0 with two major capabilities plus the previously-drafted search feature, all merged into one release.

1. Agent integration foundation (17-task plan executed via subagent-driven development from docs/superpowers/plans/2026-05-15-agent-integration-v0.3-schema-and-exports.md):

  • Structured note schema — optional type (context/instruction/warning/decision/todo/handoff/rationale), priority (low/normal/high/critical), scope, tags, expiresAt, authorType, references. All optional; legacy v0.2.x notes load with defaults applied at the NoteManager boundary (single lazy-migration point).
  • Auto-generated workspace exports.code-notes/INDEX.json (machine-readable, deterministic, with byFile/byType/byTag lookups) and .code-notes/AGENTS.md (human-readable digest hoisting instructions/warnings/handoffs/decisions). Debounced 200ms atomic writes on every note change.
  • Sidebar enhancements — type description suffix, priority tooltip badge, Quick-Pick type filter, expired-notes toggle.
  • New commandsRegenerate Exports, Set Note Type / Tags / Priority…, Filter Notes by Type…, Toggle Expired Notes.
  • New settingscodeContextNotes.exports.{enabled,indexJson,agentsMarkdown}.

2. Search and Filter (deferred): review verification found the search UI (commands, keybinding, settings, searchUI.ts) was silently dropped in an earlier merge — only the SearchManager backend reached main. Rather than double this PR's surface, search claims were removed from the changelogs; the UI ships in a follow-up release (Issue #10 stays open).

Architecture decisions

  • Storage format extended with new bold-label fields (**Type:** …, etc.) rather than introducing YAML frontmatter. Fields equal to default are omitted, so untouched legacy notes remain byte-identical on disk.
  • ExportWriter accepts an injectable getConfig so its unit tests run without the VS Code host.
  • Two explicit deferrals to v0.4 (called out in the plan's self-review): directory-scope resolution and INDEX.json.errors[] population — both belong with the MCP server work.

Test plan

  • npm run compile:tsc — clean
  • npm run compile (esbuild) — clean
  • npm run test:unit — 60/60 passing (5 noteDefaults + 6 exportGenerator + 3 exportWriter + 3 storage parser + 2 storage writer)
  • npm run package:dev — produces code-context-notes-0.3.0.vsix (95 KB)
  • cd web && npm run build:client — clean
  • Manual smoke: install vsix in clean workspace, create note, verify .code-notes/INDEX.json + AGENTS.md appear within ~250ms
  • Manual smoke: run Set Note Type / Tags / Priority… → set type=instruction, priority=high → verify hoisted to "Critical instructions and warnings" in AGENTS.md
  • Manual smoke: run Filter Notes by Type → pick instruction → sidebar filters correctly
  • Manual smoke: open existing v0.2.x workspace → verify legacy notes still load and display

Manual smoke tests verified 2026-07-16 by driving the extension in a real VS Code extension host (@vscode/test-electron): exports appeared 206ms after activation and 298ms after note creation; instruction/high note hoisted to "Critical instructions and warnings"; type filter and expired-notes toggle verified against the live sidebar tree provider; legacy note loaded with defaults and its on-disk file stayed byte-identical. (Ran the dev-extension path rather than installing the vsix; npm run package:dev builds it cleanly.)

Docs

  • docs/changelogs/v0.3.0.md — merged changelog
  • docs/superpowers/specs/2026-05-15-agent-integration-design.md — full design spec across v0.3/v0.4/v0.5
  • docs/superpowers/plans/2026-05-15-agent-integration-v0.3-schema-and-exports.md — implementation plan
  • README.md — exports + .gitignore guidance section
  • web/src/pages/ChangelogPage.tsx — v0.3.0 timeline entry

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Extended note metadata: type, priority, scope, tags, expiry date, author type, and references
    • Auto-generated exports in .code-notes/: INDEX.json (for integrations) and AGENTS.md (agent digest)
    • Sidebar enhancements: type display, filtering by type, and expired note toggle
    • New commands for managing exports and note metadata
    • Configurable export generation via settings
  • Documentation

    • Updated README with export documentation and gitignore guidance
    • Completed v0.3.0 changelog with feature details

Review Change Stack

Review fixes (2026-07-16)

Applied after CodeRabbit/Copilot review + live verification:

  • updateNoteMetadata: rejects soft-deleted notes, syncs the search index, caches defaults-applied notes (cache entry points now normalize via applyDefaults)
  • Sidebar: filters apply to file groups and the root count (no more hollow file nodes); filterByType/toggleExpired guarded for no-workspace mode
  • Exports: hooks always attached so exports.enabled toggles both ways without reload; external note-file changes (git pull) regenerate exports; AGENTS.md watcher self-trigger loop guarded; unique temp names for atomic writes; manual regenerate reports disabled/failed states honestly; INDEX.json.contentPath honors codeContextNotes.storageDirectory
  • Storage parser validates structured-field values (invalid type/scope/priority/authorType dropped; malformed references filtered)
  • package-lock.json synced to 0.3.0; stale hardcoded version log removed; docs nits (fence languages, spec frontmatter wording, README determinism caveat, stale web "Coming in v0.3.0" section)

jnahian and others added 20 commits May 15, 2026 13:11
Documents the web/ commands, the three SSR runtimes (Vite dev,
Express, Vercel serverless), and points at the existing changelog
guide and skill rather than duplicating instructions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three-stage rollout (v0.3 schema+exports, v0.4 MCP server, v0.5 trust
model + audit UI) for making notes a first-class context source for
coding agents — read+write loop, full structured schema, configurable
agent-write trust mode.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
17 bite-sized TDD tasks covering: structured Note schema (type, scope,
tags, priority, references, expiry, authorType), debounced atomic
INDEX.json + AGENTS.md generation, sidebar type filter, configuration
settings, changelog and version bump.

Notes two deviations from spec discovered during planning: existing
storage is bold-label markdown (not YAML frontmatter) and the layout
is flat (.code-notes/<id>.md). Plan extends both rather than fighting
them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds optional NoteType, NoteScope, NoteReference, AuthorType, NotePriority
fields. All optional for backward compatibility — defaults applied on read
in a follow-up task.
Lazily fills missing optional Note fields in memory. The on-disk file
is unchanged until the note is next saved (lazy migration).
Extends markdownToNote to read Type/Scope/Priority/Tags/AuthorType/
ExpiresAt/References. Legacy notes without these fields parse exactly
as before (fields remain undefined; defaults applied at NoteManager
boundary in a follow-up task).
Extends noteToMarkdown to write Type/Scope/Priority/Tags/AuthorType/
ExpiresAt/References. Fields equal to their default are omitted to
keep frontmatter compact for the common case (untouched legacy notes
remain shape-identical after a save).
Notes leaving NoteManager always have optional fields populated. Legacy
notes get defaults in memory; on-disk file unchanged until next save.
This is the single boundary where lazy migration happens.
Pure functions buildIndex(notes, workspaceRoot) and buildDigest(notes,
workspaceRoot). Deterministic output for the same input. No I/O —
called by exportWriter.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Owns the 200ms debounce timer for note-write bursts and the
write-temp-then-rename atomic-write logic. Failures route through
onError so a disk-full event never blocks note saves.
Hooks ExportWriter to NoteManager's noteChanged event. Initial export
runs on activation. Disabled when codeContextNotes.exports.enabled is
false.
Lets users force a fresh INDEX.json/AGENTS.md, e.g. after a disk-full
recovery or a manual delete from the storage directory.
Three booleans: enabled (master switch), indexJson, agentsMarkdown.
All default true. Read on every regeneration so toggling takes effect
without reload.
Append · {type} to NoteTreeItem.description for non-context types,
and prepend [priority] to the tooltip for high/critical notes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New title-bar actions: filter by type (multi-select Quick Pick) and
toggle expired-note visibility. Default hides expired notes.
Quick Pick driven flow: codeContextNotes.setNoteMetadata. Lets users
enrich notes after creation. Future v0.5 work will inline this in the
add/edit comment thread UI; this command unblocks v0.3 use cases.
Combines the previously drafted Search and Filter feature changelog with
the new agent-integration features (structured schema, INDEX.json/AGENTS.md
exports, sidebar enhancements). Both ship as v0.3.0.
Copilot AI review requested due to automatic review settings May 16, 2026 16:50
@vercel

vercel Bot commented May 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
code-context-notes Ready Ready Preview, Comment Jul 16, 2026 6:26pm

@coderabbitai

coderabbitai Bot commented May 16, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR implements v0.3.0 of Code Context Notes, introducing structured note metadata (type, scope, tags, references, expiry, priority, author type) with corresponding defaults, automatic generation of INDEX.json and AGENTS.md export files via debounced atomic writes, new sidebar filtering commands, extended storage serialization, and comprehensive testing and documentation.

Changes

Schema Extension and Export Generation (v0.3.0)

Layer / File(s) Summary
Note schema with metadata types
src/types.ts
Introduces NoteType, NoteScope, AuthorType, NotePriority union types and NoteReference interface; extends Note interface with optional metadata fields for classification and ordering.
Default handling and expiry utilities
src/noteDefaults.ts, src/test/suite/noteDefaults.test.ts
Provides NOTE_DEFAULTS constant, applyDefaults() to populate missing metadata without mutation, and isExpired() to check expiration; unit tests validate default application and expiry logic across undefined/past/future timestamps.
Export generation functions
src/exportGenerator.ts, src/test/suite/exportGenerator.test.ts
Implements buildIndex() and buildDigest() pure functions that generate deterministic INDEX.json and AGENTS.md from notes with defaults applied, expiration filtering, and priority-ranked ordering; tests verify versioning, indexing, determinism, and digest structure.
ExportWriter with debounced atomic writes
src/exportWriter.ts, src/test/suite/exportWriter.test.ts
Implements ExportWriter class that debounces regeneration, gates writes via config callback, and writes atomically via temp+rename; tests cover successful writes, debounce coalescing, and error handling.
Storage parsing and serialization of metadata
src/storageManager.ts, src/test/suite/storageManager.test.ts
Extends StorageManager to parse/write structured metadata fields (Type, Scope, Priority, Tags, AuthorType, ExpiresAt, References) with JSON error handling and field omission for defaults; tests verify field recognition, legacy compatibility, and default omission.
NoteManager applies defaults at load boundary
src/noteManager.ts, src/test/suite/noteManager.test.ts
Updates NoteManager to apply defaults when loading notes via applyDefaults, adds updateNoteMetadata() method, and ensures all returned notes have populated defaults; integration test verifies legacy notes receive correct defaults.
Extension configuration and command registration
package.json, src/extension.ts
Adds VS Code commands (regenerateExports, filterByType, toggleExpired, setNoteMetadata) and configuration properties under codeContextNotes.exports.*; initializes ExportWriter during activation with config gating and wires regeneration to noteChanged events.
Sidebar type display and filtering
src/noteTreeItem.ts, src/notesSidebarProvider.ts
Updates NoteTreeItem to display note type and priority in sidebar; adds setTypeFilter() and toggleHideExpired() methods to NotesSidebarProvider for dynamic sidebar filtering and expiry hiding.
Unit test runner configuration
src/test/runUnitTests.ts
Updates test runner to include new unit test files (noteDefaults, exportGenerator, exportWriter).
Core documentation
README.md, web/CLAUDE.md
Adds README section on auto-generated exports and gitignore guidance; creates web project guide documenting SSR architecture, scripts, routes, and changelog maintenance.
Implementation plan and design specification
docs/superpowers/plans/2026-05-15-agent-integration-v0.3-schema-and-exports.md, docs/superpowers/specs/2026-05-15-agent-integration-design.md
Provides detailed implementation plan for all v0.3 workstreams and comprehensive multi-part design specification covering schema, exports, v0.4/v0.5 roadmap (MCP, trust model), migration strategy, error handling, and multi-package testing.
Release notes and web changelog
docs/changelogs/v0.3.0.md, web/src/pages/ChangelogPage.tsx
Completes v0.3.0 changelog with schema/exports/sidebar/settings details; updates web changelog page to display v0.3.0 as latest with Added/Technical/Coming-next sections.

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 A rabbit's note on v0.3:
Metadata now flourishes in our markdown beds,
INDEX and AGENTS bloom with every keystroke spread,
Defaults gently fill the missing threads,
While sidebar filters hop through note-type heads! 🌱✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 54.55% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: shipping v0.3.0 with agent integration foundation (schema + exports) as the primary feature, with search mentioned as an additional capability.
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/v0.3-agent-integration

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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 and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/src/pages/ChangelogPage.tsx (1)

763-808: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove or update the stale "Coming in v0.3.0" section.

This section describes features that are now released in v0.3.0 (displayed at the top with the "Latest" badge). The outdated future-looking content creates confusion for users visiting the changelog.

Recommended action: Remove lines 763-808 entirely, since the search features are already documented in the v0.3.0 entry above.

Alternative: Update to "Coming in v0.4.0" with the MCP server content mentioned in the markdown changelog's "Coming Next" section.

🗑️ Proposed fix: Remove the stale section
-          {/* Future Versions Note */}
-          <div className="relative grid grid-cols-1 md:grid-cols-[30%_70%] gap-8 items-start">
-            {/* Timeline Node - Future */}
-            <div className="absolute left-0 md:left-[30%] transform -translate-x-1/2 top-2">
-              <div className="w-4 h-4 rounded-full bg-purple-500 border-4 border-white dark:border-slate-900 shadow-lg animate-pulse"></div>
-            </div>
-
-            {/* Left Column - Version Info */}
-            <div className="pl-8 md:pl-0 md:pr-12 text-left md:text-right space-y-2">
-              <h3 className="text-2xl font-bold text-purple-600">Coming in v0.3.0</h3>
-              <div className="flex items-center gap-2 text-muted-foreground text-sm md:justify-end">
-                <Search className="h-4 w-4" />
-                <span>Future Release</span>
-              </div>
-              <p className="text-sm text-muted-foreground">
-                What's next for Code Context Notes
-              </p>
-            </div>
-
-            {/* Right Column - Changes */}
-            <div className="pl-8 md:pl-12">
-          <Card className="bg-gradient-to-br from-purple-50 to-pink-50 dark:from-purple-950 dark:to-pink-950 border-2 border-purple-300 shadow-brand-drop">
-            <CardContent>
-              <div className="space-y-2 text-sm text-muted-foreground">
-                <div className="flex items-start space-x-2">
-                  <span className="text-purple-500 font-bold">→</span>
-                  <span>
-                    <strong>Search and Filter Notes</strong> - Full-text search across all note content with filters by author, date range, and file path
-                  </span>
-                </div>
-                <div className="flex items-start space-x-2">
-                  <span className="text-purple-500 font-bold">→</span>
-                  <span>
-                    <strong>Regex Pattern Matching</strong> - Advanced search capabilities for power users
-                  </span>
-                </div>
-                <div className="flex items-start space-x-2">
-                  <span className="text-purple-500 font-bold">→</span>
-                  <span>
-                    <strong>Background Indexing</strong> - Instant search results with automatic index updates
-                  </span>
-                </div>
-              </div>
-            </CardContent>
-          </Card>
-            </div>
-          </div>
-
🤖 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 `@web/src/pages/ChangelogPage.tsx` around lines 763 - 808, The JSX block
rendering the stale "Coming in v0.3.0" timeline card should be removed (or
updated) — remove the entire section that includes the timeline node div, the h3
with text "Coming in v0.3.0", the Search icon usage, and the Card / CardContent
that lists "Search and Filter Notes", "Regex Pattern Matching", and "Background
Indexing"; alternatively, if you prefer to keep a future section, change the h3
to "Coming in v0.4.0" and replace the inner card contents with the MCP server
notes from the markdown "Coming Next" section so it no longer duplicates already
released v0.3.0 features.
🧹 Nitpick comments (7)
docs/superpowers/specs/2026-05-15-agent-integration-design.md (1)

133-134: ⚡ Quick win

Align storage format/path statements with the implemented v0.3 contract.

This spec still describes YAML frontmatter and nested note paths, while the v0.3 plan in this PR defines bold-label markdown and flat .code-notes/<id>.md. Please normalize these sections to one canonical storage contract to avoid implementation drift in v0.4+ workstreams.

Also applies to: 176-177, 317-317, 483-509

🤖 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 `@docs/superpowers/specs/2026-05-15-agent-integration-design.md` around lines
133 - 134, The spec currently describes YAML frontmatter and nested note paths
but must be updated to match the implemented v0.3 contract: replace any
"Storage:" or frontmatter descriptions that reference YAML frontmatter and
nested note paths with the canonical v0.3 description (bold-label markdown
in-document metadata and flat storage under .code-notes/<id>.md), and normalize
all occurrences (including the regions noted around lines 176-177, 317, and
483-509) so the document consistently specifies bold-label markdown metadata and
the flat .code-notes/<id>.md path contract.
src/test/runUnitTests.ts (1)

35-39: ⚡ Quick win

Refactor the test file filter to use an array for better maintainability.

The boolean chain with 5 OR conditions is becoming difficult to maintain. Consider using an array with .includes() for cleaner code that's easier to extend when adding new test files.

♻️ Proposed refactoring
 // Filter to only pure unit tests (no vscode dependency)
+const pureUnitTests = [
+  'storageManager.test.js',
+  'gitIntegration.test.js',
+  'noteDefaults.test.js',
+  'exportGenerator.test.js',
+  'exportWriter.test.js'
+];
+
 const unitTestFiles = files.filter(f => {
   const basename = path.basename(f);
-  // Only include tests that don't require vscode
-  return basename === 'storageManager.test.js' || basename === 'gitIntegration.test.js' || basename === 'noteDefaults.test.js' || basename === 'exportGenerator.test.js' || basename === 'exportWriter.test.js';
+  return pureUnitTests.includes(basename);
 });
🤖 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 `@src/test/runUnitTests.ts` around lines 35 - 39, The unitTestFiles filter uses
a long boolean OR chain which is hard to maintain; refactor the files.filter
callback in runUnitTests.ts to compute basename via path.basename(f), then test
membership against an array of allowed test file names (e.g., const allowed =
['storageManager.test.js','gitIntegration.test.js','noteDefaults.test.js','exportGenerator.test.js','exportWriter.test.js'])
and return allowed.includes(basename) inside the files.filter callback so
adding/removing tests becomes a simple array change (update references to
unitTestFiles and the files.filter callback).
README.md (1)

367-368: ⚡ Quick win

Consider clarifying the regeneration timing.

The phrase "on every note change" might suggest immediate regeneration, but the PR objectives indicate a 200ms debounce is in place. Consider adding "automatically" or "debounced" to clarify the behavior for users who make rapid successive changes.

✍️ Possible clarification
-When auto-exports are enabled, two files are regenerated in `.code-notes/`
-on every note change:
+When auto-exports are enabled, two files are automatically regenerated in `.code-notes/`
+whenever notes change:
🤖 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 `@README.md` around lines 367 - 368, Update the README sentence that currently
reads "When auto-exports are enabled, two files are regenerated in
`.code-notes/` on every note change:" to clarify the timing: mention that
regeneration is automatic but debounced (200ms). For example, change it to state
that files are regenerated automatically on note changes and add "(debounced by
200ms)" so users understand rapid successive edits won't trigger immediate
repeated writes; edit the same sentence in README to include that debounced
timing.
src/storageManager.ts (1)

214-235: ⚡ Quick win

Use shared defaults when deciding whether to omit structured fields.

These comparisons hardcode default literals (context, line, normal, human). Pull from NOTE_DEFAULTS so serialization behavior can’t drift if defaults change later.

Proposed diff
 import { Note, NoteStorage, NoteMetadata } from './types.js';
+import { NOTE_DEFAULTS } from './noteDefaults.js';
@@
-    if (note.type && note.type !== 'context') {
+    if (note.type && note.type !== NOTE_DEFAULTS.type) {
       lines.push(`**Type:** ${note.type}`);
     }
-    if (note.scope && note.scope !== 'line') {
+    if (note.scope && note.scope !== NOTE_DEFAULTS.scope) {
       lines.push(`**Scope:** ${note.scope}`);
     }
-    if (note.priority && note.priority !== 'normal') {
+    if (note.priority && note.priority !== NOTE_DEFAULTS.priority) {
       lines.push(`**Priority:** ${note.priority}`);
     }
@@
-    if (note.authorType && note.authorType !== 'human') {
+    if (note.authorType && note.authorType !== NOTE_DEFAULTS.authorType) {
       lines.push(`**AuthorType:** ${note.authorType}`);
     }
🤖 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 `@src/storageManager.ts` around lines 214 - 235, The serialization currently
omits structured fields by comparing note properties to hardcoded literals
(e.g., 'context', 'line', 'normal', 'human'); update those comparisons to use
the centralized defaults from NOTE_DEFAULTS so behavior follows the shared
defaults. Specifically, replace checks like note.type !== 'context', note.scope
!== 'line', note.priority !== 'normal', and note.authorType !== 'human' with
comparisons against NOTE_DEFAULTS.type, NOTE_DEFAULTS.scope,
NOTE_DEFAULTS.priority, and NOTE_DEFAULTS.authorType respectively (leave other
checks like tags/references/expiresAt unchanged) so changes to NOTE_DEFAULTS
automatically affect serialization in the functions handling note formatting.
src/test/suite/noteManager.test.ts (1)

506-537: ⚡ Quick win

Add a regression test for updateNoteMetadata + defaults boundary.

Great legacy-load coverage. Please also add a case that calls updateNoteMetadata(...) on a legacy/default-omitted note and then re-reads via getNotesForFile to assert type/scope/tags remain defaulted after the metadata-update path.

🤖 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 `@src/test/suite/noteManager.test.ts` around lines 506 - 537, Add a new test
that writes a legacy-shaped note (omitting type/scope/tags) to storage as in the
existing test, then call noteManager.updateNoteMetadata('legacy-1', {/* any
metadata change that triggers an update, e.g. author or updatedAt */}) and
finally re-read notes via noteManager.getNotesForFile('/abs/x.ts') and assert
that the returned note still has type === 'context', scope === 'line', and tags
deep-equals [] to ensure the updateNoteMetadata path applies defaults the same
way as initial loads; reference the existing use of storage.saveNote,
noteManager.updateNoteMetadata, and noteManager.getNotesForFile to locate where
to add this case.
src/exportGenerator.ts (1)

116-118: ⚡ Quick win

Make AGENTS.md section ordering deterministic across runs.

Line 116 onward still depends on input order for equal-priority critical notes, handoffs, decisions, and same-line file notes. That can cause digest churn for identical note sets. Add a stable tiebreak sort (e.g., filePath, lineRange.start, lineRange.end, id) in each section.

Proposed deterministic sort tweak
+const NOTE_TIEBREAK = (a: Note, b: Note): number =>
+  relativePath(a.filePath, workspaceRoot).localeCompare(relativePath(b.filePath, workspaceRoot)) ||
+  (a.lineRange.start - b.lineRange.start) ||
+  (a.lineRange.end - b.lineRange.end) ||
+  a.id.localeCompare(b.id);

   const critical = notes
     .filter(n => n.type === 'instruction' || n.type === 'warning')
-    .sort((a, b) => (PRIORITY_RANK[a.priority!] ?? 99) - (PRIORITY_RANK[b.priority!] ?? 99));
+    .sort((a, b) =>
+      ((PRIORITY_RANK[a.priority!] ?? 99) - (PRIORITY_RANK[b.priority!] ?? 99)) ||
+      NOTE_TIEBREAK(a, b)
+    );

-  const handoffs = notes.filter(n => n.type === 'handoff');
+  const handoffs = notes.filter(n => n.type === 'handoff').sort(NOTE_TIEBREAK);

-  const decisions = notes.filter(n => n.type === 'decision');
+  const decisions = notes.filter(n => n.type === 'decision').sort(NOTE_TIEBREAK);

-    const fileNotes = byFile.get(file)!.sort((a, b) => a.lineRange.start - b.lineRange.start);
+    const fileNotes = byFile.get(file)!.sort((a, b) =>
+      (a.lineRange.start - b.lineRange.start) ||
+      (a.lineRange.end - b.lineRange.end) ||
+      a.id.localeCompare(b.id)
+    );

Also applies to: 127-143, 158-161

🤖 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 `@src/exportGenerator.ts` around lines 116 - 118, The current sort for the
"critical" array (const critical = notes.filter(...).sort(...)) and similar
sorts for handoffs, decisions, and same-line file notes rely only on priority
and thus are non-deterministic for equal-priority items; update each comparator
to add a stable tiebreaker chain that compares filePath (string), then
lineRange.start (number), then lineRange.end (number), then id (string) so
equal-priority entries are deterministically ordered; locate the sort calls for
the variables critical, handoffs, decisions and the same-line notes block and
extend their comparator functions to return comparisons on those fields when
PRIORITY_RANK values are equal.
src/test/suite/exportWriter.test.ts (1)

24-59: ⚡ Quick win

Add a regression test for overlapping regenerate() calls.

Current tests validate debounce, but not concurrent regenerate overlap. Add a test that fires two regenerate() promises concurrently and asserts no onError plus deterministic final output.

🤖 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 `@src/test/suite/exportWriter.test.ts` around lines 24 - 59, Add a new test
that verifies overlapping ExportWriter.regenerate calls don't race: create a
workspace with a '.code-notes' dir and an ExportWriter(ws, '.code-notes', {
debounceMs: 0 }), set writer.onError to capture any error, then fire two
concurrent regenerate() promises with different note sets (use sampleNote to
produce distinct IDs), await both promises, assert onError was not called, and
read/parse INDEX.json to assert the final index matches the notes from the last
regenerate call (deterministic final output). Use the same tmpdir() pattern as
other tests and ensure you check AGENTS.md or INDEX.json contents to validate
atomic, deterministic results.
🤖 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
`@docs/superpowers/plans/2026-05-15-agent-integration-v0.3-schema-and-exports.md`:
- Around line 1315-1319: The fenced code block containing
".code-notes/INDEX.json" and ".code-notes/AGENTS.md" is missing a language
identifier; update the markdown in the document so the fence is typed as
gitignore (i.e., change the opening ``` to ```gitignore) so markdownlint MD040
will accept it and the entries are highlighted/treated correctly.

In `@docs/superpowers/specs/2026-05-15-agent-integration-design.md`:
- Around line 377-381: Fenced code blocks under the "Code Context Notes" rows
are missing language identifiers which may trigger markdownlint MD040; update
both code fences (the blocks containing "Code Context Notes › Agent write mode:
[direct | queue | audit ▼]" and "Code Context Notes › Agent allow-list: 
[claude-code, cursor-agent]" / "Code Context Notes › Audit log retention: [last
1000 ops]") by adding an appropriate language tag (e.g., ```text) immediately
after the opening backticks so markdownlint recognizes them.

In `@README.md`:
- Around line 375-378: The fenced code block showing the two paths
(.code-notes/INDEX.json and .code-notes/AGENTS.md) lacks a language specifier;
update the markdown fenced block in README.md so the opening triple backticks
include the `gitignore` language (i.e., change the fence to ```gitignore) to
enable proper syntax highlighting for ignore-style entries.

In `@src/exportWriter.ts`:
- Around line 39-52: scheduleRegenerate can race with direct calls to
regenerate, causing concurrent atomicWrite calls (for INDEX.json and AGENTS.md
using the fixed ".tmp" suffix in atomicWrite) to clobber the same temp files;
serialize regenerate executions by adding a Promise-based queue or mutex inside
the module (e.g., a private regenerating flag or an async queue) that all
callers (scheduleRegenerate -> the delayed invoke and direct calls to
regenerate) await before performing atomicWrite, or alternatively make
atomicWrite generate unique temp paths per execution (e.g., include
timestamp/UUID in the temp suffix) so INDEX.json.tmp/AGENTS.md.tmp are never
reused concurrently; update regenerate(), scheduleRegenerate(), and
atomicWrite() to use that serialization or unique-temp strategy to prevent
concurrent fs.rename/ENOENT/data loss.

In `@src/extension.ts`:
- Around line 983-1000: The command handlers use sidebarProvider without
guarding against partial/no-workspace activation; update the callbacks
registered in filterByTypeCommand and toggleExpiredCommand to first check that
sidebarProvider is initialized (e.g., if (!sidebarProvider) {
vscode.window.showWarningMessage('Feature unavailable without workspace');
return; }) before calling sidebarProvider.setTypeFilter(...) or
sidebarProvider.toggleHideExpired(); this prevents dereferencing undefined and
provides a clear early-exit when no workspace is active.
- Around line 111-118: The event listener for noteManager ('noteChanged') must
always be registered even if exportsEnabled is false; move or add the
noteManager.on('noteChanged', ...) registration outside the exportsEnabled
conditional and change its handler to check exportsEnabled before calling
exportWriter.scheduleRegenerate(() => noteManager.getAllNotes()). Keep the
initial exportWriter.scheduleRegenerate(...) call inside the exportsEnabled
block so immediate regeneration only happens when exports are enabled, but
ensure the persistent listener exists to start auto-exports whenever
exportsEnabled becomes true later.

In `@src/noteManager.ts`:
- Around line 182-184: The updateNoteMetadata flow allows changes to
soft-deleted notes because it doesn't check the note's deleted flag; add the
same guard used in updateNote: after retrieving the note with
this.storage.loadNoteById(noteId) (the existing variable), verify the note is
not soft-deleted (e.g. existing.deleted or existing.isDeleted) and if it is,
throw the same Error(`Note ${noteId} not found`) to prevent metadata updates on
deleted notes.
- Around line 186-199: The code currently saves `updated` from storage and
writes it to cache and emits events without normalizing defaults or updating the
search index; change the flow so you first normalize the saved note (e.g., const
normalized = applyDefaults(updated)), then pass `normalized` into
this.updateNoteInCache(...) and into emits/return, and after caching call
this.searchManager.updateIndex(normalized) (mirroring other write paths) before
calling this.clearWorkspaceCache(); ensure all references to the note in this
method (cache, events, return) use `normalized` not the raw `updated`.

In `@src/notesSidebarProvider.ts`:
- Around line 191-194: The file/root nodes are currently computed from
unfiltered notes because filtering happens only when computing the local
"filtered" variable; update the code so filtering (applyDefaults + expiry/type
checks using applyDefaults, isExpired, hideExpired, and typeFilter) is applied
earlier—before constructing fileNode and any root totals—so that fileNode.notes
and any aggregates are built from the filtered list; locate where fileNode is
created in NotesSidebarProvider and replace its notes/source-array with the
filtered result (or filter the source array first) to ensure empty files and
totals reflect active filters.

In `@src/storageManager.ts`:
- Around line 321-345: The parser in storageManager.ts currently assigns raw
strings/JSON into note fields (note.type, note.scope, note.priority,
note.authorType, note.expiresAt, note.references, note.tags) which can introduce
invalid metadata; update the parsing in the block handling '**Type:**',
'**Scope:**', '**Priority:**', '**Tags:**', '**AuthorType:**', '**ExpiresAt:**'
and '**References:**' to validate and normalize values instead of using "as any"
or blind JSON.parse: map type/priority/authorType/scope against allowed
enum/string sets and only assign when matching (otherwise set undefined or
default), normalize tags to a deduped non-empty string array, parse expiresAt
into a validated ISO date (or Date) and drop/flag invalid dates, and for
References JSON validate the shape (e.g., ensure array of objects with expected
keys or array of strings) before assigning to note.references; add graceful
error handling/logging for invalid values rather than assigning raw input.

In `@web/CLAUDE.md`:
- Line 7: Replace the hardcoded absolute path string
`/Users/nahian/Projects/code-notes/src` with a portable relative path (for
example `../src` or `./src` depending on the repository layout) in the
web/CLAUDE.md content so the reference points to the extension source from the
web subproject rather than a single developer's machine; update the text that
currently mentions `/Users/nahian/Projects/code-notes/src` to use the chosen
relative path and ensure the sentence still reads clearly.

---

Outside diff comments:
In `@web/src/pages/ChangelogPage.tsx`:
- Around line 763-808: The JSX block rendering the stale "Coming in v0.3.0"
timeline card should be removed (or updated) — remove the entire section that
includes the timeline node div, the h3 with text "Coming in v0.3.0", the Search
icon usage, and the Card / CardContent that lists "Search and Filter Notes",
"Regex Pattern Matching", and "Background Indexing"; alternatively, if you
prefer to keep a future section, change the h3 to "Coming in v0.4.0" and replace
the inner card contents with the MCP server notes from the markdown "Coming
Next" section so it no longer duplicates already released v0.3.0 features.

---

Nitpick comments:
In `@docs/superpowers/specs/2026-05-15-agent-integration-design.md`:
- Around line 133-134: The spec currently describes YAML frontmatter and nested
note paths but must be updated to match the implemented v0.3 contract: replace
any "Storage:" or frontmatter descriptions that reference YAML frontmatter and
nested note paths with the canonical v0.3 description (bold-label markdown
in-document metadata and flat storage under .code-notes/<id>.md), and normalize
all occurrences (including the regions noted around lines 176-177, 317, and
483-509) so the document consistently specifies bold-label markdown metadata and
the flat .code-notes/<id>.md path contract.

In `@README.md`:
- Around line 367-368: Update the README sentence that currently reads "When
auto-exports are enabled, two files are regenerated in `.code-notes/` on every
note change:" to clarify the timing: mention that regeneration is automatic but
debounced (200ms). For example, change it to state that files are regenerated
automatically on note changes and add "(debounced by 200ms)" so users understand
rapid successive edits won't trigger immediate repeated writes; edit the same
sentence in README to include that debounced timing.

In `@src/exportGenerator.ts`:
- Around line 116-118: The current sort for the "critical" array (const critical
= notes.filter(...).sort(...)) and similar sorts for handoffs, decisions, and
same-line file notes rely only on priority and thus are non-deterministic for
equal-priority items; update each comparator to add a stable tiebreaker chain
that compares filePath (string), then lineRange.start (number), then
lineRange.end (number), then id (string) so equal-priority entries are
deterministically ordered; locate the sort calls for the variables critical,
handoffs, decisions and the same-line notes block and extend their comparator
functions to return comparisons on those fields when PRIORITY_RANK values are
equal.

In `@src/storageManager.ts`:
- Around line 214-235: The serialization currently omits structured fields by
comparing note properties to hardcoded literals (e.g., 'context', 'line',
'normal', 'human'); update those comparisons to use the centralized defaults
from NOTE_DEFAULTS so behavior follows the shared defaults. Specifically,
replace checks like note.type !== 'context', note.scope !== 'line',
note.priority !== 'normal', and note.authorType !== 'human' with comparisons
against NOTE_DEFAULTS.type, NOTE_DEFAULTS.scope, NOTE_DEFAULTS.priority, and
NOTE_DEFAULTS.authorType respectively (leave other checks like
tags/references/expiresAt unchanged) so changes to NOTE_DEFAULTS automatically
affect serialization in the functions handling note formatting.

In `@src/test/runUnitTests.ts`:
- Around line 35-39: The unitTestFiles filter uses a long boolean OR chain which
is hard to maintain; refactor the files.filter callback in runUnitTests.ts to
compute basename via path.basename(f), then test membership against an array of
allowed test file names (e.g., const allowed =
['storageManager.test.js','gitIntegration.test.js','noteDefaults.test.js','exportGenerator.test.js','exportWriter.test.js'])
and return allowed.includes(basename) inside the files.filter callback so
adding/removing tests becomes a simple array change (update references to
unitTestFiles and the files.filter callback).

In `@src/test/suite/exportWriter.test.ts`:
- Around line 24-59: Add a new test that verifies overlapping
ExportWriter.regenerate calls don't race: create a workspace with a
'.code-notes' dir and an ExportWriter(ws, '.code-notes', { debounceMs: 0 }), set
writer.onError to capture any error, then fire two concurrent regenerate()
promises with different note sets (use sampleNote to produce distinct IDs),
await both promises, assert onError was not called, and read/parse INDEX.json to
assert the final index matches the notes from the last regenerate call
(deterministic final output). Use the same tmpdir() pattern as other tests and
ensure you check AGENTS.md or INDEX.json contents to validate atomic,
deterministic results.

In `@src/test/suite/noteManager.test.ts`:
- Around line 506-537: Add a new test that writes a legacy-shaped note (omitting
type/scope/tags) to storage as in the existing test, then call
noteManager.updateNoteMetadata('legacy-1', {/* any metadata change that triggers
an update, e.g. author or updatedAt */}) and finally re-read notes via
noteManager.getNotesForFile('/abs/x.ts') and assert that the returned note still
has type === 'context', scope === 'line', and tags deep-equals [] to ensure the
updateNoteMetadata path applies defaults the same way as initial loads;
reference the existing use of storage.saveNote, noteManager.updateNoteMetadata,
and noteManager.getNotesForFile to locate where to add this case.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 55a9c87c-ca66-404c-98f9-a5755ff29145

📥 Commits

Reviewing files that changed from the base of the PR and between c7de3c9 and 7f81a64.

📒 Files selected for processing (22)
  • README.md
  • docs/changelogs/v0.3.0.md
  • docs/superpowers/plans/2026-05-15-agent-integration-v0.3-schema-and-exports.md
  • docs/superpowers/specs/2026-05-15-agent-integration-design.md
  • package.json
  • src/exportGenerator.ts
  • src/exportWriter.ts
  • src/extension.ts
  • src/noteDefaults.ts
  • src/noteManager.ts
  • src/noteTreeItem.ts
  • src/notesSidebarProvider.ts
  • src/storageManager.ts
  • src/test/runUnitTests.ts
  • src/test/suite/exportGenerator.test.ts
  • src/test/suite/exportWriter.test.ts
  • src/test/suite/noteDefaults.test.ts
  • src/test/suite/noteManager.test.ts
  • src/test/suite/storageManager.test.ts
  • src/types.ts
  • web/CLAUDE.md
  • web/src/pages/ChangelogPage.tsx

Comment thread docs/superpowers/plans/2026-05-15-agent-integration-v0.3-schema-and-exports.md Outdated
Comment thread docs/superpowers/specs/2026-05-15-agent-integration-design.md Outdated
Comment thread README.md Outdated
Comment thread src/exportWriter.ts
Comment thread src/extension.ts Outdated
Comment thread src/noteManager.ts
Comment thread src/noteManager.ts Outdated
Comment thread src/notesSidebarProvider.ts Outdated
Comment thread src/storageManager.ts
Comment thread web/CLAUDE.md Outdated

Copilot AI 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.

Pull request overview

Adds the v0.3.0 foundation for structured, agent-readable notes and generated workspace exports, alongside release documentation and web changelog updates.

Changes:

  • Extends notes with optional schema metadata, defaults, parsing/writing support, and sidebar metadata/filter UI.
  • Adds INDEX.json / AGENTS.md generation with debounced export writing and configuration.
  • Adds tests and release/web documentation for v0.3.0 agent integration and search messaging.

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 26 comments.

Show a summary per file
File Description
src/types.ts Adds structured note metadata types and optional fields.
src/noteDefaults.ts Adds defaulting and expiry helpers.
src/storageManager.ts Parses and writes structured metadata fields.
src/noteManager.ts Applies defaults on storage reads and adds metadata updates.
src/exportGenerator.ts Builds INDEX.json and AGENTS.md contents.
src/exportWriter.ts Writes generated exports with debounce and atomic rename.
src/extension.ts Wires exports and registers new commands.
src/notesSidebarProvider.ts Adds type/expiry filter state for sidebar notes.
src/noteTreeItem.ts Displays note type and priority in sidebar items/tooltips.
src/test/runUnitTests.ts Includes new unit test files in the unit runner.
src/test/suite/storageManager.test.ts Adds structured metadata parser/writer tests.
src/test/suite/noteManager.test.ts Adds defaulting boundary coverage.
src/test/suite/noteDefaults.test.ts Adds defaults and expiry tests.
src/test/suite/exportGenerator.test.ts Adds index/digest generator tests.
src/test/suite/exportWriter.test.ts Adds export writer debounce/write/error tests.
package.json Bumps version and contributes export commands/settings.
README.md Documents generated exports and gitignore guidance.
docs/changelogs/v0.3.0.md Adds v0.3.0 release notes.
docs/superpowers/specs/2026-05-15-agent-integration-design.md Adds agent integration design spec.
docs/superpowers/plans/2026-05-15-agent-integration-v0.3-schema-and-exports.md Adds implementation plan.
web/src/pages/ChangelogPage.tsx Adds v0.3.0 entry to web changelog.
web/CLAUDE.md Adds web subproject agent guidance.
Comments suppressed due to low confidence (7)

src/exportGenerator.ts:95

  • generatedAt defaults to the current time, so buildIndex(notes, workspaceRoot) produces a different INDEX.json on every regeneration even when the notes are unchanged. This contradicts the deterministic-output behavior documented for the generated exports and will create avoidable git diffs for teams that commit them.
  return {
    version: 1,
    generatedAt: now.toISOString(),
    workspaceRoot,
    notes: entries,

src/extension.ts:1000

  • This command also dereferences sidebarProvider without a workspace/initialization guard. In the no-workspace partial activation path, invoking it from the command palette will fail with an exception rather than a user-facing error.
	const toggleExpiredCommand = vscode.commands.registerCommand(
		'codeContextNotes.toggleExpired',
		() => {
			sidebarProvider.toggleHideExpired();
		}

docs/superpowers/specs/2026-05-15-agent-integration-design.md:508

  • This migration section also describes YAML/frontmatter behavior and an older-version YAML loader, which does not match the current bold-label markdown parser. Please update the design doc so rollback/compatibility guidance matches the actual on-disk format.
### 6.3 Frontmatter format

Writer omits any field equal to its default. A plain note that's still just a `context` note on a line range stays the shape it always had.

### 6.4 Backward compatibility

A v0.2.x install opening a workspace with v0.3 notes: unknown frontmatter keys are ignored by the YAML loader. Note loads with its original fields. `INDEX.json`/`AGENTS.md` ignored. No data loss either direction. Mixed v0.2.x/v0.3 installs across a team are fine without coordination.

src/exportGenerator.ts:118

  • The digest ordering for instructions/warnings only sorts by priority, leaving ties in the input order returned by the filesystem-backed note scan. Because AGENTS.md is documented as deterministic, add a stable tie-breaker such as file path/line/id so equal-priority notes do not reorder between regenerations.
  const critical = notes
    .filter(n => n.type === 'instruction' || n.type === 'warning')
    .sort((a, b) => (PRIORITY_RANK[a.priority!] ?? 99) - (PRIORITY_RANK[b.priority!] ?? 99));

src/exportGenerator.ts:132

  • Open handoffs are emitted in the input order without any stable sort. Since the input comes from scanning note files, this can make AGENTS.md reorder unchanged handoffs across platforms/filesystems despite the deterministic-output guarantee.
  const handoffs = notes.filter(n => n.type === 'handoff');
  if (handoffs.length > 0) {
    out.push('## Open handoffs');
    for (const n of handoffs) {
      const range = n.lineRange.start === n.lineRange.end ? `${n.lineRange.start + 1}` : `${n.lineRange.start + 1}-${n.lineRange.end + 1}`;
      out.push(`- **\`${relativePath(n.filePath, workspaceRoot)}:${range}\`** — handoff from ${n.author}: ${preview(n.content)}`);

src/exportGenerator.ts:142

  • Decisions are also emitted in raw input order. For deterministic generated output, this section should use the same kind of stable ordering as the all-notes section, such as relative file path, line number, then note id.
  const decisions = notes.filter(n => n.type === 'decision');
  if (decisions.length > 0) {
    out.push('## Decisions worth knowing');
    for (const n of decisions) {
      out.push(`- **\`${relativePath(n.filePath, workspaceRoot)}:${n.lineRange.start + 1}\`** — decision: ${preview(n.content)}`);
    }

src/exportGenerator.ts:161

  • Within a file, notes with the same starting line are sorted only by lineRange.start, so equal-line notes retain filesystem scan order. Add a secondary key such as end line and id to keep AGENTS.md stable when multiple notes are attached to the same line.
    out.push(`### \`${file}\``);
    const fileNotes = byFile.get(file)!.sort((a, b) => a.lineRange.start - b.lineRange.start);
    for (const n of fileNotes) {
      const tags = n.tags!.length > 0 ? ` [${n.tags!.join(', ')}]` : '';
      out.push(`- L${n.lineRange.start + 1} — ${n.type} (${n.priority})${tags}: ${preview(n.content)}`);

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/noteManager.ts
Comment thread src/exportGenerator.ts
Comment thread src/exportWriter.ts
Comment thread src/extension.ts Outdated
Comment thread src/extension.ts Outdated
Comment thread src/storageManager.ts
Comment thread src/storageManager.ts
Comment thread src/noteDefaults.ts
Comment thread src/extension.ts
Comment thread src/noteManager.ts Outdated
- exportWriter: serialize regenerate() calls so the debounced timer and
  manual "Regenerate Exports" command can't race on the same tmp files
- extension: always subscribe to noteChanged so enabling exports after
  activation works without a reload; guard filterByType/toggleExpired
  against missing sidebarProvider in no-workspace activation; surface
  real success/failure from the regenerateExports command instead of
  always showing success
- noteManager: block metadata updates on soft-deleted notes, normalize
  updateNoteMetadata/createNote through applyDefaults before caching so
  cache hits can't return notes with undefined schema fields, and keep
  the search index in sync on metadata updates
- notesSidebarProvider: apply type/expiry filters before building file
  nodes so the root count and per-file nodes reflect the active filters
  instead of showing empty files or stale totals
- storageManager: validate parsed Type/Scope/Priority/AuthorType/
  References against known enums instead of blind `as any`/JSON.parse;
  reuse NOTE_DEFAULTS instead of duplicated literals when serializing
- exportGenerator: thread the configured storage directory into
  contentPath/digest source line (was hardcoded to .code-notes) and
  add stable tiebreak sorting so AGENTS.md ordering is deterministic
  for equal-priority/same-line notes
- fix package-lock.json version drift (0.1.7 -> 0.3.0)
- fix hardcoded absolute path in web/CLAUDE.md, misleading NotePriority
  doc comment, missing markdownlint language tags, and remove the
  stale "Coming in v0.3.0" changelog section duplicating shipped notes

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015NoZbQSkHz14Fo7fnaU5n7
@jnahian jnahian changed the title feat: v0.3.0 — agent integration foundation (schema + exports) + search feat: v0.3.0 — agent integration foundation (schema + exports) Jul 16, 2026
jnahian and others added 6 commits July 16, 2026 23:24
- Reject metadata updates on soft-deleted notes (matches updateNote)
- Sync the search index on metadata changes
- Apply schema defaults at the cache entry points (addNoteToCache /
  updateNoteInCache) so cached notes always honor the NoteManager
  boundary guarantee, including notes inserted by createNote

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Filtering now happens once in applyNoteFilters, used by the root
count, file nodes, and note leaves — files whose notes are all
filtered out no longer render as empty groups, and the root total
matches what the tree shows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…status

- Export hooks always attached: toggling exports.enabled takes effect
  both ways without a reload (regenerate reads config per run)
- External note-file changes (git pull, manual edits) also regenerate
  exports via the noteFileChanged watcher
- Watcher ignores the generated AGENTS.md — regenerating exports was
  re-triggering the watcher in a feedback loop
- Unique temp filenames so overlapping regenerations can't clobber
  each other's temp file
- regenerate() returns written/disabled/failed; the manual command
  reports each state instead of always claiming success
- INDEX.json contentPath honors codeContextNotes.storageDirectory;
  AGENTS.md header no longer claims INDEX.json as its source
- Activation log reads the real extension version (was hardcoded 0.1.3)
- Guard filterByType/toggleExpired for no-workspace activation

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Invalid Type/Scope/Priority/AuthorType values are dropped with a
warning (schema defaults apply at the NoteManager boundary), and
References entries are filtered to valid {kind, value} shapes.
Narrows the NotePriority comment to shipped behavior.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Verification found the search UI (commands, keybinding, settings,
searchUI.ts) was silently dropped in an earlier merge — only the
SearchManager backend reached main. Search claims are removed from
the v0.3.0 changelogs; the UI ships in a follow-up (Issue #10).

Also: README determinism caveat (generatedAt) and configurable
storage-directory phrasing, gitignore/text fence languages (MD040),
spec frontmatter wording aligned to bold-label format, web/CLAUDE.md
relative path, stale 'Coming in v0.3.0' web section now 'Coming
Next' (MCP server + search), exports setting description, lockfile
synced to 0.3.0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Both address the same CodeRabbit/Copilot findings from parallel
sessions. Kept the superset: remote's typed enum validation,
NOTE_DEFAULTS reuse, regenerate() serialization, and digest tiebreak
sorting; local's unique tmp filenames, regenerate status returns,
noteFileChanged export regeneration + AGENTS.md watcher-loop guard,
search-claims removal from changelogs, and regression tests. Kept
per-entry references salvage (tested) over all-or-nothing, and the
digest header without an INDEX.json pointer since exports.indexJson
can be disabled independently.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jnahian

jnahian commented Jul 16, 2026

Copy link
Copy Markdown
Owner Author

All review findings from CodeRabbit and Copilot have been addressed and the threads resolved.

Two parallel fix sessions landed on this branch; they were merged in d282c9a keeping the superset of both: typed enum validation + NOTE_DEFAULTS reuse + serialized regenerate() + digest tiebreak sorting (remote session), and unique temp filenames + regenerate() status returns + external-change export regeneration with an AGENTS.md watcher-loop guard + search-claims removal + regression tests (this session).

Verification on the merged tree: tsc clean, esbuild clean, 60/60 unit tests, integration suite unchanged vs. baseline (the 34 pre-existing failures are unrelated search/tag tests that predate this PR), plus a live extension-host smoke pass covering exports, metadata QuickPick flow, sidebar filter/expired toggle, and legacy-note compatibility.

🤖 Generated with Claude Code

jnahian and others added 5 commits July 16, 2026 23:51
tsc never deletes outputs for removed sources, so out/test/suite kept
stale compiled suites from old branches (searchManager, sidebarProvider,
tagManager) — ~100 phantom tests failing against code that doesn't
exist in this tree. pretest now cleans out/ first.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- getNotesForFile cached a pre-filtered list from storage.loadNotes,
  hiding deleted notes from getAllNotesForFile cache hits; the cache
  now always holds all notes and filters at return
- deleteNote removed the soft-deleted note from the cache instead of
  updating it, turning 'already deleted' errors into 'not found'
- getNoteById no longer returns soft-deleted notes to consumers

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- getCurrentlyEditingComment looked up commentThreads (keyed by
  file:line thread key) with a note id, so it always returned null;
  the thread key is now tracked alongside the editing note id
- Comment labels always said 'Last updated' because the creation
  history entry counted as an update; fresh notes now show 'Created'

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- CodeLens: take the first line before stripping markdown (the strip
  collapses newlines, merging every line into the preview) and strip
  heading markers that appear mid-text
- noteTreeItem: strip image markdown before link markdown so
  ![alt](url) doesn't leave a stray '!'; truncateText returns the
  ellipsis itself when maxLength <= 3 instead of a clipped fragment
- Sidebar: sort note children by line number — callers may construct
  FileTreeItem with notes in any order

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Mock document paths used Date.now() alone — two docs created in the
  same millisecond collided on the same fsPath; added a sequence counter
- CommentController flows that reopen the document from disk now write
  the file first (openTextDocument was failing on nonexistent paths)
- await the now-async updateCommentThread; assert falsy instead of
  null for deleted-note lookup (API returns undefined)
- Changelog: record the fixes under v0.3.0

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix: eliminate all 34 integration test failures (phantom suites + real bugs)
# Conflicts:
#	docs/superpowers/plans/2026-05-15-agent-integration-v0.3-schema-and-exports.md
#	docs/superpowers/specs/2026-05-15-agent-integration-design.md
#	web/CLAUDE.md
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.

3 participants