diff --git a/README.md b/README.md index eb03d3adb..467623ddb 100644 --- a/README.md +++ b/README.md @@ -623,8 +623,10 @@ The best practice for working in teams is to ensure unique milestone names acros # ── GSD: Runtime / Ephemeral (per-developer, per-session) ────────────────── # Crash detection sentinel — PID lock, written per auto-mode session .gsd/auto.lock -# Auto-mode dispatch tracker — prevents re-running completed units -.gsd/completed-units.json +# Auto-mode dispatch tracker — prevents re-running completed units (includes archived per-milestone files) +.gsd/completed-units*.json +# State manifest — workflow state for recovery +.gsd/state-manifest.json # Derived state cache — regenerated from plan/roadmap files on disk .gsd/STATE.md # Per-developer token/cost accumulator @@ -637,6 +639,14 @@ The best practice for working in teams is to ensure unique milestone names acros .gsd/worktrees/ # Parallel orchestration IPC and worker status .gsd/parallel/ +# SQLite database and WAL sidecars — checkpoint state, forensics data +.gsd/gsd.db* +# Daily-rotated event journal — structured event log for forensics +.gsd/journal/ +# Doctor run history — diagnostic check results +.gsd/doctor-history.jsonl +# Workflow event log — structured event stream +.gsd/event-log.jsonl # Generated HTML reports (regenerable via /gsd export --html) .gsd/reports/ # Session-specific interrupted-work markers diff --git a/mintlify-docs/guides/working-in-teams.mdx b/mintlify-docs/guides/working-in-teams.mdx index 72baa19e2..d59bce66b 100644 --- a/mintlify-docs/guides/working-in-teams.mdx +++ b/mintlify-docs/guides/working-in-teams.mdx @@ -26,19 +26,24 @@ Share planning artifacts while keeping runtime files local: ```bash # Runtime / ephemeral (per-developer) .gsd/auto.lock -.gsd/completed-units.json +.gsd/completed-units*.json +.gsd/state-manifest.json .gsd/STATE.md .gsd/metrics.json .gsd/activity/ .gsd/runtime/ .gsd/worktrees/ +.gsd/gsd.db* +.gsd/journal/ +.gsd/doctor-history.jsonl +.gsd/event-log.jsonl .gsd/milestones/**/continue.md .gsd/milestones/**/*-CONTINUE.md ``` **Shared** (committed): preferences, PROJECT.md, REQUIREMENTS.md, DECISIONS.md, milestones. -**Local** (gitignored): lock files, metrics, state cache, worktrees, activity logs. +**Local** (gitignored): lock files, metrics, state cache, worktrees, activity logs, database files, journals. ### 3. Commit diff --git a/src/resources/extensions/gsd/doctor-runtime-checks.ts b/src/resources/extensions/gsd/doctor-runtime-checks.ts index d2af2bd9a..5b4b99572 100644 --- a/src/resources/extensions/gsd/doctor-runtime-checks.ts +++ b/src/resources/extensions/gsd/doctor-runtime-checks.ts @@ -303,13 +303,16 @@ export async function checkRuntimeHealth( content.split("\n").map(l => l.trim()).filter(l => l && !l.startsWith("#")), ); - // Check for critical runtime patterns that must be present + // Check for critical runtime patterns that must be present. + // NOTE: GSD_RUNTIME_PATTERNS in gitignore.ts is the canonical source of truth. + // This is a minimal subset for the doctor check. const criticalPatterns = [ ".gsd/activity/", ".gsd/runtime/", ".gsd/auto.lock", - ".gsd/gsd.db", - ".gsd/completed-units.json", + ".gsd/gsd.db*", + ".gsd/completed-units*.json", + ".gsd/event-log.jsonl", ]; // If blanket .gsd/ or .gsd is present, all patterns are covered diff --git a/src/resources/extensions/gsd/git-service.ts b/src/resources/extensions/gsd/git-service.ts index ae73a0e94..c937da714 100644 --- a/src/resources/extensions/gsd/git-service.ts +++ b/src/resources/extensions/gsd/git-service.ts @@ -192,22 +192,25 @@ export interface PreMergeCheckResult { /** * GSD runtime paths that should be excluded from smart staging. * These are transient/generated artifacts that should never be committed. - * Matches the union of SKIP_PATHS + SKIP_EXACT in worktree-manager.ts - * and the first 7 entries in gitignore.ts BASELINE_PATTERNS. + * + * NOTE: GSD_RUNTIME_PATTERNS in gitignore.ts is the canonical source of truth. + * This array must stay synchronized with it. */ export const RUNTIME_EXCLUSION_PATHS: readonly string[] = [ ".gsd/activity/", + ".gsd/forensics/", ".gsd/runtime/", ".gsd/worktrees/", + ".gsd/parallel/", ".gsd/auto.lock", ".gsd/metrics.json", - ".gsd/completed-units.json", + ".gsd/completed-units*.json", // covers completed-units.json and archived completed-units-{MID}.json + ".gsd/state-manifest.json", ".gsd/STATE.md", - ".gsd/gsd.db", - ".gsd/gsd.db-shm", // SQLite WAL sidecar — always created alongside gsd.db (#2296) - ".gsd/gsd.db-wal", // SQLite WAL sidecar — always created alongside gsd.db (#2296) - ".gsd/journal/", // daily-rotated JSONL event journal (#2296) - ".gsd/doctor-history.jsonl", // doctor run history (#2296) + ".gsd/gsd.db*", + ".gsd/journal/", + ".gsd/doctor-history.jsonl", + ".gsd/event-log.jsonl", ".gsd/DISCUSSION-MANIFEST.json", ]; diff --git a/src/resources/extensions/gsd/gitignore.ts b/src/resources/extensions/gsd/gitignore.ts index 8a80c3da5..98341849a 100644 --- a/src/resources/extensions/gsd/gitignore.ts +++ b/src/resources/extensions/gsd/gitignore.ts @@ -15,6 +15,12 @@ import { GIT_NO_PROMPT_ENV } from "./git-constants.js"; /** * GSD runtime patterns for git index cleanup. + * + * CANONICAL SOURCE OF TRUTH: This array is the authoritative list of runtime + * ignore patterns. Other modules (RUNTIME_EXCLUSION_PATHS in git-service.ts, + * SKIP_* arrays in worktree-manager.ts, criticalPatterns in doctor-runtime-checks.ts) + * must stay synchronized with this list. + * * With external state (symlink), these are a no-op in most cases, * but retained for backwards compatibility during migration. */ @@ -26,13 +32,13 @@ const GSD_RUNTIME_PATTERNS = [ ".gsd/parallel/", ".gsd/auto.lock", ".gsd/metrics.json", - ".gsd/completed-units.json", + ".gsd/completed-units*.json", // covers completed-units.json and archived completed-units-{MID}.json + ".gsd/state-manifest.json", ".gsd/STATE.md", - ".gsd/gsd.db", - ".gsd/gsd.db-shm", // SQLite WAL sidecar — always created alongside gsd.db (#2296) - ".gsd/gsd.db-wal", // SQLite WAL sidecar — always created alongside gsd.db (#2296) - ".gsd/journal/", // daily-rotated JSONL event journal (#2296) - ".gsd/doctor-history.jsonl", // doctor run history (#2296) + ".gsd/gsd.db*", + ".gsd/journal/", + ".gsd/doctor-history.jsonl", + ".gsd/event-log.jsonl", ".gsd/DISCUSSION-MANIFEST.json", ".gsd/milestones/**/*-CONTINUE.md", ".gsd/milestones/**/continue.md", diff --git a/src/resources/extensions/gsd/tests/integration/git-service.test.ts b/src/resources/extensions/gsd/tests/integration/git-service.test.ts index f88901431..b99c2e8ca 100644 --- a/src/resources/extensions/gsd/tests/integration/git-service.test.ts +++ b/src/resources/extensions/gsd/tests/integration/git-service.test.ts @@ -248,23 +248,25 @@ describe('git-service', async () => { assert.deepStrictEqual( RUNTIME_EXCLUSION_PATHS.length, - 13, - "exactly 13 runtime exclusion paths" + 15, + "exactly 15 runtime exclusion paths" ); const expectedPaths = [ ".gsd/activity/", + ".gsd/forensics/", ".gsd/runtime/", ".gsd/worktrees/", + ".gsd/parallel/", ".gsd/auto.lock", ".gsd/metrics.json", - ".gsd/completed-units.json", + ".gsd/completed-units*.json", + ".gsd/state-manifest.json", ".gsd/STATE.md", - ".gsd/gsd.db", - ".gsd/gsd.db-shm", - ".gsd/gsd.db-wal", + ".gsd/gsd.db*", ".gsd/journal/", ".gsd/doctor-history.jsonl", + ".gsd/event-log.jsonl", ".gsd/DISCUSSION-MANIFEST.json", ]; diff --git a/src/resources/extensions/gsd/worktree-manager.ts b/src/resources/extensions/gsd/worktree-manager.ts index 37490a30b..5c4d274ec 100644 --- a/src/resources/extensions/gsd/worktree-manager.ts +++ b/src/resources/extensions/gsd/worktree-manager.ts @@ -548,13 +548,39 @@ export function removeWorktree( } } -/** Paths to skip in all worktree diffs (internal/runtime artifacts). */ -const SKIP_PATHS = [".gsd/worktrees/", ".gsd/runtime/", ".gsd/activity/"]; -const SKIP_EXACT = [".gsd/STATE.md", ".gsd/auto.lock", ".gsd/metrics.json"]; +/** + * Paths to skip in all worktree diffs (internal/runtime artifacts). + * + * NOTE: These arrays must stay synchronized with GSD_RUNTIME_PATTERNS in gitignore.ts. + * That file is the canonical source of truth for runtime ignore patterns. + * This module uses a split representation (paths/exact/prefixes) for efficient matching. + */ +const SKIP_PATHS = [ + ".gsd/worktrees/", + ".gsd/runtime/", + ".gsd/activity/", + ".gsd/forensics/", + ".gsd/parallel/", + ".gsd/journal/", +]; +const SKIP_EXACT = [ + ".gsd/STATE.md", + ".gsd/auto.lock", + ".gsd/metrics.json", + ".gsd/state-manifest.json", + ".gsd/doctor-history.jsonl", + ".gsd/event-log.jsonl", +]; +/** File prefixes to skip (for wildcard patterns like completed-units*.json, gsd.db*). */ +const SKIP_PREFIXES = [ + ".gsd/completed-units", + ".gsd/gsd.db", +]; function shouldSkipPath(filePath: string): boolean { if (SKIP_PATHS.some(p => filePath.startsWith(p))) return true; if (SKIP_EXACT.includes(filePath)) return true; + if (SKIP_PREFIXES.some(p => filePath.startsWith(p))) return true; return false; }