@wizdear/atlas-code 0.2.4 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/agent-factory.d.ts +10 -5
- package/dist/agent-factory.d.ts.map +1 -1
- package/dist/agent-factory.js +50 -13
- package/dist/agent-factory.js.map +1 -1
- package/dist/cli.d.ts +7 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +72 -16
- package/dist/cli.js.map +1 -1
- package/dist/discovery.d.ts +9 -2
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +4 -5
- package/dist/discovery.js.map +1 -1
- package/dist/extension.d.ts +9 -2
- package/dist/extension.d.ts.map +1 -1
- package/dist/extension.js +1103 -381
- package/dist/extension.js.map +1 -1
- package/dist/gate.d.ts +1 -1
- package/dist/gate.d.ts.map +1 -1
- package/dist/gate.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/orchestrator.d.ts +0 -4
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +0 -2
- package/dist/orchestrator.js.map +1 -1
- package/dist/pipeline-editor.d.ts +2 -0
- package/dist/pipeline-editor.d.ts.map +1 -1
- package/dist/pipeline-editor.js +36 -5
- package/dist/pipeline-editor.js.map +1 -1
- package/dist/pipeline.d.ts +2 -10
- package/dist/pipeline.d.ts.map +1 -1
- package/dist/pipeline.js +4 -6
- package/dist/pipeline.js.map +1 -1
- package/dist/planner.d.ts +9 -2
- package/dist/planner.d.ts.map +1 -1
- package/dist/planner.js +15 -11
- package/dist/planner.js.map +1 -1
- package/dist/roles/architect.d.ts +1 -1
- package/dist/roles/architect.d.ts.map +1 -1
- package/dist/roles/architect.js +1 -1
- package/dist/roles/architect.js.map +1 -1
- package/dist/roles/cicd.d.ts +1 -1
- package/dist/roles/cicd.d.ts.map +1 -1
- package/dist/roles/cicd.js +5 -0
- package/dist/roles/cicd.js.map +1 -1
- package/dist/roles/documenter.d.ts +1 -1
- package/dist/roles/documenter.d.ts.map +1 -1
- package/dist/roles/documenter.js +11 -0
- package/dist/roles/documenter.js.map +1 -1
- package/dist/roles/index.d.ts +1 -0
- package/dist/roles/index.d.ts.map +1 -1
- package/dist/roles/index.js +3 -0
- package/dist/roles/index.js.map +1 -1
- package/dist/roles/recover.d.ts +5 -0
- package/dist/roles/recover.d.ts.map +1 -0
- package/dist/roles/recover.js +82 -0
- package/dist/roles/recover.js.map +1 -0
- package/dist/roles/reviewer.d.ts +1 -1
- package/dist/roles/reviewer.d.ts.map +1 -1
- package/dist/roles/reviewer.js +7 -1
- package/dist/roles/reviewer.js.map +1 -1
- package/dist/roles/standards-enricher.d.ts +1 -1
- package/dist/roles/standards-enricher.d.ts.map +1 -1
- package/dist/roles/standards-enricher.js +8 -0
- package/dist/roles/standards-enricher.js.map +1 -1
- package/dist/roles/tester.d.ts +1 -1
- package/dist/roles/tester.d.ts.map +1 -1
- package/dist/roles/tester.js +7 -0
- package/dist/roles/tester.js.map +1 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +6 -6
- package/dist/router.js.map +1 -1
- package/dist/standards.d.ts +37 -11
- package/dist/standards.d.ts.map +1 -1
- package/dist/standards.js +71 -89
- package/dist/standards.js.map +1 -1
- package/dist/step-executor.d.ts +15 -2
- package/dist/step-executor.d.ts.map +1 -1
- package/dist/step-executor.js +138 -30
- package/dist/step-executor.js.map +1 -1
- package/dist/store.d.ts +3 -10
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +45 -57
- package/dist/store.js.map +1 -1
- package/dist/system-architect.d.ts +9 -2
- package/dist/system-architect.d.ts.map +1 -1
- package/dist/system-architect.js +6 -10
- package/dist/system-architect.js.map +1 -1
- package/dist/telegram/bridge.d.ts +39 -0
- package/dist/telegram/bridge.d.ts.map +1 -0
- package/dist/telegram/bridge.js +380 -0
- package/dist/telegram/bridge.js.map +1 -0
- package/dist/telegram/formatter.d.ts +15 -0
- package/dist/telegram/formatter.d.ts.map +1 -0
- package/dist/telegram/formatter.js +86 -0
- package/dist/telegram/formatter.js.map +1 -0
- package/dist/telegram/renderer.d.ts +45 -0
- package/dist/telegram/renderer.d.ts.map +1 -0
- package/dist/telegram/renderer.js +150 -0
- package/dist/telegram/renderer.js.map +1 -0
- package/dist/telegram/telegram-api.d.ts +84 -0
- package/dist/telegram/telegram-api.d.ts.map +1 -0
- package/dist/telegram/telegram-api.js +134 -0
- package/dist/telegram/telegram-api.js.map +1 -0
- package/dist/types.d.ts +10 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +2 -0
- package/dist/ui.js.map +1 -1
- package/package.json +1 -1
package/dist/store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { access, mkdir, readdir, readFile, rm, stat, unlink, writeFile } from \"node:fs/promises\";\nimport { isAbsolute, join, resolve } from \"node:path\";\nimport { createModuleLogger, type ModuleLogger, noopLogger, type VibeLogger } from \"./logger.js\";\nimport type {\n\tAgentCheckpoint,\n\tArtifactName,\n\tFeatureStatus,\n\tFeatureStatusValue,\n\tOrchestrationState,\n\tPersistedPipeline,\n\tPlanData,\n\tVibeConfig,\n} from \"./types.js\";\n\n/** Valid state transition map. */\nconst VALID_TRANSITIONS: Record<FeatureStatusValue, FeatureStatusValue[]> = {\n\tplanned: [\"designing\", \"blocked\", \"failed\"],\n\tdesigning: [\"branching\", \"implementing\", \"blocked\", \"failed\"],\n\tbranching: [\"implementing\", \"blocked\", \"failed\"],\n\timplementing: [\"testing\", \"done\", \"blocked\", \"failed\"],\n\ttesting: [\"reviewing\", \"implementing\", \"blocked\", \"failed\"],\n\treviewing: [\"done\", \"merging\", \"implementing\", \"blocked\", \"failed\"],\n\tmerging: [\"done\", \"blocked\", \"failed\"],\n\tdone: [],\n\tblocked: [\"planned\", \"designing\", \"branching\", \"implementing\", \"testing\", \"reviewing\", \"merging\", \"failed\"],\n\tfailed: [],\n};\n\n/** Default configuration. */\nconst DEFAULT_CONFIG: VibeConfig = {\n\tautonomyLevel: \"gate_auto\",\n\tgates: {\n\t\trequireRequirementsApproval: true,\n\t\trequirePlanApproval: true,\n\t\trequireDesignApproval: false,\n\t\trequireSystemDesignApproval: true,\n\t\trequireMergeApproval: true,\n\t\trequireDiagnosisApproval: true,\n\t},\n\tretry: {\n\t\tmaxTestRetries: 3,\n\t\tmaxReviewRetries: 2,\n\t\tmaxRegressionRetries: 3,\n\t\tmaxStepRetries: 2,\n\t},\n\tstandards: {\n\t\tsources: [\".vibe/standards/\"],\n\t},\n\tnotifications: {\n\t\tonStepComplete: true,\n\t\tonBlocked: true,\n\t\tonPRReady: true,\n\t\tchannel: \"terminal\",\n\t},\n\tprojectAnalysis: {\n\t\tautoAnalyzeOnInit: true,\n\t\tstaleThresholdDays: 7,\n\t\texcludePaths: [\"node_modules\", \"dist\", \".git\"],\n\t},\n\tdiscovery: {\n\t\tmaxQuestionRounds: 5,\n\t\tskipIfClear: true,\n\t},\n\tcompaction: {\n\t\tenabled: true,\n\t\treserveTokens: 16384,\n\t\tkeepRecentTokens: 20000,\n\t},\n\ttesting: {\n\t\ttestCommand: \"\",\n\t\ttestTimeout: 300,\n\t\trunExistingTests: false,\n\t\texcludePatterns: [],\n\t\tciChecks: [],\n\t},\n};\n\n/** Default .gitignore content for user project .vibe/ directories. */\nconst VIBE_GITIGNORE_CONTENT = `# Runtime data (not design artifacts)\nlogs/\norchestration-state.json\nrequirements.md\nproject-context.md\nfeatures/*/agent-history/\n\n# Config is project-specific, tracked\n!config.json\n`;\n\n/** Deep merges two objects. Keys missing from target are taken from defaults. */\nfunction deepMerge(target: Record<string, unknown>, defaults: Record<string, unknown>): Record<string, unknown> {\n\tconst result = { ...defaults };\n\tfor (const key of Object.keys(target)) {\n\t\tconst targetVal = target[key];\n\t\tconst defaultVal = defaults[key];\n\t\tif (\n\t\t\ttargetVal !== undefined &&\n\t\t\ttargetVal !== null &&\n\t\t\ttypeof targetVal === \"object\" &&\n\t\t\t!Array.isArray(targetVal) &&\n\t\t\ttypeof defaultVal === \"object\" &&\n\t\t\tdefaultVal !== null &&\n\t\t\t!Array.isArray(defaultVal)\n\t\t) {\n\t\t\tresult[key] = deepMerge(targetVal as Record<string, unknown>, defaultVal as Record<string, unknown>);\n\t\t} else if (targetVal !== undefined) {\n\t\t\tresult[key] = targetVal;\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Manages .vibe/ directory creation, feature state machine, project config loading,\n * and standard path resolution.\n */\nexport class VibeStore {\n\tprivate readonly vibeDir: string;\n\tprivate readonly featuresDir: string;\n\tprivate readonly standardsDir: string;\n\tprivate readonly log: ModuleLogger;\n\n\tconstructor(\n\t\tprivate readonly projectRoot: string,\n\t\tlogger?: VibeLogger,\n\t) {\n\t\tthis.vibeDir = join(projectRoot, \".vibe\");\n\t\tthis.featuresDir = join(this.vibeDir, \"features\");\n\t\tthis.standardsDir = join(this.vibeDir, \"standards\");\n\t\tthis.log = createModuleLogger(logger ?? noopLogger, \"store\");\n\t}\n\n\t/** Returns the project root path. */\n\tgetProjectRoot(): string {\n\t\treturn this.projectRoot;\n\t}\n\n\t// ─── Directory ───────────────────────────────────────────────────────────\n\n\t/** Initializes the .vibe/ directory structure. */\n\tasync init(): Promise<void> {\n\t\tawait mkdir(this.featuresDir, { recursive: true });\n\t\tawait mkdir(this.standardsDir, { recursive: true });\n\t\tawait mkdir(this.getSkillsDir(), { recursive: true });\n\n\t\tconst configPath = join(this.vibeDir, \"config.json\");\n\t\tif (!(await this.fileExists(configPath))) {\n\t\t\tawait writeFile(configPath, `${JSON.stringify(DEFAULT_CONFIG, null, \"\\t\")}\\n`, \"utf-8\");\n\t\t}\n\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tif (!(await this.fileExists(planPath))) {\n\t\t\tconst emptyPlan: PlanData = {\n\t\t\t\tproject: \"\",\n\t\t\t\tdescription: \"\",\n\t\t\t\tworkflowType: \"new_feature\",\n\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t\tupdatedAt: new Date().toISOString(),\n\t\t\t\tfeatures: [],\n\t\t\t\tdependencyGraph: {},\n\t\t\t};\n\t\t\tawait writeFile(planPath, `${JSON.stringify(emptyPlan, null, \"\\t\")}\\n`, \"utf-8\");\n\t\t}\n\n\t\tconst architecturePath = join(this.vibeDir, \"architecture.md\");\n\t\tif (!(await this.fileExists(architecturePath))) {\n\t\t\tawait writeFile(architecturePath, \"# Architecture\\n\", \"utf-8\");\n\t\t}\n\n\t\tconst gitignorePath = join(this.vibeDir, \".gitignore\");\n\t\tif (!(await this.fileExists(gitignorePath))) {\n\t\t\tawait writeFile(gitignorePath, VIBE_GITIGNORE_CONTENT, \"utf-8\");\n\t\t}\n\t}\n\n\t/** Check if .vibe/ directory has been initialized. */\n\tasync isInitialized(): Promise<boolean> {\n\t\treturn this.fileExists(this.vibeDir);\n\t}\n\n\tgetVibeDir(): string {\n\t\treturn this.vibeDir;\n\t}\n\n\tgetFeaturesDir(): string {\n\t\treturn this.featuresDir;\n\t}\n\n\tgetStandardsDir(): string {\n\t\treturn this.standardsDir;\n\t}\n\n\tgetFeatureDir(featureId: string): string {\n\t\treturn join(this.featuresDir, featureId);\n\t}\n\n\t/** Lists all feature IDs (directory names under features/). */\n\tasync listFeatures(): Promise<string[]> {\n\t\tif (!(await this.fileExists(this.featuresDir))) {\n\t\t\treturn [];\n\t\t}\n\t\tconst entries = await readdir(this.featuresDir, { withFileTypes: true });\n\t\treturn entries\n\t\t\t.filter((e) => e.isDirectory())\n\t\t\t.map((e) => e.name)\n\t\t\t.sort();\n\t}\n\n\t/** Creates the feature directory if it doesn't exist and returns the path. */\n\tasync ensureFeatureDir(featureId: string): Promise<string> {\n\t\tconst dir = this.getFeatureDir(featureId);\n\t\tawait mkdir(dir, { recursive: true });\n\t\treturn dir;\n\t}\n\n\t// ─── Config ──────────────────────────────────────────────────────────────\n\n\t/** Reads config.json and returns a complete VibeConfig merged with defaults. */\n\tasync loadConfig(): Promise<VibeConfig> {\n\t\tconst configPath = join(this.vibeDir, \"config.json\");\n\t\tif (!(await this.fileExists(configPath))) {\n\t\t\treturn { ...DEFAULT_CONFIG };\n\t\t}\n\t\tconst raw = await readFile(configPath, \"utf-8\");\n\t\tconst partial = JSON.parse(raw) as Record<string, unknown>;\n\t\treturn deepMerge(partial, DEFAULT_CONFIG as unknown as Record<string, unknown>) as unknown as VibeConfig;\n\t}\n\n\t/** Saves configuration to config.json. */\n\tasync saveConfig(config: VibeConfig): Promise<void> {\n\t\tconst configPath = join(this.vibeDir, \"config.json\");\n\t\tawait writeFile(configPath, `${JSON.stringify(config, null, \"\\t\")}\\n`, \"utf-8\");\n\t}\n\n\t// ─── Plan ────────────────────────────────────────────────────────────────\n\n\t/** Reads plan.json. */\n\t/** Checks if a meaningful plan exists. Returns true if plan.json exists and has at least one feature. */\n\tasync hasPlan(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst raw = await readFile(join(this.vibeDir, \"plan.json\"), \"utf-8\");\n\t\t\tconst plan = JSON.parse(raw) as PlanData;\n\t\t\treturn plan.features.length > 0;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tasync loadPlan(): Promise<PlanData> {\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tconst raw = await readFile(planPath, \"utf-8\");\n\t\treturn JSON.parse(raw) as PlanData;\n\t}\n\n\t/** Writes plan.json. */\n\tasync savePlan(plan: PlanData): Promise<void> {\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tawait writeFile(planPath, `${JSON.stringify(plan, null, \"\\t\")}\\n`, \"utf-8\");\n\t}\n\n\t// ─── Feature Status ──────────────────────────────────────────────────────\n\n\t/** Reads the feature's status.json. */\n\tasync loadFeatureStatus(featureId: string): Promise<FeatureStatus> {\n\t\tconst statusPath = join(this.getFeatureDir(featureId), \"status.json\");\n\t\tconst raw = await readFile(statusPath, \"utf-8\");\n\t\treturn JSON.parse(raw) as FeatureStatus;\n\t}\n\n\t/**\n\t * Updates feature status. Validates state transitions and syncs status.json with plan.json.\n\t * Auto-creates the feature directory and status.json if they don't exist.\n\t */\n\tasync updateFeatureStatus(featureId: string, newStatus: FeatureStatusValue): Promise<void> {\n\t\tthis.log.debug(`Updating feature status: ${featureId} → ${newStatus}`, { featureId, newStatus });\n\t\tawait this.ensureFeatureDir(featureId);\n\t\tconst statusPath = join(this.getFeatureDir(featureId), \"status.json\");\n\n\t\tlet currentStatus: FeatureStatus;\n\t\tif (await this.fileExists(statusPath)) {\n\t\t\tconst raw = await readFile(statusPath, \"utf-8\");\n\t\t\tcurrentStatus = JSON.parse(raw) as FeatureStatus;\n\n\t\t\t// Idempotent: same-state transition is a no-op\n\t\t\tif (currentStatus.status === newStatus) {\n\t\t\t\tthis.log.debug(`Status already \"${newStatus}\", skipping transition`, { featureId });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst allowed = VALID_TRANSITIONS[currentStatus.status];\n\t\t\tif (!allowed.includes(newStatus)) {\n\t\t\t\tthis.log.warn(`Invalid state transition: \"${currentStatus.status}\" → \"${newStatus}\"`, { featureId });\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid state transition: \"${currentStatus.status}\" → \"${newStatus}\" for feature \"${featureId}\". Allowed transitions: [${allowed.join(\", \")}]`,\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tcurrentStatus = {\n\t\t\t\tstatus: \"planned\",\n\t\t\t\tupdatedAt: new Date().toISOString(),\n\t\t\t};\n\t\t\t// New features can only start from planned. Validate planned → newStatus transition.\n\t\t\tif (newStatus !== \"planned\") {\n\t\t\t\tconst allowed = VALID_TRANSITIONS.planned;\n\t\t\t\tif (!allowed.includes(newStatus)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Invalid state transition: \"planned\" → \"${newStatus}\" for new feature \"${featureId}\". Allowed transitions: [${allowed.join(\", \")}]`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst updated: FeatureStatus = {\n\t\t\tstatus: newStatus,\n\t\t\tupdatedAt: new Date().toISOString(),\n\t\t};\n\t\tawait writeFile(statusPath, `${JSON.stringify(updated, null, \"\\t\")}\\n`, \"utf-8\");\n\n\t\t// Sync with plan.json\n\t\tawait this.syncPlanFeatureStatus(featureId, newStatus);\n\t}\n\n\t/** Syncs the feature's status within plan.json. */\n\tprivate async syncPlanFeatureStatus(featureId: string, status: FeatureStatusValue): Promise<void> {\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tif (!(await this.fileExists(planPath))) {\n\t\t\treturn;\n\t\t}\n\t\tconst plan = await this.loadPlan();\n\t\tconst feature = plan.features.find((f) => f.featureId === featureId);\n\t\tif (feature) {\n\t\t\tfeature.status = status;\n\t\t\tplan.updatedAt = new Date().toISOString();\n\t\t\tawait this.savePlan(plan);\n\t\t}\n\t}\n\n\t// ─── Artifacts ───────────────────────────────────────────────────────────\n\n\t/** Returns the absolute path for an artifact file. */\n\tgetArtifactPath(featureId: string, artifact: ArtifactName): string {\n\t\treturn join(this.getFeatureDir(featureId), artifact);\n\t}\n\n\t/** Checks if an artifact file exists. */\n\tasync hasArtifact(featureId: string, artifact: ArtifactName): Promise<boolean> {\n\t\treturn this.fileExists(this.getArtifactPath(featureId, artifact));\n\t}\n\n\t/** Reads an artifact file. */\n\tasync readArtifact(featureId: string, artifact: ArtifactName): Promise<string> {\n\t\treturn readFile(this.getArtifactPath(featureId, artifact), \"utf-8\");\n\t}\n\n\t/** Writes an artifact file. Auto-creates the feature directory if missing. */\n\tasync writeArtifact(featureId: string, artifact: ArtifactName, content: string): Promise<void> {\n\t\tthis.log.debug(`Writing artifact: ${artifact}`, { featureId });\n\t\tawait this.ensureFeatureDir(featureId);\n\t\tawait writeFile(this.getArtifactPath(featureId, artifact), content, \"utf-8\");\n\t}\n\n\t/** Writes a global artifact file to the .vibe/ root. */\n\tasync writeGlobalArtifact(filename: string, content: string): Promise<void> {\n\t\tawait writeFile(join(this.vibeDir, filename), content, \"utf-8\");\n\t}\n\n\t/** Reads a global artifact file from the .vibe/ root. */\n\tasync readGlobalArtifact(filename: string): Promise<string> {\n\t\treturn readFile(join(this.vibeDir, filename), \"utf-8\");\n\t}\n\n\t/** Checks if a global artifact file exists. */\n\tasync hasGlobalArtifact(filename: string): Promise<boolean> {\n\t\treturn this.fileExists(join(this.vibeDir, filename));\n\t}\n\n\t// ─── Standards ───────────────────────────────────────────────────────────\n\n\t/** Returns a list of .md files in .vibe/standards/ (filenames only). */\n\tasync listStandardFiles(): Promise<string[]> {\n\t\tif (!(await this.fileExists(this.standardsDir))) {\n\t\t\treturn [];\n\t\t}\n\t\tconst entries = await readdir(this.standardsDir);\n\t\treturn entries.filter((e) => e.endsWith(\".md\")).sort();\n\t}\n\n\t/** Resolves a standards source path to an absolute path. */\n\tresolveStandardSource(source: string): string {\n\t\tif (isAbsolute(source)) {\n\t\t\treturn source;\n\t\t}\n\t\treturn resolve(this.projectRoot, source);\n\t}\n\n\t/** Checks if a standard file exists in .vibe/standards/. */\n\tasync hasStandardFile(fileName: string): Promise<boolean> {\n\t\treturn this.fileExists(join(this.standardsDir, fileName));\n\t}\n\n\t/** Reads all standard files and returns them as Map<filename, content>. */\n\tasync readAllStandards(): Promise<Map<string, string>> {\n\t\tconst files = await this.listStandardFiles();\n\t\tconst result = new Map<string, string>();\n\t\tfor (const fileName of files) {\n\t\t\tconst content = await readFile(join(this.standardsDir, fileName), \"utf-8\");\n\t\t\tresult.set(fileName, content);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/** Writes a single standard file. */\n\tasync writeStandard(fileName: string, content: string): Promise<void> {\n\t\tawait writeFile(join(this.standardsDir, fileName), content, \"utf-8\");\n\t}\n\n\t// ─── Requirements ────────────────────────────────────────────────────────\n\n\t/** Returns the path to .vibe/requirements.md. */\n\tgetRequirementsPath(): string {\n\t\treturn join(this.vibeDir, \"requirements.md\");\n\t}\n\n\t/** Checks if requirements.md exists. */\n\tasync hasRequirements(): Promise<boolean> {\n\t\treturn this.fileExists(this.getRequirementsPath());\n\t}\n\n\t/** Reads requirements.md. */\n\tasync readRequirements(): Promise<string> {\n\t\treturn readFile(this.getRequirementsPath(), \"utf-8\");\n\t}\n\n\t/** Writes requirements.md. */\n\tasync writeRequirements(content: string): Promise<void> {\n\t\tawait writeFile(this.getRequirementsPath(), content, \"utf-8\");\n\t}\n\n\t/** Deletes requirements.md. */\n\tasync clearRequirements(): Promise<void> {\n\t\tconst filePath = this.getRequirementsPath();\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t// ─── System Design ───────────────────────────────────────────────────────\n\n\t/** Returns the path to .vibe/system-design.md. */\n\tgetSystemDesignPath(): string {\n\t\treturn join(this.vibeDir, \"system-design.md\");\n\t}\n\n\t/** Checks if system-design.md exists. */\n\tasync hasSystemDesign(): Promise<boolean> {\n\t\treturn this.fileExists(this.getSystemDesignPath());\n\t}\n\n\t/** Reads system-design.md. */\n\tasync readSystemDesign(): Promise<string> {\n\t\treturn readFile(this.getSystemDesignPath(), \"utf-8\");\n\t}\n\n\t/** Writes system-design.md. */\n\tasync writeSystemDesign(content: string): Promise<void> {\n\t\tawait writeFile(this.getSystemDesignPath(), content, \"utf-8\");\n\t}\n\n\t/** Deletes system-design.md. */\n\tasync clearSystemDesign(): Promise<void> {\n\t\tconst filePath = this.getSystemDesignPath();\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t/** Deletes plan.json. */\n\tasync clearPlan(): Promise<void> {\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tif (await this.fileExists(planPath)) {\n\t\t\tawait unlink(planPath);\n\t\t}\n\t}\n\n\t/** Recursively deletes the entire feature directory. */\n\tasync clearFeatureDir(featureId: string): Promise<void> {\n\t\tconst dir = this.getFeatureDir(featureId);\n\t\tif (await this.fileExists(dir)) {\n\t\t\tawait rm(dir, { recursive: true, force: true });\n\t\t}\n\t}\n\n\t/** Deletes all feature directories under features/. */\n\tasync clearAllFeatures(): Promise<void> {\n\t\tconst dir = this.getFeaturesDir();\n\t\tif (!(await this.fileExists(dir))) return;\n\t\tconst entries = await readdir(dir);\n\t\tfor (const entry of entries) {\n\t\t\tawait rm(join(dir, entry), { recursive: true, force: true });\n\t\t}\n\t}\n\n\t/** Deletes global agent history by role name. (e.g., \"discovery\" → discovery-*.json) */\n\tasync clearGlobalAgentHistoryByRole(role: string): Promise<void> {\n\t\tconst dir = this.getGlobalAgentHistoryDir();\n\t\tif (!(await this.fileExists(dir))) return;\n\t\tconst entries = await readdir(dir);\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.startsWith(`${role}-`) && entry.endsWith(\".json\")) {\n\t\t\t\tawait unlink(join(dir, entry));\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Deletes a global artifact. */\n\tasync clearGlobalArtifact(filename: string): Promise<void> {\n\t\tconst filePath = join(this.vibeDir, filename);\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t// ─── Project Context ─────────────────────────────────────────────────────\n\n\t/** Returns the path to .vibe/project-context.md. */\n\tgetProjectContextPath(): string {\n\t\treturn join(this.vibeDir, \"project-context.md\");\n\t}\n\n\t/** Checks if project-context.md exists. */\n\tasync hasProjectContext(): Promise<boolean> {\n\t\treturn this.fileExists(this.getProjectContextPath());\n\t}\n\n\t/** Reads project-context.md. */\n\tasync readProjectContext(): Promise<string> {\n\t\treturn readFile(this.getProjectContextPath(), \"utf-8\");\n\t}\n\n\t/** Writes project-context.md. */\n\tasync writeProjectContext(content: string): Promise<void> {\n\t\tawait writeFile(this.getProjectContextPath(), content, \"utf-8\");\n\t}\n\n\t/** Checks if project-context.md is older than staleThresholdDays. */\n\tasync isProjectContextStale(thresholdDays: number): Promise<boolean> {\n\t\tconst contextPath = this.getProjectContextPath();\n\t\tif (!(await this.fileExists(contextPath))) {\n\t\t\treturn true;\n\t\t}\n\t\tconst fileStat = await stat(contextPath);\n\t\tconst ageMs = Date.now() - fileStat.mtimeMs;\n\t\tconst ageDays = ageMs / (1000 * 60 * 60 * 24);\n\t\treturn ageDays > thresholdDays;\n\t}\n\n\t// ─── Agent History (Feature Level) ───────────────────────────────────────\n\n\t/** Returns the agent history directory path for a feature. */\n\tgetAgentHistoryDir(featureId: string): string {\n\t\treturn join(this.getFeatureDir(featureId), \"agent-history\");\n\t}\n\n\t/** Returns the agent history file path. */\n\tgetAgentHistoryPath(featureId: string, role: string, action: string): string {\n\t\treturn join(this.getAgentHistoryDir(featureId), `${role}-${action}.json`);\n\t}\n\n\t/** Saves agent history. Auto-creates the directory if missing. */\n\tasync saveAgentHistory(featureId: string, checkpoint: AgentCheckpoint): Promise<void> {\n\t\tthis.log.debug(`Saving agent history: ${checkpoint.role}:${checkpoint.action}`, { featureId });\n\t\tconst dir = this.getAgentHistoryDir(featureId);\n\t\tawait mkdir(dir, { recursive: true });\n\t\tconst filePath = this.getAgentHistoryPath(featureId, checkpoint.role, checkpoint.action);\n\t\tawait writeFile(filePath, JSON.stringify(checkpoint, null, \"\\t\"), \"utf-8\");\n\t}\n\n\t/** Loads agent history. Returns null if not found. */\n\tasync loadAgentHistory(featureId: string, role: string, action: string): Promise<AgentCheckpoint | null> {\n\t\tconst filePath = this.getAgentHistoryPath(featureId, role, action);\n\t\tif (!(await this.fileExists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst raw = await readFile(filePath, \"utf-8\");\n\t\treturn JSON.parse(raw) as AgentCheckpoint;\n\t}\n\n\t/** Checks if agent history exists. */\n\tasync hasAgentHistory(featureId: string, role: string, action: string): Promise<boolean> {\n\t\treturn this.fileExists(this.getAgentHistoryPath(featureId, role, action));\n\t}\n\n\t/**\n\t * Loads prior action histories for the same role in chronological order.\n\t * Excludes the currentAction's own history (separated from retry checkpointing).\n\t */\n\tasync loadPriorAgentHistory(featureId: string, role: string, currentAction: string): Promise<AgentCheckpoint[]> {\n\t\tconst dir = this.getAgentHistoryDir(featureId);\n\t\tif (!(await this.fileExists(dir))) return [];\n\n\t\tconst entries = await readdir(dir);\n\t\tconst prefix = `${role}-`;\n\t\tconst checkpoints: AgentCheckpoint[] = [];\n\n\t\tfor (const entry of entries) {\n\t\t\tif (!entry.startsWith(prefix) || !entry.endsWith(\".json\")) continue;\n\t\t\tconst action = entry.slice(prefix.length, -5);\n\t\t\tif (action === currentAction) continue;\n\n\t\t\tconst raw = await readFile(join(dir, entry), \"utf-8\");\n\t\t\tcheckpoints.push(JSON.parse(raw) as AgentCheckpoint);\n\t\t}\n\n\t\treturn checkpoints.sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n\t}\n\n\t/** Returns all agent history filenames for a feature. */\n\tasync listAgentHistory(featureId: string): Promise<string[]> {\n\t\tconst dir = this.getAgentHistoryDir(featureId);\n\t\tif (!(await this.fileExists(dir))) {\n\t\t\treturn [];\n\t\t}\n\t\tconst entries = await readdir(dir);\n\t\treturn entries.filter((e) => e.endsWith(\".json\")).sort();\n\t}\n\n\t// ─── Agent History (Global Level) ────────────────────────────────────────\n\n\t/** Returns the project-level agent history directory path. */\n\tgetGlobalAgentHistoryDir(): string {\n\t\treturn join(this.vibeDir, \"agent-history\");\n\t}\n\n\t/** Returns the project-level agent history file path. */\n\tgetGlobalAgentHistoryPath(role: string, action: string): string {\n\t\treturn join(this.getGlobalAgentHistoryDir(), `${role}-${action}.json`);\n\t}\n\n\t/** Saves project-level agent history. */\n\tasync saveGlobalAgentHistory(checkpoint: AgentCheckpoint): Promise<void> {\n\t\tconst dir = this.getGlobalAgentHistoryDir();\n\t\tawait mkdir(dir, { recursive: true });\n\t\tconst filePath = this.getGlobalAgentHistoryPath(checkpoint.role, checkpoint.action);\n\t\tawait writeFile(filePath, JSON.stringify(checkpoint, null, \"\\t\"), \"utf-8\");\n\t}\n\n\t/** Loads project-level agent history. Returns null if not found. */\n\tasync loadGlobalAgentHistory(role: string, action: string): Promise<AgentCheckpoint | null> {\n\t\tconst filePath = this.getGlobalAgentHistoryPath(role, action);\n\t\tif (!(await this.fileExists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst raw = await readFile(filePath, \"utf-8\");\n\t\treturn JSON.parse(raw) as AgentCheckpoint;\n\t}\n\n\t/** Checks if project-level agent history exists. */\n\tasync hasGlobalAgentHistory(role: string, action: string): Promise<boolean> {\n\t\treturn this.fileExists(this.getGlobalAgentHistoryPath(role, action));\n\t}\n\n\t/** Returns a list of project-level agent history files. */\n\tasync listGlobalAgentHistory(): Promise<string[]> {\n\t\tconst dir = this.getGlobalAgentHistoryDir();\n\t\tif (!(await this.fileExists(dir))) {\n\t\t\treturn [];\n\t\t}\n\t\tconst entries = await readdir(dir);\n\t\treturn entries.filter((e) => e.endsWith(\".json\")).sort();\n\t}\n\n\t// ─── Orchestration State Persistence ─────────────────────────────────────\n\n\t/** Returns the path to orchestration-state.json. */\n\tgetOrchestrationStatePath(): string {\n\t\treturn join(this.vibeDir, \"orchestration-state.json\");\n\t}\n\n\t/** Saves orchestration state. Auto-creates .vibe/ directory if missing. */\n\tasync saveOrchestrationState(state: OrchestrationState): Promise<void> {\n\t\tawait mkdir(this.vibeDir, { recursive: true });\n\t\tawait writeFile(this.getOrchestrationStatePath(), `${JSON.stringify(state, null, \"\\t\")}\\n`, \"utf-8\");\n\t}\n\n\t/** Loads orchestration state. Returns null if not found. */\n\tasync loadOrchestrationState(): Promise<OrchestrationState | null> {\n\t\tconst filePath = this.getOrchestrationStatePath();\n\t\tif (!(await this.fileExists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst raw = await readFile(filePath, \"utf-8\");\n\t\treturn JSON.parse(raw) as OrchestrationState;\n\t}\n\n\t/** Deletes the orchestration state file. */\n\tasync clearOrchestrationState(): Promise<void> {\n\t\tconst filePath = this.getOrchestrationStatePath();\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t/** Checks if orchestration state file exists. */\n\tasync hasOrchestrationState(): Promise<boolean> {\n\t\treturn this.fileExists(this.getOrchestrationStatePath());\n\t}\n\n\t// ─── Pipeline State Persistence ──────────────────────────────────────────\n\n\t/** Returns the path to pipeline.json. */\n\tgetPipelineStatePath(featureId: string): string {\n\t\treturn join(this.getFeatureDir(featureId), \"pipeline.json\");\n\t}\n\n\t/** Saves pipeline state. */\n\tasync savePipelineState(featureId: string, state: PersistedPipeline): Promise<void> {\n\t\tawait this.ensureFeatureDir(featureId);\n\t\tawait writeFile(this.getPipelineStatePath(featureId), `${JSON.stringify(state, null, \"\\t\")}\\n`, \"utf-8\");\n\t}\n\n\t/** Loads pipeline state. Returns null if not found. */\n\tasync loadPipelineState(featureId: string): Promise<PersistedPipeline | null> {\n\t\tconst filePath = this.getPipelineStatePath(featureId);\n\t\tif (!(await this.fileExists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst raw = await readFile(filePath, \"utf-8\");\n\t\treturn JSON.parse(raw) as PersistedPipeline;\n\t}\n\n\t/** Deletes the pipeline state file. */\n\tasync clearPipelineState(featureId: string): Promise<void> {\n\t\tconst filePath = this.getPipelineStatePath(featureId);\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t// ─── Skills ──────────────────────────────────────────────────────────────\n\n\t/** Returns the path to .vibe/skills/ directory. */\n\tgetSkillsDir(): string {\n\t\treturn join(this.vibeDir, \"skills\");\n\t}\n\n\t/** Returns a list of directories under .vibe/skills/ that contain SKILL.md. */\n\tasync listSkills(): Promise<string[]> {\n\t\tconst dir = this.getSkillsDir();\n\t\tif (!(await this.fileExists(dir))) return [];\n\t\tconst entries = await readdir(dir, { withFileTypes: true });\n\t\tconst skills: string[] = [];\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tconst skillFile = join(dir, entry.name, \"SKILL.md\");\n\t\t\t\tif (await this.fileExists(skillFile)) {\n\t\t\t\t\tskills.push(entry.name);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn skills.sort();\n\t}\n\n\t/** Checks if a specific vibe skill exists. */\n\tasync hasSkill(skillName: string): Promise<boolean> {\n\t\treturn this.fileExists(join(this.getSkillsDir(), skillName, \"SKILL.md\"));\n\t}\n\n\t/** Reads the full contents of a vibe skill's SKILL.md. */\n\tasync readSkillContent(skillName: string): Promise<string> {\n\t\treturn readFile(join(this.getSkillsDir(), skillName, \"SKILL.md\"), \"utf-8\");\n\t}\n\n\t/** Extracts only the description from a vibe skill's SKILL.md frontmatter. Returns null if not found. */\n\tasync readSkillDescription(skillName: string): Promise<string | null> {\n\t\tconst content = await this.readSkillContent(skillName);\n\t\tconst match = content.match(/^---\\s*\\n([\\s\\S]*?)\\n---/);\n\t\tif (!match) return null;\n\t\tconst frontmatter = match[1];\n\t\tconst descMatch = frontmatter.match(/description:\\s*(.+)/);\n\t\treturn descMatch ? descMatch[1].trim() : null;\n\t}\n\n\t// ─── Helpers ─────────────────────────────────────────────────────────────\n\n\tprivate async fileExists(path: string): Promise<boolean> {\n\t\ttry {\n\t\t\tawait access(path);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { access, mkdir, readdir, readFile, rm, stat, unlink, writeFile } from \"node:fs/promises\";\nimport { isAbsolute, join, resolve } from \"node:path\";\nimport { createModuleLogger, type ModuleLogger, noopLogger, type VibeLogger } from \"./logger.js\";\nimport type {\n\tAgentCheckpoint,\n\tArtifactName,\n\tFeatureStatus,\n\tFeatureStatusValue,\n\tOrchestrationState,\n\tPersistedPipeline,\n\tPlanData,\n\tVibeConfig,\n} from \"./types.js\";\n\n/** Valid state transition map. */\nconst VALID_TRANSITIONS: Record<FeatureStatusValue, FeatureStatusValue[]> = {\n\tplanned: [\"designing\", \"blocked\", \"failed\"],\n\tdesigning: [\"branching\", \"implementing\", \"blocked\", \"failed\"],\n\tbranching: [\"implementing\", \"blocked\", \"failed\"],\n\timplementing: [\"testing\", \"done\", \"blocked\", \"failed\"],\n\ttesting: [\"reviewing\", \"implementing\", \"blocked\", \"failed\"],\n\treviewing: [\"done\", \"merging\", \"implementing\", \"blocked\", \"failed\"],\n\tmerging: [\"done\", \"blocked\", \"failed\"],\n\tdone: [],\n\tblocked: [\"planned\", \"designing\", \"branching\", \"implementing\", \"testing\", \"reviewing\", \"merging\", \"failed\"],\n\tfailed: [],\n};\n\n/** Default configuration. */\nconst DEFAULT_CONFIG: VibeConfig = {\n\tautonomyLevel: \"gate_auto\",\n\tgates: {\n\t\trequireRequirementsApproval: true,\n\t\trequirePlanApproval: true,\n\t\trequireDesignApproval: false,\n\t\trequireSystemDesignApproval: true,\n\t\trequireMergeApproval: true,\n\t\trequireDiagnosisApproval: true,\n\t},\n\tretry: {\n\t\tmaxTestRetries: 3,\n\t\tmaxReviewRetries: 2,\n\t\tmaxRegressionRetries: 3,\n\t\tmaxStepRetries: 2,\n\t},\n\tstandards: {\n\t\tsources: [\".vibe/standards/\"],\n\t},\n\tnotifications: {\n\t\tonStepComplete: true,\n\t\tonBlocked: true,\n\t\tonPRReady: true,\n\t\tchannel: \"terminal\",\n\t},\n\tprojectAnalysis: {\n\t\tautoAnalyzeOnInit: true,\n\t\tstaleThresholdDays: 7,\n\t\texcludePaths: [\"node_modules\", \"dist\", \".git\"],\n\t},\n\tdiscovery: {\n\t\tmaxQuestionRounds: 5,\n\t\tskipIfClear: true,\n\t},\n\tcompaction: {\n\t\tenabled: true,\n\t\treserveTokens: 16384,\n\t\tkeepRecentTokens: 20000,\n\t},\n\ttesting: {\n\t\ttestCommand: \"\",\n\t\ttestTimeout: 300,\n\t\trunExistingTests: false,\n\t\texcludePatterns: [],\n\t\tciChecks: [],\n\t},\n};\n\n/** Marker comment used to identify vibe-managed gitignore block. */\nconst VIBE_GITIGNORE_MARKER = \"# >>> vibe managed\";\nconst VIBE_GITIGNORE_MARKER_END = \"# <<< vibe managed\";\n\n/** Gitignore rules appended to project root .gitignore. */\nconst VIBE_GITIGNORE_BLOCK = `${VIBE_GITIGNORE_MARKER}\n.vibe/logs/\n.vibe/orchestration-state.json\n.vibe/requirements.md\n.vibe/project-context.md\n.vibe/agent-history/\n.vibe/features/*/agent-history/\n${VIBE_GITIGNORE_MARKER_END}`;\n\n/** Deep merges two objects. Keys missing from target are taken from defaults. */\nfunction deepMerge(target: Record<string, unknown>, defaults: Record<string, unknown>): Record<string, unknown> {\n\tconst result = { ...defaults };\n\tfor (const key of Object.keys(target)) {\n\t\tconst targetVal = target[key];\n\t\tconst defaultVal = defaults[key];\n\t\tif (\n\t\t\ttargetVal !== undefined &&\n\t\t\ttargetVal !== null &&\n\t\t\ttypeof targetVal === \"object\" &&\n\t\t\t!Array.isArray(targetVal) &&\n\t\t\ttypeof defaultVal === \"object\" &&\n\t\t\tdefaultVal !== null &&\n\t\t\t!Array.isArray(defaultVal)\n\t\t) {\n\t\t\tresult[key] = deepMerge(targetVal as Record<string, unknown>, defaultVal as Record<string, unknown>);\n\t\t} else if (targetVal !== undefined) {\n\t\t\tresult[key] = targetVal;\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Manages .vibe/ directory creation, feature state machine, project config loading,\n * and standard path resolution.\n */\nexport class VibeStore {\n\tprivate readonly vibeDir: string;\n\tprivate readonly featuresDir: string;\n\tprivate readonly standardsDir: string;\n\tprivate readonly log: ModuleLogger;\n\n\tconstructor(\n\t\tprivate readonly projectRoot: string,\n\t\tlogger?: VibeLogger,\n\t) {\n\t\tthis.vibeDir = join(projectRoot, \".vibe\");\n\t\tthis.featuresDir = join(this.vibeDir, \"features\");\n\t\tthis.standardsDir = join(this.vibeDir, \"standards\");\n\t\tthis.log = createModuleLogger(logger ?? noopLogger, \"store\");\n\t}\n\n\t/** Returns the project root path. */\n\tgetProjectRoot(): string {\n\t\treturn this.projectRoot;\n\t}\n\n\t// ─── Directory ───────────────────────────────────────────────────────────\n\n\t/** Initializes the .vibe/ directory structure. */\n\tasync init(): Promise<void> {\n\t\tawait mkdir(this.featuresDir, { recursive: true });\n\t\tawait mkdir(this.standardsDir, { recursive: true });\n\t\tconst configPath = join(this.vibeDir, \"config.json\");\n\t\tif (!(await this.fileExists(configPath))) {\n\t\t\tawait writeFile(configPath, `${JSON.stringify(DEFAULT_CONFIG, null, \"\\t\")}\\n`, \"utf-8\");\n\t\t}\n\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tif (!(await this.fileExists(planPath))) {\n\t\t\tconst emptyPlan: PlanData = {\n\t\t\t\tproject: \"\",\n\t\t\t\tdescription: \"\",\n\t\t\t\tworkflowType: \"new_feature\",\n\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t\tupdatedAt: new Date().toISOString(),\n\t\t\t\tfeatures: [],\n\t\t\t\tdependencyGraph: {},\n\t\t\t};\n\t\t\tawait writeFile(planPath, `${JSON.stringify(emptyPlan, null, \"\\t\")}\\n`, \"utf-8\");\n\t\t}\n\n\t\tawait this.ensureRootGitignore();\n\t}\n\n\t/** Check if .vibe/ directory has been initialized. */\n\tasync isInitialized(): Promise<boolean> {\n\t\treturn this.fileExists(this.vibeDir);\n\t}\n\n\tgetVibeDir(): string {\n\t\treturn this.vibeDir;\n\t}\n\n\tgetFeaturesDir(): string {\n\t\treturn this.featuresDir;\n\t}\n\n\tgetStandardsDir(): string {\n\t\treturn this.standardsDir;\n\t}\n\n\tgetFeatureDir(featureId: string): string {\n\t\treturn join(this.featuresDir, featureId);\n\t}\n\n\t/** Lists all feature IDs (directory names under features/). */\n\tasync listFeatures(): Promise<string[]> {\n\t\tif (!(await this.fileExists(this.featuresDir))) {\n\t\t\treturn [];\n\t\t}\n\t\tconst entries = await readdir(this.featuresDir, { withFileTypes: true });\n\t\treturn entries\n\t\t\t.filter((e) => e.isDirectory())\n\t\t\t.map((e) => e.name)\n\t\t\t.sort();\n\t}\n\n\t/** Creates the feature directory if it doesn't exist and returns the path. */\n\tasync ensureFeatureDir(featureId: string): Promise<string> {\n\t\tconst dir = this.getFeatureDir(featureId);\n\t\tawait mkdir(dir, { recursive: true });\n\t\treturn dir;\n\t}\n\n\t// ─── Config ──────────────────────────────────────────────────────────────\n\n\t/** Reads config.json and returns a complete VibeConfig merged with defaults. */\n\tasync loadConfig(): Promise<VibeConfig> {\n\t\tconst configPath = join(this.vibeDir, \"config.json\");\n\t\tif (!(await this.fileExists(configPath))) {\n\t\t\treturn { ...DEFAULT_CONFIG };\n\t\t}\n\t\tconst raw = await readFile(configPath, \"utf-8\");\n\t\tconst partial = JSON.parse(raw) as Record<string, unknown>;\n\t\treturn deepMerge(partial, DEFAULT_CONFIG as unknown as Record<string, unknown>) as unknown as VibeConfig;\n\t}\n\n\t/** Saves configuration to config.json. */\n\tasync saveConfig(config: VibeConfig): Promise<void> {\n\t\tconst configPath = join(this.vibeDir, \"config.json\");\n\t\tawait writeFile(configPath, `${JSON.stringify(config, null, \"\\t\")}\\n`, \"utf-8\");\n\t}\n\n\t// ─── Plan ────────────────────────────────────────────────────────────────\n\n\t/** Reads plan.json. */\n\t/** Checks if a meaningful plan exists. Returns true if plan.json exists and has at least one feature. */\n\tasync hasPlan(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst raw = await readFile(join(this.vibeDir, \"plan.json\"), \"utf-8\");\n\t\t\tconst plan = JSON.parse(raw) as PlanData;\n\t\t\treturn plan.features.length > 0;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tasync loadPlan(): Promise<PlanData> {\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tconst raw = await readFile(planPath, \"utf-8\");\n\t\treturn JSON.parse(raw) as PlanData;\n\t}\n\n\t/** Writes plan.json. */\n\tasync savePlan(plan: PlanData): Promise<void> {\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tawait writeFile(planPath, `${JSON.stringify(plan, null, \"\\t\")}\\n`, \"utf-8\");\n\t}\n\n\t// ─── Feature Status ──────────────────────────────────────────────────────\n\n\t/** Reads the feature's status.json. */\n\tasync loadFeatureStatus(featureId: string): Promise<FeatureStatus> {\n\t\tconst statusPath = join(this.getFeatureDir(featureId), \"status.json\");\n\t\tconst raw = await readFile(statusPath, \"utf-8\");\n\t\treturn JSON.parse(raw) as FeatureStatus;\n\t}\n\n\t/**\n\t * Updates feature status. Validates state transitions and syncs status.json with plan.json.\n\t * Auto-creates the feature directory and status.json if they don't exist.\n\t */\n\tasync updateFeatureStatus(featureId: string, newStatus: FeatureStatusValue): Promise<void> {\n\t\tthis.log.debug(`Updating feature status: ${featureId} → ${newStatus}`, { featureId, newStatus });\n\t\tawait this.ensureFeatureDir(featureId);\n\t\tconst statusPath = join(this.getFeatureDir(featureId), \"status.json\");\n\n\t\tlet currentStatus: FeatureStatus;\n\t\tif (await this.fileExists(statusPath)) {\n\t\t\tconst raw = await readFile(statusPath, \"utf-8\");\n\t\t\tcurrentStatus = JSON.parse(raw) as FeatureStatus;\n\n\t\t\t// Idempotent: same-state transition is a no-op\n\t\t\tif (currentStatus.status === newStatus) {\n\t\t\t\tthis.log.debug(`Status already \"${newStatus}\", skipping transition`, { featureId });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst allowed = VALID_TRANSITIONS[currentStatus.status];\n\t\t\tif (!allowed.includes(newStatus)) {\n\t\t\t\tthis.log.warn(`Invalid state transition: \"${currentStatus.status}\" → \"${newStatus}\"`, { featureId });\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid state transition: \"${currentStatus.status}\" → \"${newStatus}\" for feature \"${featureId}\". Allowed transitions: [${allowed.join(\", \")}]`,\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tcurrentStatus = {\n\t\t\t\tstatus: \"planned\",\n\t\t\t\tupdatedAt: new Date().toISOString(),\n\t\t\t};\n\t\t\t// New features can only start from planned. Validate planned → newStatus transition.\n\t\t\tif (newStatus !== \"planned\") {\n\t\t\t\tconst allowed = VALID_TRANSITIONS.planned;\n\t\t\t\tif (!allowed.includes(newStatus)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Invalid state transition: \"planned\" → \"${newStatus}\" for new feature \"${featureId}\". Allowed transitions: [${allowed.join(\", \")}]`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst updated: FeatureStatus = {\n\t\t\tstatus: newStatus,\n\t\t\tupdatedAt: new Date().toISOString(),\n\t\t};\n\t\tawait writeFile(statusPath, `${JSON.stringify(updated, null, \"\\t\")}\\n`, \"utf-8\");\n\n\t\t// Sync with plan.json\n\t\tawait this.syncPlanFeatureStatus(featureId, newStatus);\n\t}\n\n\t/** Syncs the feature's status within plan.json. */\n\tprivate async syncPlanFeatureStatus(featureId: string, status: FeatureStatusValue): Promise<void> {\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tif (!(await this.fileExists(planPath))) {\n\t\t\treturn;\n\t\t}\n\t\tconst plan = await this.loadPlan();\n\t\tconst feature = plan.features.find((f) => f.featureId === featureId);\n\t\tif (feature) {\n\t\t\tfeature.status = status;\n\t\t\tplan.updatedAt = new Date().toISOString();\n\t\t\tawait this.savePlan(plan);\n\t\t}\n\t}\n\n\t// ─── Artifacts ───────────────────────────────────────────────────────────\n\n\t/** Returns the absolute path for an artifact file. */\n\tgetArtifactPath(featureId: string, artifact: ArtifactName): string {\n\t\treturn join(this.getFeatureDir(featureId), artifact);\n\t}\n\n\t/** Checks if an artifact file exists. */\n\tasync hasArtifact(featureId: string, artifact: ArtifactName): Promise<boolean> {\n\t\treturn this.fileExists(this.getArtifactPath(featureId, artifact));\n\t}\n\n\t/** Reads an artifact file. */\n\tasync readArtifact(featureId: string, artifact: ArtifactName): Promise<string> {\n\t\treturn readFile(this.getArtifactPath(featureId, artifact), \"utf-8\");\n\t}\n\n\t/** Writes an artifact file. Auto-creates the feature directory if missing. */\n\tasync writeArtifact(featureId: string, artifact: ArtifactName, content: string): Promise<void> {\n\t\tthis.log.debug(`Writing artifact: ${artifact}`, { featureId });\n\t\tawait this.ensureFeatureDir(featureId);\n\t\tawait writeFile(this.getArtifactPath(featureId, artifact), content, \"utf-8\");\n\t}\n\n\t/** Writes a global artifact file to the .vibe/ root. */\n\tasync writeGlobalArtifact(filename: string, content: string): Promise<void> {\n\t\tawait writeFile(join(this.vibeDir, filename), content, \"utf-8\");\n\t}\n\n\t/** Reads a global artifact file from the .vibe/ root. */\n\tasync readGlobalArtifact(filename: string): Promise<string> {\n\t\treturn readFile(join(this.vibeDir, filename), \"utf-8\");\n\t}\n\n\t/** Checks if a global artifact file exists. */\n\tasync hasGlobalArtifact(filename: string): Promise<boolean> {\n\t\treturn this.fileExists(join(this.vibeDir, filename));\n\t}\n\n\t// ─── Standards ───────────────────────────────────────────────────────────\n\n\t/** Returns a list of .md files in .vibe/standards/ (filenames only). */\n\tasync listStandardFiles(): Promise<string[]> {\n\t\tif (!(await this.fileExists(this.standardsDir))) {\n\t\t\treturn [];\n\t\t}\n\t\tconst entries = await readdir(this.standardsDir);\n\t\treturn entries.filter((e) => e.endsWith(\".md\")).sort();\n\t}\n\n\t/** Resolves a standards source path to an absolute path. */\n\tresolveStandardSource(source: string): string {\n\t\tif (isAbsolute(source)) {\n\t\t\treturn source;\n\t\t}\n\t\treturn resolve(this.projectRoot, source);\n\t}\n\n\t/** Checks if a standard file exists in .vibe/standards/. */\n\tasync hasStandardFile(fileName: string): Promise<boolean> {\n\t\treturn this.fileExists(join(this.standardsDir, fileName));\n\t}\n\n\t/** Reads all standard files and returns them as Map<filename, content>. */\n\tasync readAllStandards(): Promise<Map<string, string>> {\n\t\tconst files = await this.listStandardFiles();\n\t\tconst result = new Map<string, string>();\n\t\tfor (const fileName of files) {\n\t\t\tconst content = await readFile(join(this.standardsDir, fileName), \"utf-8\");\n\t\t\tresult.set(fileName, content);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/** Writes a single standard file. */\n\tasync writeStandard(fileName: string, content: string): Promise<void> {\n\t\tawait writeFile(join(this.standardsDir, fileName), content, \"utf-8\");\n\t}\n\n\t// ─── Requirements ────────────────────────────────────────────────────────\n\n\t/** Returns the path to .vibe/requirements.md. */\n\tgetRequirementsPath(): string {\n\t\treturn join(this.vibeDir, \"requirements.md\");\n\t}\n\n\t/** Checks if requirements.md exists. */\n\tasync hasRequirements(): Promise<boolean> {\n\t\treturn this.fileExists(this.getRequirementsPath());\n\t}\n\n\t/** Reads requirements.md. */\n\tasync readRequirements(): Promise<string> {\n\t\treturn readFile(this.getRequirementsPath(), \"utf-8\");\n\t}\n\n\t/** Writes requirements.md. */\n\tasync writeRequirements(content: string): Promise<void> {\n\t\tawait writeFile(this.getRequirementsPath(), content, \"utf-8\");\n\t}\n\n\t/** Deletes requirements.md. */\n\tasync clearRequirements(): Promise<void> {\n\t\tconst filePath = this.getRequirementsPath();\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t// ─── System Design ───────────────────────────────────────────────────────\n\n\t/** Returns the path to .vibe/system-design.md. */\n\tgetSystemDesignPath(): string {\n\t\treturn join(this.vibeDir, \"system-design.md\");\n\t}\n\n\t/** Checks if system-design.md exists. */\n\tasync hasSystemDesign(): Promise<boolean> {\n\t\treturn this.fileExists(this.getSystemDesignPath());\n\t}\n\n\t/** Reads system-design.md. */\n\tasync readSystemDesign(): Promise<string> {\n\t\treturn readFile(this.getSystemDesignPath(), \"utf-8\");\n\t}\n\n\t/** Writes system-design.md. */\n\tasync writeSystemDesign(content: string): Promise<void> {\n\t\tawait writeFile(this.getSystemDesignPath(), content, \"utf-8\");\n\t}\n\n\t/** Deletes system-design.md. */\n\tasync clearSystemDesign(): Promise<void> {\n\t\tconst filePath = this.getSystemDesignPath();\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t/** Deletes plan.json. */\n\tasync clearPlan(): Promise<void> {\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tif (await this.fileExists(planPath)) {\n\t\t\tawait unlink(planPath);\n\t\t}\n\t}\n\n\t/** Recursively deletes the entire feature directory. */\n\tasync clearFeatureDir(featureId: string): Promise<void> {\n\t\tconst dir = this.getFeatureDir(featureId);\n\t\tif (await this.fileExists(dir)) {\n\t\t\tawait rm(dir, { recursive: true, force: true });\n\t\t}\n\t}\n\n\t/** Deletes all feature directories under features/. */\n\tasync clearAllFeatures(): Promise<void> {\n\t\tconst dir = this.getFeaturesDir();\n\t\tif (!(await this.fileExists(dir))) return;\n\t\tconst entries = await readdir(dir);\n\t\tfor (const entry of entries) {\n\t\t\tawait rm(join(dir, entry), { recursive: true, force: true });\n\t\t}\n\t}\n\n\t/** Deletes global agent history by role name. (e.g., \"discovery\" → discovery-*.json) */\n\tasync clearGlobalAgentHistoryByRole(role: string): Promise<void> {\n\t\tconst dir = this.getGlobalAgentHistoryDir();\n\t\tif (!(await this.fileExists(dir))) return;\n\t\tconst entries = await readdir(dir);\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.startsWith(`${role}-`) && entry.endsWith(\".json\")) {\n\t\t\t\tawait unlink(join(dir, entry));\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Deletes a global artifact. */\n\tasync clearGlobalArtifact(filename: string): Promise<void> {\n\t\tconst filePath = join(this.vibeDir, filename);\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t// ─── Project Context ─────────────────────────────────────────────────────\n\n\t/** Returns the path to .vibe/project-context.md. */\n\tgetProjectContextPath(): string {\n\t\treturn join(this.vibeDir, \"project-context.md\");\n\t}\n\n\t/** Checks if project-context.md exists. */\n\tasync hasProjectContext(): Promise<boolean> {\n\t\treturn this.fileExists(this.getProjectContextPath());\n\t}\n\n\t/** Reads project-context.md. */\n\tasync readProjectContext(): Promise<string> {\n\t\treturn readFile(this.getProjectContextPath(), \"utf-8\");\n\t}\n\n\t/** Writes project-context.md. */\n\tasync writeProjectContext(content: string): Promise<void> {\n\t\tawait writeFile(this.getProjectContextPath(), content, \"utf-8\");\n\t}\n\n\t/** Checks if project-context.md is older than staleThresholdDays. */\n\tasync isProjectContextStale(thresholdDays: number): Promise<boolean> {\n\t\tconst contextPath = this.getProjectContextPath();\n\t\tif (!(await this.fileExists(contextPath))) {\n\t\t\treturn true;\n\t\t}\n\t\tconst fileStat = await stat(contextPath);\n\t\tconst ageMs = Date.now() - fileStat.mtimeMs;\n\t\tconst ageDays = ageMs / (1000 * 60 * 60 * 24);\n\t\treturn ageDays > thresholdDays;\n\t}\n\n\t// ─── Agent History (Feature Level) ───────────────────────────────────────\n\n\t/** Returns the agent history directory path for a feature. */\n\tgetAgentHistoryDir(featureId: string): string {\n\t\treturn join(this.getFeatureDir(featureId), \"agent-history\");\n\t}\n\n\t/** Returns the agent history file path. */\n\tgetAgentHistoryPath(featureId: string, role: string, action: string): string {\n\t\treturn join(this.getAgentHistoryDir(featureId), `${role}-${action}.json`);\n\t}\n\n\t/** Saves agent history. Auto-creates the directory if missing. */\n\tasync saveAgentHistory(featureId: string, checkpoint: AgentCheckpoint): Promise<void> {\n\t\tthis.log.debug(`Saving agent history: ${checkpoint.role}:${checkpoint.action}`, { featureId });\n\t\tconst dir = this.getAgentHistoryDir(featureId);\n\t\tawait mkdir(dir, { recursive: true });\n\t\tconst filePath = this.getAgentHistoryPath(featureId, checkpoint.role, checkpoint.action);\n\t\tawait writeFile(filePath, JSON.stringify(checkpoint, null, \"\\t\"), \"utf-8\");\n\t}\n\n\t/** Loads agent history. Returns null if not found. */\n\tasync loadAgentHistory(featureId: string, role: string, action: string): Promise<AgentCheckpoint | null> {\n\t\tconst filePath = this.getAgentHistoryPath(featureId, role, action);\n\t\tif (!(await this.fileExists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst raw = await readFile(filePath, \"utf-8\");\n\t\treturn JSON.parse(raw) as AgentCheckpoint;\n\t}\n\n\t/** Checks if agent history exists. */\n\tasync hasAgentHistory(featureId: string, role: string, action: string): Promise<boolean> {\n\t\treturn this.fileExists(this.getAgentHistoryPath(featureId, role, action));\n\t}\n\n\t/**\n\t * Loads prior action histories for the same role in chronological order.\n\t * Excludes the currentAction's own history (separated from retry checkpointing).\n\t */\n\tasync loadPriorAgentHistory(featureId: string, role: string, currentAction: string): Promise<AgentCheckpoint[]> {\n\t\tconst dir = this.getAgentHistoryDir(featureId);\n\t\tif (!(await this.fileExists(dir))) return [];\n\n\t\tconst entries = await readdir(dir);\n\t\tconst prefix = `${role}-`;\n\t\tconst checkpoints: AgentCheckpoint[] = [];\n\n\t\tfor (const entry of entries) {\n\t\t\tif (!entry.startsWith(prefix) || !entry.endsWith(\".json\")) continue;\n\t\t\tconst action = entry.slice(prefix.length, -5);\n\t\t\tif (action === currentAction) continue;\n\n\t\t\tconst raw = await readFile(join(dir, entry), \"utf-8\");\n\t\t\tcheckpoints.push(JSON.parse(raw) as AgentCheckpoint);\n\t\t}\n\n\t\treturn checkpoints.sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n\t}\n\n\t/** Returns all agent history filenames for a feature. */\n\tasync listAgentHistory(featureId: string): Promise<string[]> {\n\t\tconst dir = this.getAgentHistoryDir(featureId);\n\t\tif (!(await this.fileExists(dir))) {\n\t\t\treturn [];\n\t\t}\n\t\tconst entries = await readdir(dir);\n\t\treturn entries.filter((e) => e.endsWith(\".json\")).sort();\n\t}\n\n\t// ─── Agent History (Global Level) ────────────────────────────────────────\n\n\t/** Returns the project-level agent history directory path. */\n\tgetGlobalAgentHistoryDir(): string {\n\t\treturn join(this.vibeDir, \"agent-history\");\n\t}\n\n\t/** Returns the project-level agent history file path. */\n\tgetGlobalAgentHistoryPath(role: string, action: string): string {\n\t\treturn join(this.getGlobalAgentHistoryDir(), `${role}-${action}.json`);\n\t}\n\n\t/** Saves project-level agent history. */\n\tasync saveGlobalAgentHistory(checkpoint: AgentCheckpoint): Promise<void> {\n\t\tconst dir = this.getGlobalAgentHistoryDir();\n\t\tawait mkdir(dir, { recursive: true });\n\t\tconst filePath = this.getGlobalAgentHistoryPath(checkpoint.role, checkpoint.action);\n\t\tawait writeFile(filePath, JSON.stringify(checkpoint, null, \"\\t\"), \"utf-8\");\n\t}\n\n\t/** Loads project-level agent history. Returns null if not found. */\n\tasync loadGlobalAgentHistory(role: string, action: string): Promise<AgentCheckpoint | null> {\n\t\tconst filePath = this.getGlobalAgentHistoryPath(role, action);\n\t\tif (!(await this.fileExists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst raw = await readFile(filePath, \"utf-8\");\n\t\treturn JSON.parse(raw) as AgentCheckpoint;\n\t}\n\n\t/** Checks if project-level agent history exists. */\n\tasync hasGlobalAgentHistory(role: string, action: string): Promise<boolean> {\n\t\treturn this.fileExists(this.getGlobalAgentHistoryPath(role, action));\n\t}\n\n\t/** Returns a list of project-level agent history files. */\n\tasync listGlobalAgentHistory(): Promise<string[]> {\n\t\tconst dir = this.getGlobalAgentHistoryDir();\n\t\tif (!(await this.fileExists(dir))) {\n\t\t\treturn [];\n\t\t}\n\t\tconst entries = await readdir(dir);\n\t\treturn entries.filter((e) => e.endsWith(\".json\")).sort();\n\t}\n\n\t// ─── Orchestration State Persistence ─────────────────────────────────────\n\n\t/** Returns the path to orchestration-state.json. */\n\tgetOrchestrationStatePath(): string {\n\t\treturn join(this.vibeDir, \"orchestration-state.json\");\n\t}\n\n\t/** Saves orchestration state. Auto-creates .vibe/ directory if missing. */\n\tasync saveOrchestrationState(state: OrchestrationState): Promise<void> {\n\t\tawait mkdir(this.vibeDir, { recursive: true });\n\t\tawait writeFile(this.getOrchestrationStatePath(), `${JSON.stringify(state, null, \"\\t\")}\\n`, \"utf-8\");\n\t}\n\n\t/** Loads orchestration state. Returns null if not found. */\n\tasync loadOrchestrationState(): Promise<OrchestrationState | null> {\n\t\tconst filePath = this.getOrchestrationStatePath();\n\t\tif (!(await this.fileExists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst raw = await readFile(filePath, \"utf-8\");\n\t\treturn JSON.parse(raw) as OrchestrationState;\n\t}\n\n\t/** Deletes the orchestration state file. */\n\tasync clearOrchestrationState(): Promise<void> {\n\t\tconst filePath = this.getOrchestrationStatePath();\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t/** Checks if orchestration state file exists. */\n\tasync hasOrchestrationState(): Promise<boolean> {\n\t\treturn this.fileExists(this.getOrchestrationStatePath());\n\t}\n\n\t// ─── Pipeline State Persistence ──────────────────────────────────────────\n\n\t/** Returns the path to pipeline.json. */\n\tgetPipelineStatePath(featureId: string): string {\n\t\treturn join(this.getFeatureDir(featureId), \"pipeline.json\");\n\t}\n\n\t/** Saves pipeline state. */\n\tasync savePipelineState(featureId: string, state: PersistedPipeline): Promise<void> {\n\t\tawait this.ensureFeatureDir(featureId);\n\t\tawait writeFile(this.getPipelineStatePath(featureId), `${JSON.stringify(state, null, \"\\t\")}\\n`, \"utf-8\");\n\t}\n\n\t/** Loads pipeline state. Returns null if not found. */\n\tasync loadPipelineState(featureId: string): Promise<PersistedPipeline | null> {\n\t\tconst filePath = this.getPipelineStatePath(featureId);\n\t\tif (!(await this.fileExists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst raw = await readFile(filePath, \"utf-8\");\n\t\treturn JSON.parse(raw) as PersistedPipeline;\n\t}\n\n\t/** Deletes the pipeline state file. */\n\tasync clearPipelineState(featureId: string): Promise<void> {\n\t\tconst filePath = this.getPipelineStatePath(featureId);\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t// ─── Reset ───────────────────────────────────────────────────────────────\n\n\t/** Deletes the entire .vibe/ directory and re-initializes from scratch. */\n\tasync reset(): Promise<void> {\n\t\tif (await this.fileExists(this.vibeDir)) {\n\t\t\tawait rm(this.vibeDir, { recursive: true, force: true });\n\t\t}\n\t\tawait this.init();\n\t}\n\n\t// ─── Helpers ─────────────────────────────────────────────────────────────\n\n\t/**\n\t * Ensures the project root .gitignore contains vibe-managed rules.\n\t * Appends a managed block if missing, or replaces it if already present.\n\t */\n\tprivate async ensureRootGitignore(): Promise<void> {\n\t\tconst gitignorePath = join(this.projectRoot, \".gitignore\");\n\t\tlet content = \"\";\n\t\tif (await this.fileExists(gitignorePath)) {\n\t\t\tcontent = await readFile(gitignorePath, \"utf-8\");\n\t\t}\n\n\t\tif (content.includes(VIBE_GITIGNORE_MARKER)) {\n\t\t\t// Replace existing managed block\n\t\t\tconst startIdx = content.indexOf(VIBE_GITIGNORE_MARKER);\n\t\t\tconst endIdx = content.indexOf(VIBE_GITIGNORE_MARKER_END);\n\t\t\tif (endIdx !== -1) {\n\t\t\t\tconst before = content.slice(0, startIdx);\n\t\t\t\tconst after = content.slice(endIdx + VIBE_GITIGNORE_MARKER_END.length);\n\t\t\t\tcontent = before + VIBE_GITIGNORE_BLOCK + after;\n\t\t\t}\n\t\t} else {\n\t\t\t// Append managed block\n\t\t\tconst separator = content.length > 0 && !content.endsWith(\"\\n\") ? \"\\n\\n\" : content.length > 0 ? \"\\n\" : \"\";\n\t\t\tcontent = `${content}${separator}${VIBE_GITIGNORE_BLOCK}\\n`;\n\t\t}\n\n\t\tawait writeFile(gitignorePath, content, \"utf-8\");\n\t}\n\n\tprivate async fileExists(path: string): Promise<boolean> {\n\t\ttry {\n\t\t\tawait access(path);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n}\n"]}
|
package/dist/store.js
CHANGED
|
@@ -62,17 +62,18 @@ const DEFAULT_CONFIG = {
|
|
|
62
62
|
ciChecks: [],
|
|
63
63
|
},
|
|
64
64
|
};
|
|
65
|
-
/**
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
65
|
+
/** Marker comment used to identify vibe-managed gitignore block. */
|
|
66
|
+
const VIBE_GITIGNORE_MARKER = "# >>> vibe managed";
|
|
67
|
+
const VIBE_GITIGNORE_MARKER_END = "# <<< vibe managed";
|
|
68
|
+
/** Gitignore rules appended to project root .gitignore. */
|
|
69
|
+
const VIBE_GITIGNORE_BLOCK = `${VIBE_GITIGNORE_MARKER}
|
|
70
|
+
.vibe/logs/
|
|
71
|
+
.vibe/orchestration-state.json
|
|
72
|
+
.vibe/requirements.md
|
|
73
|
+
.vibe/project-context.md
|
|
74
|
+
.vibe/agent-history/
|
|
75
|
+
.vibe/features/*/agent-history/
|
|
76
|
+
${VIBE_GITIGNORE_MARKER_END}`;
|
|
76
77
|
/** Deep merges two objects. Keys missing from target are taken from defaults. */
|
|
77
78
|
function deepMerge(target, defaults) {
|
|
78
79
|
const result = { ...defaults };
|
|
@@ -120,7 +121,6 @@ export class VibeStore {
|
|
|
120
121
|
async init() {
|
|
121
122
|
await mkdir(this.featuresDir, { recursive: true });
|
|
122
123
|
await mkdir(this.standardsDir, { recursive: true });
|
|
123
|
-
await mkdir(this.getSkillsDir(), { recursive: true });
|
|
124
124
|
const configPath = join(this.vibeDir, "config.json");
|
|
125
125
|
if (!(await this.fileExists(configPath))) {
|
|
126
126
|
await writeFile(configPath, `${JSON.stringify(DEFAULT_CONFIG, null, "\t")}\n`, "utf-8");
|
|
@@ -138,14 +138,7 @@ export class VibeStore {
|
|
|
138
138
|
};
|
|
139
139
|
await writeFile(planPath, `${JSON.stringify(emptyPlan, null, "\t")}\n`, "utf-8");
|
|
140
140
|
}
|
|
141
|
-
|
|
142
|
-
if (!(await this.fileExists(architecturePath))) {
|
|
143
|
-
await writeFile(architecturePath, "# Architecture\n", "utf-8");
|
|
144
|
-
}
|
|
145
|
-
const gitignorePath = join(this.vibeDir, ".gitignore");
|
|
146
|
-
if (!(await this.fileExists(gitignorePath))) {
|
|
147
|
-
await writeFile(gitignorePath, VIBE_GITIGNORE_CONTENT, "utf-8");
|
|
148
|
-
}
|
|
141
|
+
await this.ensureRootGitignore();
|
|
149
142
|
}
|
|
150
143
|
/** Check if .vibe/ directory has been initialized. */
|
|
151
144
|
async isInitialized() {
|
|
@@ -623,47 +616,42 @@ export class VibeStore {
|
|
|
623
616
|
await unlink(filePath);
|
|
624
617
|
}
|
|
625
618
|
}
|
|
626
|
-
// ───
|
|
627
|
-
/**
|
|
628
|
-
|
|
629
|
-
|
|
619
|
+
// ─── Reset ───────────────────────────────────────────────────────────────
|
|
620
|
+
/** Deletes the entire .vibe/ directory and re-initializes from scratch. */
|
|
621
|
+
async reset() {
|
|
622
|
+
if (await this.fileExists(this.vibeDir)) {
|
|
623
|
+
await rm(this.vibeDir, { recursive: true, force: true });
|
|
624
|
+
}
|
|
625
|
+
await this.init();
|
|
630
626
|
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
const
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
627
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────
|
|
628
|
+
/**
|
|
629
|
+
* Ensures the project root .gitignore contains vibe-managed rules.
|
|
630
|
+
* Appends a managed block if missing, or replaces it if already present.
|
|
631
|
+
*/
|
|
632
|
+
async ensureRootGitignore() {
|
|
633
|
+
const gitignorePath = join(this.projectRoot, ".gitignore");
|
|
634
|
+
let content = "";
|
|
635
|
+
if (await this.fileExists(gitignorePath)) {
|
|
636
|
+
content = await readFile(gitignorePath, "utf-8");
|
|
637
|
+
}
|
|
638
|
+
if (content.includes(VIBE_GITIGNORE_MARKER)) {
|
|
639
|
+
// Replace existing managed block
|
|
640
|
+
const startIdx = content.indexOf(VIBE_GITIGNORE_MARKER);
|
|
641
|
+
const endIdx = content.indexOf(VIBE_GITIGNORE_MARKER_END);
|
|
642
|
+
if (endIdx !== -1) {
|
|
643
|
+
const before = content.slice(0, startIdx);
|
|
644
|
+
const after = content.slice(endIdx + VIBE_GITIGNORE_MARKER_END.length);
|
|
645
|
+
content = before + VIBE_GITIGNORE_BLOCK + after;
|
|
644
646
|
}
|
|
645
647
|
}
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
/** Reads the full contents of a vibe skill's SKILL.md. */
|
|
653
|
-
async readSkillContent(skillName) {
|
|
654
|
-
return readFile(join(this.getSkillsDir(), skillName, "SKILL.md"), "utf-8");
|
|
655
|
-
}
|
|
656
|
-
/** Extracts only the description from a vibe skill's SKILL.md frontmatter. Returns null if not found. */
|
|
657
|
-
async readSkillDescription(skillName) {
|
|
658
|
-
const content = await this.readSkillContent(skillName);
|
|
659
|
-
const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
660
|
-
if (!match)
|
|
661
|
-
return null;
|
|
662
|
-
const frontmatter = match[1];
|
|
663
|
-
const descMatch = frontmatter.match(/description:\s*(.+)/);
|
|
664
|
-
return descMatch ? descMatch[1].trim() : null;
|
|
648
|
+
else {
|
|
649
|
+
// Append managed block
|
|
650
|
+
const separator = content.length > 0 && !content.endsWith("\n") ? "\n\n" : content.length > 0 ? "\n" : "";
|
|
651
|
+
content = `${content}${separator}${VIBE_GITIGNORE_BLOCK}\n`;
|
|
652
|
+
}
|
|
653
|
+
await writeFile(gitignorePath, content, "utf-8");
|
|
665
654
|
}
|
|
666
|
-
// ─── Helpers ─────────────────────────────────────────────────────────────
|
|
667
655
|
async fileExists(path) {
|
|
668
656
|
try {
|
|
669
657
|
await access(path);
|
package/dist/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { access, mkdir, readdir, readFile, rm, stat, unlink, writeFile } from \"node:fs/promises\";\nimport { isAbsolute, join, resolve } from \"node:path\";\nimport { createModuleLogger, type ModuleLogger, noopLogger, type VibeLogger } from \"./logger.js\";\nimport type {\n\tAgentCheckpoint,\n\tArtifactName,\n\tFeatureStatus,\n\tFeatureStatusValue,\n\tOrchestrationState,\n\tPersistedPipeline,\n\tPlanData,\n\tVibeConfig,\n} from \"./types.js\";\n\n/** Valid state transition map. */\nconst VALID_TRANSITIONS: Record<FeatureStatusValue, FeatureStatusValue[]> = {\n\tplanned: [\"designing\", \"blocked\", \"failed\"],\n\tdesigning: [\"branching\", \"implementing\", \"blocked\", \"failed\"],\n\tbranching: [\"implementing\", \"blocked\", \"failed\"],\n\timplementing: [\"testing\", \"done\", \"blocked\", \"failed\"],\n\ttesting: [\"reviewing\", \"implementing\", \"blocked\", \"failed\"],\n\treviewing: [\"done\", \"merging\", \"implementing\", \"blocked\", \"failed\"],\n\tmerging: [\"done\", \"blocked\", \"failed\"],\n\tdone: [],\n\tblocked: [\"planned\", \"designing\", \"branching\", \"implementing\", \"testing\", \"reviewing\", \"merging\", \"failed\"],\n\tfailed: [],\n};\n\n/** Default configuration. */\nconst DEFAULT_CONFIG: VibeConfig = {\n\tautonomyLevel: \"gate_auto\",\n\tgates: {\n\t\trequireRequirementsApproval: true,\n\t\trequirePlanApproval: true,\n\t\trequireDesignApproval: false,\n\t\trequireSystemDesignApproval: true,\n\t\trequireMergeApproval: true,\n\t\trequireDiagnosisApproval: true,\n\t},\n\tretry: {\n\t\tmaxTestRetries: 3,\n\t\tmaxReviewRetries: 2,\n\t\tmaxRegressionRetries: 3,\n\t\tmaxStepRetries: 2,\n\t},\n\tstandards: {\n\t\tsources: [\".vibe/standards/\"],\n\t},\n\tnotifications: {\n\t\tonStepComplete: true,\n\t\tonBlocked: true,\n\t\tonPRReady: true,\n\t\tchannel: \"terminal\",\n\t},\n\tprojectAnalysis: {\n\t\tautoAnalyzeOnInit: true,\n\t\tstaleThresholdDays: 7,\n\t\texcludePaths: [\"node_modules\", \"dist\", \".git\"],\n\t},\n\tdiscovery: {\n\t\tmaxQuestionRounds: 5,\n\t\tskipIfClear: true,\n\t},\n\tcompaction: {\n\t\tenabled: true,\n\t\treserveTokens: 16384,\n\t\tkeepRecentTokens: 20000,\n\t},\n\ttesting: {\n\t\ttestCommand: \"\",\n\t\ttestTimeout: 300,\n\t\trunExistingTests: false,\n\t\texcludePatterns: [],\n\t\tciChecks: [],\n\t},\n};\n\n/** Default .gitignore content for user project .vibe/ directories. */\nconst VIBE_GITIGNORE_CONTENT = `# Runtime data (not design artifacts)\nlogs/\norchestration-state.json\nrequirements.md\nproject-context.md\nfeatures/*/agent-history/\n\n# Config is project-specific, tracked\n!config.json\n`;\n\n/** Deep merges two objects. Keys missing from target are taken from defaults. */\nfunction deepMerge(target: Record<string, unknown>, defaults: Record<string, unknown>): Record<string, unknown> {\n\tconst result = { ...defaults };\n\tfor (const key of Object.keys(target)) {\n\t\tconst targetVal = target[key];\n\t\tconst defaultVal = defaults[key];\n\t\tif (\n\t\t\ttargetVal !== undefined &&\n\t\t\ttargetVal !== null &&\n\t\t\ttypeof targetVal === \"object\" &&\n\t\t\t!Array.isArray(targetVal) &&\n\t\t\ttypeof defaultVal === \"object\" &&\n\t\t\tdefaultVal !== null &&\n\t\t\t!Array.isArray(defaultVal)\n\t\t) {\n\t\t\tresult[key] = deepMerge(targetVal as Record<string, unknown>, defaultVal as Record<string, unknown>);\n\t\t} else if (targetVal !== undefined) {\n\t\t\tresult[key] = targetVal;\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Manages .vibe/ directory creation, feature state machine, project config loading,\n * and standard path resolution.\n */\nexport class VibeStore {\n\tprivate readonly vibeDir: string;\n\tprivate readonly featuresDir: string;\n\tprivate readonly standardsDir: string;\n\tprivate readonly log: ModuleLogger;\n\n\tconstructor(\n\t\tprivate readonly projectRoot: string,\n\t\tlogger?: VibeLogger,\n\t) {\n\t\tthis.vibeDir = join(projectRoot, \".vibe\");\n\t\tthis.featuresDir = join(this.vibeDir, \"features\");\n\t\tthis.standardsDir = join(this.vibeDir, \"standards\");\n\t\tthis.log = createModuleLogger(logger ?? noopLogger, \"store\");\n\t}\n\n\t/** Returns the project root path. */\n\tgetProjectRoot(): string {\n\t\treturn this.projectRoot;\n\t}\n\n\t// ─── Directory ───────────────────────────────────────────────────────────\n\n\t/** Initializes the .vibe/ directory structure. */\n\tasync init(): Promise<void> {\n\t\tawait mkdir(this.featuresDir, { recursive: true });\n\t\tawait mkdir(this.standardsDir, { recursive: true });\n\t\tawait mkdir(this.getSkillsDir(), { recursive: true });\n\n\t\tconst configPath = join(this.vibeDir, \"config.json\");\n\t\tif (!(await this.fileExists(configPath))) {\n\t\t\tawait writeFile(configPath, `${JSON.stringify(DEFAULT_CONFIG, null, \"\\t\")}\\n`, \"utf-8\");\n\t\t}\n\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tif (!(await this.fileExists(planPath))) {\n\t\t\tconst emptyPlan: PlanData = {\n\t\t\t\tproject: \"\",\n\t\t\t\tdescription: \"\",\n\t\t\t\tworkflowType: \"new_feature\",\n\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t\tupdatedAt: new Date().toISOString(),\n\t\t\t\tfeatures: [],\n\t\t\t\tdependencyGraph: {},\n\t\t\t};\n\t\t\tawait writeFile(planPath, `${JSON.stringify(emptyPlan, null, \"\\t\")}\\n`, \"utf-8\");\n\t\t}\n\n\t\tconst architecturePath = join(this.vibeDir, \"architecture.md\");\n\t\tif (!(await this.fileExists(architecturePath))) {\n\t\t\tawait writeFile(architecturePath, \"# Architecture\\n\", \"utf-8\");\n\t\t}\n\n\t\tconst gitignorePath = join(this.vibeDir, \".gitignore\");\n\t\tif (!(await this.fileExists(gitignorePath))) {\n\t\t\tawait writeFile(gitignorePath, VIBE_GITIGNORE_CONTENT, \"utf-8\");\n\t\t}\n\t}\n\n\t/** Check if .vibe/ directory has been initialized. */\n\tasync isInitialized(): Promise<boolean> {\n\t\treturn this.fileExists(this.vibeDir);\n\t}\n\n\tgetVibeDir(): string {\n\t\treturn this.vibeDir;\n\t}\n\n\tgetFeaturesDir(): string {\n\t\treturn this.featuresDir;\n\t}\n\n\tgetStandardsDir(): string {\n\t\treturn this.standardsDir;\n\t}\n\n\tgetFeatureDir(featureId: string): string {\n\t\treturn join(this.featuresDir, featureId);\n\t}\n\n\t/** Lists all feature IDs (directory names under features/). */\n\tasync listFeatures(): Promise<string[]> {\n\t\tif (!(await this.fileExists(this.featuresDir))) {\n\t\t\treturn [];\n\t\t}\n\t\tconst entries = await readdir(this.featuresDir, { withFileTypes: true });\n\t\treturn entries\n\t\t\t.filter((e) => e.isDirectory())\n\t\t\t.map((e) => e.name)\n\t\t\t.sort();\n\t}\n\n\t/** Creates the feature directory if it doesn't exist and returns the path. */\n\tasync ensureFeatureDir(featureId: string): Promise<string> {\n\t\tconst dir = this.getFeatureDir(featureId);\n\t\tawait mkdir(dir, { recursive: true });\n\t\treturn dir;\n\t}\n\n\t// ─── Config ──────────────────────────────────────────────────────────────\n\n\t/** Reads config.json and returns a complete VibeConfig merged with defaults. */\n\tasync loadConfig(): Promise<VibeConfig> {\n\t\tconst configPath = join(this.vibeDir, \"config.json\");\n\t\tif (!(await this.fileExists(configPath))) {\n\t\t\treturn { ...DEFAULT_CONFIG };\n\t\t}\n\t\tconst raw = await readFile(configPath, \"utf-8\");\n\t\tconst partial = JSON.parse(raw) as Record<string, unknown>;\n\t\treturn deepMerge(partial, DEFAULT_CONFIG as unknown as Record<string, unknown>) as unknown as VibeConfig;\n\t}\n\n\t/** Saves configuration to config.json. */\n\tasync saveConfig(config: VibeConfig): Promise<void> {\n\t\tconst configPath = join(this.vibeDir, \"config.json\");\n\t\tawait writeFile(configPath, `${JSON.stringify(config, null, \"\\t\")}\\n`, \"utf-8\");\n\t}\n\n\t// ─── Plan ────────────────────────────────────────────────────────────────\n\n\t/** Reads plan.json. */\n\t/** Checks if a meaningful plan exists. Returns true if plan.json exists and has at least one feature. */\n\tasync hasPlan(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst raw = await readFile(join(this.vibeDir, \"plan.json\"), \"utf-8\");\n\t\t\tconst plan = JSON.parse(raw) as PlanData;\n\t\t\treturn plan.features.length > 0;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tasync loadPlan(): Promise<PlanData> {\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tconst raw = await readFile(planPath, \"utf-8\");\n\t\treturn JSON.parse(raw) as PlanData;\n\t}\n\n\t/** Writes plan.json. */\n\tasync savePlan(plan: PlanData): Promise<void> {\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tawait writeFile(planPath, `${JSON.stringify(plan, null, \"\\t\")}\\n`, \"utf-8\");\n\t}\n\n\t// ─── Feature Status ──────────────────────────────────────────────────────\n\n\t/** Reads the feature's status.json. */\n\tasync loadFeatureStatus(featureId: string): Promise<FeatureStatus> {\n\t\tconst statusPath = join(this.getFeatureDir(featureId), \"status.json\");\n\t\tconst raw = await readFile(statusPath, \"utf-8\");\n\t\treturn JSON.parse(raw) as FeatureStatus;\n\t}\n\n\t/**\n\t * Updates feature status. Validates state transitions and syncs status.json with plan.json.\n\t * Auto-creates the feature directory and status.json if they don't exist.\n\t */\n\tasync updateFeatureStatus(featureId: string, newStatus: FeatureStatusValue): Promise<void> {\n\t\tthis.log.debug(`Updating feature status: ${featureId} → ${newStatus}`, { featureId, newStatus });\n\t\tawait this.ensureFeatureDir(featureId);\n\t\tconst statusPath = join(this.getFeatureDir(featureId), \"status.json\");\n\n\t\tlet currentStatus: FeatureStatus;\n\t\tif (await this.fileExists(statusPath)) {\n\t\t\tconst raw = await readFile(statusPath, \"utf-8\");\n\t\t\tcurrentStatus = JSON.parse(raw) as FeatureStatus;\n\n\t\t\t// Idempotent: same-state transition is a no-op\n\t\t\tif (currentStatus.status === newStatus) {\n\t\t\t\tthis.log.debug(`Status already \"${newStatus}\", skipping transition`, { featureId });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst allowed = VALID_TRANSITIONS[currentStatus.status];\n\t\t\tif (!allowed.includes(newStatus)) {\n\t\t\t\tthis.log.warn(`Invalid state transition: \"${currentStatus.status}\" → \"${newStatus}\"`, { featureId });\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid state transition: \"${currentStatus.status}\" → \"${newStatus}\" for feature \"${featureId}\". Allowed transitions: [${allowed.join(\", \")}]`,\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tcurrentStatus = {\n\t\t\t\tstatus: \"planned\",\n\t\t\t\tupdatedAt: new Date().toISOString(),\n\t\t\t};\n\t\t\t// New features can only start from planned. Validate planned → newStatus transition.\n\t\t\tif (newStatus !== \"planned\") {\n\t\t\t\tconst allowed = VALID_TRANSITIONS.planned;\n\t\t\t\tif (!allowed.includes(newStatus)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Invalid state transition: \"planned\" → \"${newStatus}\" for new feature \"${featureId}\". Allowed transitions: [${allowed.join(\", \")}]`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst updated: FeatureStatus = {\n\t\t\tstatus: newStatus,\n\t\t\tupdatedAt: new Date().toISOString(),\n\t\t};\n\t\tawait writeFile(statusPath, `${JSON.stringify(updated, null, \"\\t\")}\\n`, \"utf-8\");\n\n\t\t// Sync with plan.json\n\t\tawait this.syncPlanFeatureStatus(featureId, newStatus);\n\t}\n\n\t/** Syncs the feature's status within plan.json. */\n\tprivate async syncPlanFeatureStatus(featureId: string, status: FeatureStatusValue): Promise<void> {\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tif (!(await this.fileExists(planPath))) {\n\t\t\treturn;\n\t\t}\n\t\tconst plan = await this.loadPlan();\n\t\tconst feature = plan.features.find((f) => f.featureId === featureId);\n\t\tif (feature) {\n\t\t\tfeature.status = status;\n\t\t\tplan.updatedAt = new Date().toISOString();\n\t\t\tawait this.savePlan(plan);\n\t\t}\n\t}\n\n\t// ─── Artifacts ───────────────────────────────────────────────────────────\n\n\t/** Returns the absolute path for an artifact file. */\n\tgetArtifactPath(featureId: string, artifact: ArtifactName): string {\n\t\treturn join(this.getFeatureDir(featureId), artifact);\n\t}\n\n\t/** Checks if an artifact file exists. */\n\tasync hasArtifact(featureId: string, artifact: ArtifactName): Promise<boolean> {\n\t\treturn this.fileExists(this.getArtifactPath(featureId, artifact));\n\t}\n\n\t/** Reads an artifact file. */\n\tasync readArtifact(featureId: string, artifact: ArtifactName): Promise<string> {\n\t\treturn readFile(this.getArtifactPath(featureId, artifact), \"utf-8\");\n\t}\n\n\t/** Writes an artifact file. Auto-creates the feature directory if missing. */\n\tasync writeArtifact(featureId: string, artifact: ArtifactName, content: string): Promise<void> {\n\t\tthis.log.debug(`Writing artifact: ${artifact}`, { featureId });\n\t\tawait this.ensureFeatureDir(featureId);\n\t\tawait writeFile(this.getArtifactPath(featureId, artifact), content, \"utf-8\");\n\t}\n\n\t/** Writes a global artifact file to the .vibe/ root. */\n\tasync writeGlobalArtifact(filename: string, content: string): Promise<void> {\n\t\tawait writeFile(join(this.vibeDir, filename), content, \"utf-8\");\n\t}\n\n\t/** Reads a global artifact file from the .vibe/ root. */\n\tasync readGlobalArtifact(filename: string): Promise<string> {\n\t\treturn readFile(join(this.vibeDir, filename), \"utf-8\");\n\t}\n\n\t/** Checks if a global artifact file exists. */\n\tasync hasGlobalArtifact(filename: string): Promise<boolean> {\n\t\treturn this.fileExists(join(this.vibeDir, filename));\n\t}\n\n\t// ─── Standards ───────────────────────────────────────────────────────────\n\n\t/** Returns a list of .md files in .vibe/standards/ (filenames only). */\n\tasync listStandardFiles(): Promise<string[]> {\n\t\tif (!(await this.fileExists(this.standardsDir))) {\n\t\t\treturn [];\n\t\t}\n\t\tconst entries = await readdir(this.standardsDir);\n\t\treturn entries.filter((e) => e.endsWith(\".md\")).sort();\n\t}\n\n\t/** Resolves a standards source path to an absolute path. */\n\tresolveStandardSource(source: string): string {\n\t\tif (isAbsolute(source)) {\n\t\t\treturn source;\n\t\t}\n\t\treturn resolve(this.projectRoot, source);\n\t}\n\n\t/** Checks if a standard file exists in .vibe/standards/. */\n\tasync hasStandardFile(fileName: string): Promise<boolean> {\n\t\treturn this.fileExists(join(this.standardsDir, fileName));\n\t}\n\n\t/** Reads all standard files and returns them as Map<filename, content>. */\n\tasync readAllStandards(): Promise<Map<string, string>> {\n\t\tconst files = await this.listStandardFiles();\n\t\tconst result = new Map<string, string>();\n\t\tfor (const fileName of files) {\n\t\t\tconst content = await readFile(join(this.standardsDir, fileName), \"utf-8\");\n\t\t\tresult.set(fileName, content);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/** Writes a single standard file. */\n\tasync writeStandard(fileName: string, content: string): Promise<void> {\n\t\tawait writeFile(join(this.standardsDir, fileName), content, \"utf-8\");\n\t}\n\n\t// ─── Requirements ────────────────────────────────────────────────────────\n\n\t/** Returns the path to .vibe/requirements.md. */\n\tgetRequirementsPath(): string {\n\t\treturn join(this.vibeDir, \"requirements.md\");\n\t}\n\n\t/** Checks if requirements.md exists. */\n\tasync hasRequirements(): Promise<boolean> {\n\t\treturn this.fileExists(this.getRequirementsPath());\n\t}\n\n\t/** Reads requirements.md. */\n\tasync readRequirements(): Promise<string> {\n\t\treturn readFile(this.getRequirementsPath(), \"utf-8\");\n\t}\n\n\t/** Writes requirements.md. */\n\tasync writeRequirements(content: string): Promise<void> {\n\t\tawait writeFile(this.getRequirementsPath(), content, \"utf-8\");\n\t}\n\n\t/** Deletes requirements.md. */\n\tasync clearRequirements(): Promise<void> {\n\t\tconst filePath = this.getRequirementsPath();\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t// ─── System Design ───────────────────────────────────────────────────────\n\n\t/** Returns the path to .vibe/system-design.md. */\n\tgetSystemDesignPath(): string {\n\t\treturn join(this.vibeDir, \"system-design.md\");\n\t}\n\n\t/** Checks if system-design.md exists. */\n\tasync hasSystemDesign(): Promise<boolean> {\n\t\treturn this.fileExists(this.getSystemDesignPath());\n\t}\n\n\t/** Reads system-design.md. */\n\tasync readSystemDesign(): Promise<string> {\n\t\treturn readFile(this.getSystemDesignPath(), \"utf-8\");\n\t}\n\n\t/** Writes system-design.md. */\n\tasync writeSystemDesign(content: string): Promise<void> {\n\t\tawait writeFile(this.getSystemDesignPath(), content, \"utf-8\");\n\t}\n\n\t/** Deletes system-design.md. */\n\tasync clearSystemDesign(): Promise<void> {\n\t\tconst filePath = this.getSystemDesignPath();\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t/** Deletes plan.json. */\n\tasync clearPlan(): Promise<void> {\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tif (await this.fileExists(planPath)) {\n\t\t\tawait unlink(planPath);\n\t\t}\n\t}\n\n\t/** Recursively deletes the entire feature directory. */\n\tasync clearFeatureDir(featureId: string): Promise<void> {\n\t\tconst dir = this.getFeatureDir(featureId);\n\t\tif (await this.fileExists(dir)) {\n\t\t\tawait rm(dir, { recursive: true, force: true });\n\t\t}\n\t}\n\n\t/** Deletes all feature directories under features/. */\n\tasync clearAllFeatures(): Promise<void> {\n\t\tconst dir = this.getFeaturesDir();\n\t\tif (!(await this.fileExists(dir))) return;\n\t\tconst entries = await readdir(dir);\n\t\tfor (const entry of entries) {\n\t\t\tawait rm(join(dir, entry), { recursive: true, force: true });\n\t\t}\n\t}\n\n\t/** Deletes global agent history by role name. (e.g., \"discovery\" → discovery-*.json) */\n\tasync clearGlobalAgentHistoryByRole(role: string): Promise<void> {\n\t\tconst dir = this.getGlobalAgentHistoryDir();\n\t\tif (!(await this.fileExists(dir))) return;\n\t\tconst entries = await readdir(dir);\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.startsWith(`${role}-`) && entry.endsWith(\".json\")) {\n\t\t\t\tawait unlink(join(dir, entry));\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Deletes a global artifact. */\n\tasync clearGlobalArtifact(filename: string): Promise<void> {\n\t\tconst filePath = join(this.vibeDir, filename);\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t// ─── Project Context ─────────────────────────────────────────────────────\n\n\t/** Returns the path to .vibe/project-context.md. */\n\tgetProjectContextPath(): string {\n\t\treturn join(this.vibeDir, \"project-context.md\");\n\t}\n\n\t/** Checks if project-context.md exists. */\n\tasync hasProjectContext(): Promise<boolean> {\n\t\treturn this.fileExists(this.getProjectContextPath());\n\t}\n\n\t/** Reads project-context.md. */\n\tasync readProjectContext(): Promise<string> {\n\t\treturn readFile(this.getProjectContextPath(), \"utf-8\");\n\t}\n\n\t/** Writes project-context.md. */\n\tasync writeProjectContext(content: string): Promise<void> {\n\t\tawait writeFile(this.getProjectContextPath(), content, \"utf-8\");\n\t}\n\n\t/** Checks if project-context.md is older than staleThresholdDays. */\n\tasync isProjectContextStale(thresholdDays: number): Promise<boolean> {\n\t\tconst contextPath = this.getProjectContextPath();\n\t\tif (!(await this.fileExists(contextPath))) {\n\t\t\treturn true;\n\t\t}\n\t\tconst fileStat = await stat(contextPath);\n\t\tconst ageMs = Date.now() - fileStat.mtimeMs;\n\t\tconst ageDays = ageMs / (1000 * 60 * 60 * 24);\n\t\treturn ageDays > thresholdDays;\n\t}\n\n\t// ─── Agent History (Feature Level) ───────────────────────────────────────\n\n\t/** Returns the agent history directory path for a feature. */\n\tgetAgentHistoryDir(featureId: string): string {\n\t\treturn join(this.getFeatureDir(featureId), \"agent-history\");\n\t}\n\n\t/** Returns the agent history file path. */\n\tgetAgentHistoryPath(featureId: string, role: string, action: string): string {\n\t\treturn join(this.getAgentHistoryDir(featureId), `${role}-${action}.json`);\n\t}\n\n\t/** Saves agent history. Auto-creates the directory if missing. */\n\tasync saveAgentHistory(featureId: string, checkpoint: AgentCheckpoint): Promise<void> {\n\t\tthis.log.debug(`Saving agent history: ${checkpoint.role}:${checkpoint.action}`, { featureId });\n\t\tconst dir = this.getAgentHistoryDir(featureId);\n\t\tawait mkdir(dir, { recursive: true });\n\t\tconst filePath = this.getAgentHistoryPath(featureId, checkpoint.role, checkpoint.action);\n\t\tawait writeFile(filePath, JSON.stringify(checkpoint, null, \"\\t\"), \"utf-8\");\n\t}\n\n\t/** Loads agent history. Returns null if not found. */\n\tasync loadAgentHistory(featureId: string, role: string, action: string): Promise<AgentCheckpoint | null> {\n\t\tconst filePath = this.getAgentHistoryPath(featureId, role, action);\n\t\tif (!(await this.fileExists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst raw = await readFile(filePath, \"utf-8\");\n\t\treturn JSON.parse(raw) as AgentCheckpoint;\n\t}\n\n\t/** Checks if agent history exists. */\n\tasync hasAgentHistory(featureId: string, role: string, action: string): Promise<boolean> {\n\t\treturn this.fileExists(this.getAgentHistoryPath(featureId, role, action));\n\t}\n\n\t/**\n\t * Loads prior action histories for the same role in chronological order.\n\t * Excludes the currentAction's own history (separated from retry checkpointing).\n\t */\n\tasync loadPriorAgentHistory(featureId: string, role: string, currentAction: string): Promise<AgentCheckpoint[]> {\n\t\tconst dir = this.getAgentHistoryDir(featureId);\n\t\tif (!(await this.fileExists(dir))) return [];\n\n\t\tconst entries = await readdir(dir);\n\t\tconst prefix = `${role}-`;\n\t\tconst checkpoints: AgentCheckpoint[] = [];\n\n\t\tfor (const entry of entries) {\n\t\t\tif (!entry.startsWith(prefix) || !entry.endsWith(\".json\")) continue;\n\t\t\tconst action = entry.slice(prefix.length, -5);\n\t\t\tif (action === currentAction) continue;\n\n\t\t\tconst raw = await readFile(join(dir, entry), \"utf-8\");\n\t\t\tcheckpoints.push(JSON.parse(raw) as AgentCheckpoint);\n\t\t}\n\n\t\treturn checkpoints.sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n\t}\n\n\t/** Returns all agent history filenames for a feature. */\n\tasync listAgentHistory(featureId: string): Promise<string[]> {\n\t\tconst dir = this.getAgentHistoryDir(featureId);\n\t\tif (!(await this.fileExists(dir))) {\n\t\t\treturn [];\n\t\t}\n\t\tconst entries = await readdir(dir);\n\t\treturn entries.filter((e) => e.endsWith(\".json\")).sort();\n\t}\n\n\t// ─── Agent History (Global Level) ────────────────────────────────────────\n\n\t/** Returns the project-level agent history directory path. */\n\tgetGlobalAgentHistoryDir(): string {\n\t\treturn join(this.vibeDir, \"agent-history\");\n\t}\n\n\t/** Returns the project-level agent history file path. */\n\tgetGlobalAgentHistoryPath(role: string, action: string): string {\n\t\treturn join(this.getGlobalAgentHistoryDir(), `${role}-${action}.json`);\n\t}\n\n\t/** Saves project-level agent history. */\n\tasync saveGlobalAgentHistory(checkpoint: AgentCheckpoint): Promise<void> {\n\t\tconst dir = this.getGlobalAgentHistoryDir();\n\t\tawait mkdir(dir, { recursive: true });\n\t\tconst filePath = this.getGlobalAgentHistoryPath(checkpoint.role, checkpoint.action);\n\t\tawait writeFile(filePath, JSON.stringify(checkpoint, null, \"\\t\"), \"utf-8\");\n\t}\n\n\t/** Loads project-level agent history. Returns null if not found. */\n\tasync loadGlobalAgentHistory(role: string, action: string): Promise<AgentCheckpoint | null> {\n\t\tconst filePath = this.getGlobalAgentHistoryPath(role, action);\n\t\tif (!(await this.fileExists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst raw = await readFile(filePath, \"utf-8\");\n\t\treturn JSON.parse(raw) as AgentCheckpoint;\n\t}\n\n\t/** Checks if project-level agent history exists. */\n\tasync hasGlobalAgentHistory(role: string, action: string): Promise<boolean> {\n\t\treturn this.fileExists(this.getGlobalAgentHistoryPath(role, action));\n\t}\n\n\t/** Returns a list of project-level agent history files. */\n\tasync listGlobalAgentHistory(): Promise<string[]> {\n\t\tconst dir = this.getGlobalAgentHistoryDir();\n\t\tif (!(await this.fileExists(dir))) {\n\t\t\treturn [];\n\t\t}\n\t\tconst entries = await readdir(dir);\n\t\treturn entries.filter((e) => e.endsWith(\".json\")).sort();\n\t}\n\n\t// ─── Orchestration State Persistence ─────────────────────────────────────\n\n\t/** Returns the path to orchestration-state.json. */\n\tgetOrchestrationStatePath(): string {\n\t\treturn join(this.vibeDir, \"orchestration-state.json\");\n\t}\n\n\t/** Saves orchestration state. Auto-creates .vibe/ directory if missing. */\n\tasync saveOrchestrationState(state: OrchestrationState): Promise<void> {\n\t\tawait mkdir(this.vibeDir, { recursive: true });\n\t\tawait writeFile(this.getOrchestrationStatePath(), `${JSON.stringify(state, null, \"\\t\")}\\n`, \"utf-8\");\n\t}\n\n\t/** Loads orchestration state. Returns null if not found. */\n\tasync loadOrchestrationState(): Promise<OrchestrationState | null> {\n\t\tconst filePath = this.getOrchestrationStatePath();\n\t\tif (!(await this.fileExists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst raw = await readFile(filePath, \"utf-8\");\n\t\treturn JSON.parse(raw) as OrchestrationState;\n\t}\n\n\t/** Deletes the orchestration state file. */\n\tasync clearOrchestrationState(): Promise<void> {\n\t\tconst filePath = this.getOrchestrationStatePath();\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t/** Checks if orchestration state file exists. */\n\tasync hasOrchestrationState(): Promise<boolean> {\n\t\treturn this.fileExists(this.getOrchestrationStatePath());\n\t}\n\n\t// ─── Pipeline State Persistence ──────────────────────────────────────────\n\n\t/** Returns the path to pipeline.json. */\n\tgetPipelineStatePath(featureId: string): string {\n\t\treturn join(this.getFeatureDir(featureId), \"pipeline.json\");\n\t}\n\n\t/** Saves pipeline state. */\n\tasync savePipelineState(featureId: string, state: PersistedPipeline): Promise<void> {\n\t\tawait this.ensureFeatureDir(featureId);\n\t\tawait writeFile(this.getPipelineStatePath(featureId), `${JSON.stringify(state, null, \"\\t\")}\\n`, \"utf-8\");\n\t}\n\n\t/** Loads pipeline state. Returns null if not found. */\n\tasync loadPipelineState(featureId: string): Promise<PersistedPipeline | null> {\n\t\tconst filePath = this.getPipelineStatePath(featureId);\n\t\tif (!(await this.fileExists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst raw = await readFile(filePath, \"utf-8\");\n\t\treturn JSON.parse(raw) as PersistedPipeline;\n\t}\n\n\t/** Deletes the pipeline state file. */\n\tasync clearPipelineState(featureId: string): Promise<void> {\n\t\tconst filePath = this.getPipelineStatePath(featureId);\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t// ─── Skills ──────────────────────────────────────────────────────────────\n\n\t/** Returns the path to .vibe/skills/ directory. */\n\tgetSkillsDir(): string {\n\t\treturn join(this.vibeDir, \"skills\");\n\t}\n\n\t/** Returns a list of directories under .vibe/skills/ that contain SKILL.md. */\n\tasync listSkills(): Promise<string[]> {\n\t\tconst dir = this.getSkillsDir();\n\t\tif (!(await this.fileExists(dir))) return [];\n\t\tconst entries = await readdir(dir, { withFileTypes: true });\n\t\tconst skills: string[] = [];\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tconst skillFile = join(dir, entry.name, \"SKILL.md\");\n\t\t\t\tif (await this.fileExists(skillFile)) {\n\t\t\t\t\tskills.push(entry.name);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn skills.sort();\n\t}\n\n\t/** Checks if a specific vibe skill exists. */\n\tasync hasSkill(skillName: string): Promise<boolean> {\n\t\treturn this.fileExists(join(this.getSkillsDir(), skillName, \"SKILL.md\"));\n\t}\n\n\t/** Reads the full contents of a vibe skill's SKILL.md. */\n\tasync readSkillContent(skillName: string): Promise<string> {\n\t\treturn readFile(join(this.getSkillsDir(), skillName, \"SKILL.md\"), \"utf-8\");\n\t}\n\n\t/** Extracts only the description from a vibe skill's SKILL.md frontmatter. Returns null if not found. */\n\tasync readSkillDescription(skillName: string): Promise<string | null> {\n\t\tconst content = await this.readSkillContent(skillName);\n\t\tconst match = content.match(/^---\\s*\\n([\\s\\S]*?)\\n---/);\n\t\tif (!match) return null;\n\t\tconst frontmatter = match[1];\n\t\tconst descMatch = frontmatter.match(/description:\\s*(.+)/);\n\t\treturn descMatch ? descMatch[1].trim() : null;\n\t}\n\n\t// ─── Helpers ─────────────────────────────────────────────────────────────\n\n\tprivate async fileExists(path: string): Promise<boolean> {\n\t\ttry {\n\t\t\tawait access(path);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { access, mkdir, readdir, readFile, rm, stat, unlink, writeFile } from \"node:fs/promises\";\nimport { isAbsolute, join, resolve } from \"node:path\";\nimport { createModuleLogger, type ModuleLogger, noopLogger, type VibeLogger } from \"./logger.js\";\nimport type {\n\tAgentCheckpoint,\n\tArtifactName,\n\tFeatureStatus,\n\tFeatureStatusValue,\n\tOrchestrationState,\n\tPersistedPipeline,\n\tPlanData,\n\tVibeConfig,\n} from \"./types.js\";\n\n/** Valid state transition map. */\nconst VALID_TRANSITIONS: Record<FeatureStatusValue, FeatureStatusValue[]> = {\n\tplanned: [\"designing\", \"blocked\", \"failed\"],\n\tdesigning: [\"branching\", \"implementing\", \"blocked\", \"failed\"],\n\tbranching: [\"implementing\", \"blocked\", \"failed\"],\n\timplementing: [\"testing\", \"done\", \"blocked\", \"failed\"],\n\ttesting: [\"reviewing\", \"implementing\", \"blocked\", \"failed\"],\n\treviewing: [\"done\", \"merging\", \"implementing\", \"blocked\", \"failed\"],\n\tmerging: [\"done\", \"blocked\", \"failed\"],\n\tdone: [],\n\tblocked: [\"planned\", \"designing\", \"branching\", \"implementing\", \"testing\", \"reviewing\", \"merging\", \"failed\"],\n\tfailed: [],\n};\n\n/** Default configuration. */\nconst DEFAULT_CONFIG: VibeConfig = {\n\tautonomyLevel: \"gate_auto\",\n\tgates: {\n\t\trequireRequirementsApproval: true,\n\t\trequirePlanApproval: true,\n\t\trequireDesignApproval: false,\n\t\trequireSystemDesignApproval: true,\n\t\trequireMergeApproval: true,\n\t\trequireDiagnosisApproval: true,\n\t},\n\tretry: {\n\t\tmaxTestRetries: 3,\n\t\tmaxReviewRetries: 2,\n\t\tmaxRegressionRetries: 3,\n\t\tmaxStepRetries: 2,\n\t},\n\tstandards: {\n\t\tsources: [\".vibe/standards/\"],\n\t},\n\tnotifications: {\n\t\tonStepComplete: true,\n\t\tonBlocked: true,\n\t\tonPRReady: true,\n\t\tchannel: \"terminal\",\n\t},\n\tprojectAnalysis: {\n\t\tautoAnalyzeOnInit: true,\n\t\tstaleThresholdDays: 7,\n\t\texcludePaths: [\"node_modules\", \"dist\", \".git\"],\n\t},\n\tdiscovery: {\n\t\tmaxQuestionRounds: 5,\n\t\tskipIfClear: true,\n\t},\n\tcompaction: {\n\t\tenabled: true,\n\t\treserveTokens: 16384,\n\t\tkeepRecentTokens: 20000,\n\t},\n\ttesting: {\n\t\ttestCommand: \"\",\n\t\ttestTimeout: 300,\n\t\trunExistingTests: false,\n\t\texcludePatterns: [],\n\t\tciChecks: [],\n\t},\n};\n\n/** Marker comment used to identify vibe-managed gitignore block. */\nconst VIBE_GITIGNORE_MARKER = \"# >>> vibe managed\";\nconst VIBE_GITIGNORE_MARKER_END = \"# <<< vibe managed\";\n\n/** Gitignore rules appended to project root .gitignore. */\nconst VIBE_GITIGNORE_BLOCK = `${VIBE_GITIGNORE_MARKER}\n.vibe/logs/\n.vibe/orchestration-state.json\n.vibe/requirements.md\n.vibe/project-context.md\n.vibe/agent-history/\n.vibe/features/*/agent-history/\n${VIBE_GITIGNORE_MARKER_END}`;\n\n/** Deep merges two objects. Keys missing from target are taken from defaults. */\nfunction deepMerge(target: Record<string, unknown>, defaults: Record<string, unknown>): Record<string, unknown> {\n\tconst result = { ...defaults };\n\tfor (const key of Object.keys(target)) {\n\t\tconst targetVal = target[key];\n\t\tconst defaultVal = defaults[key];\n\t\tif (\n\t\t\ttargetVal !== undefined &&\n\t\t\ttargetVal !== null &&\n\t\t\ttypeof targetVal === \"object\" &&\n\t\t\t!Array.isArray(targetVal) &&\n\t\t\ttypeof defaultVal === \"object\" &&\n\t\t\tdefaultVal !== null &&\n\t\t\t!Array.isArray(defaultVal)\n\t\t) {\n\t\t\tresult[key] = deepMerge(targetVal as Record<string, unknown>, defaultVal as Record<string, unknown>);\n\t\t} else if (targetVal !== undefined) {\n\t\t\tresult[key] = targetVal;\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Manages .vibe/ directory creation, feature state machine, project config loading,\n * and standard path resolution.\n */\nexport class VibeStore {\n\tprivate readonly vibeDir: string;\n\tprivate readonly featuresDir: string;\n\tprivate readonly standardsDir: string;\n\tprivate readonly log: ModuleLogger;\n\n\tconstructor(\n\t\tprivate readonly projectRoot: string,\n\t\tlogger?: VibeLogger,\n\t) {\n\t\tthis.vibeDir = join(projectRoot, \".vibe\");\n\t\tthis.featuresDir = join(this.vibeDir, \"features\");\n\t\tthis.standardsDir = join(this.vibeDir, \"standards\");\n\t\tthis.log = createModuleLogger(logger ?? noopLogger, \"store\");\n\t}\n\n\t/** Returns the project root path. */\n\tgetProjectRoot(): string {\n\t\treturn this.projectRoot;\n\t}\n\n\t// ─── Directory ───────────────────────────────────────────────────────────\n\n\t/** Initializes the .vibe/ directory structure. */\n\tasync init(): Promise<void> {\n\t\tawait mkdir(this.featuresDir, { recursive: true });\n\t\tawait mkdir(this.standardsDir, { recursive: true });\n\t\tconst configPath = join(this.vibeDir, \"config.json\");\n\t\tif (!(await this.fileExists(configPath))) {\n\t\t\tawait writeFile(configPath, `${JSON.stringify(DEFAULT_CONFIG, null, \"\\t\")}\\n`, \"utf-8\");\n\t\t}\n\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tif (!(await this.fileExists(planPath))) {\n\t\t\tconst emptyPlan: PlanData = {\n\t\t\t\tproject: \"\",\n\t\t\t\tdescription: \"\",\n\t\t\t\tworkflowType: \"new_feature\",\n\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t\tupdatedAt: new Date().toISOString(),\n\t\t\t\tfeatures: [],\n\t\t\t\tdependencyGraph: {},\n\t\t\t};\n\t\t\tawait writeFile(planPath, `${JSON.stringify(emptyPlan, null, \"\\t\")}\\n`, \"utf-8\");\n\t\t}\n\n\t\tawait this.ensureRootGitignore();\n\t}\n\n\t/** Check if .vibe/ directory has been initialized. */\n\tasync isInitialized(): Promise<boolean> {\n\t\treturn this.fileExists(this.vibeDir);\n\t}\n\n\tgetVibeDir(): string {\n\t\treturn this.vibeDir;\n\t}\n\n\tgetFeaturesDir(): string {\n\t\treturn this.featuresDir;\n\t}\n\n\tgetStandardsDir(): string {\n\t\treturn this.standardsDir;\n\t}\n\n\tgetFeatureDir(featureId: string): string {\n\t\treturn join(this.featuresDir, featureId);\n\t}\n\n\t/** Lists all feature IDs (directory names under features/). */\n\tasync listFeatures(): Promise<string[]> {\n\t\tif (!(await this.fileExists(this.featuresDir))) {\n\t\t\treturn [];\n\t\t}\n\t\tconst entries = await readdir(this.featuresDir, { withFileTypes: true });\n\t\treturn entries\n\t\t\t.filter((e) => e.isDirectory())\n\t\t\t.map((e) => e.name)\n\t\t\t.sort();\n\t}\n\n\t/** Creates the feature directory if it doesn't exist and returns the path. */\n\tasync ensureFeatureDir(featureId: string): Promise<string> {\n\t\tconst dir = this.getFeatureDir(featureId);\n\t\tawait mkdir(dir, { recursive: true });\n\t\treturn dir;\n\t}\n\n\t// ─── Config ──────────────────────────────────────────────────────────────\n\n\t/** Reads config.json and returns a complete VibeConfig merged with defaults. */\n\tasync loadConfig(): Promise<VibeConfig> {\n\t\tconst configPath = join(this.vibeDir, \"config.json\");\n\t\tif (!(await this.fileExists(configPath))) {\n\t\t\treturn { ...DEFAULT_CONFIG };\n\t\t}\n\t\tconst raw = await readFile(configPath, \"utf-8\");\n\t\tconst partial = JSON.parse(raw) as Record<string, unknown>;\n\t\treturn deepMerge(partial, DEFAULT_CONFIG as unknown as Record<string, unknown>) as unknown as VibeConfig;\n\t}\n\n\t/** Saves configuration to config.json. */\n\tasync saveConfig(config: VibeConfig): Promise<void> {\n\t\tconst configPath = join(this.vibeDir, \"config.json\");\n\t\tawait writeFile(configPath, `${JSON.stringify(config, null, \"\\t\")}\\n`, \"utf-8\");\n\t}\n\n\t// ─── Plan ────────────────────────────────────────────────────────────────\n\n\t/** Reads plan.json. */\n\t/** Checks if a meaningful plan exists. Returns true if plan.json exists and has at least one feature. */\n\tasync hasPlan(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst raw = await readFile(join(this.vibeDir, \"plan.json\"), \"utf-8\");\n\t\t\tconst plan = JSON.parse(raw) as PlanData;\n\t\t\treturn plan.features.length > 0;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tasync loadPlan(): Promise<PlanData> {\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tconst raw = await readFile(planPath, \"utf-8\");\n\t\treturn JSON.parse(raw) as PlanData;\n\t}\n\n\t/** Writes plan.json. */\n\tasync savePlan(plan: PlanData): Promise<void> {\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tawait writeFile(planPath, `${JSON.stringify(plan, null, \"\\t\")}\\n`, \"utf-8\");\n\t}\n\n\t// ─── Feature Status ──────────────────────────────────────────────────────\n\n\t/** Reads the feature's status.json. */\n\tasync loadFeatureStatus(featureId: string): Promise<FeatureStatus> {\n\t\tconst statusPath = join(this.getFeatureDir(featureId), \"status.json\");\n\t\tconst raw = await readFile(statusPath, \"utf-8\");\n\t\treturn JSON.parse(raw) as FeatureStatus;\n\t}\n\n\t/**\n\t * Updates feature status. Validates state transitions and syncs status.json with plan.json.\n\t * Auto-creates the feature directory and status.json if they don't exist.\n\t */\n\tasync updateFeatureStatus(featureId: string, newStatus: FeatureStatusValue): Promise<void> {\n\t\tthis.log.debug(`Updating feature status: ${featureId} → ${newStatus}`, { featureId, newStatus });\n\t\tawait this.ensureFeatureDir(featureId);\n\t\tconst statusPath = join(this.getFeatureDir(featureId), \"status.json\");\n\n\t\tlet currentStatus: FeatureStatus;\n\t\tif (await this.fileExists(statusPath)) {\n\t\t\tconst raw = await readFile(statusPath, \"utf-8\");\n\t\t\tcurrentStatus = JSON.parse(raw) as FeatureStatus;\n\n\t\t\t// Idempotent: same-state transition is a no-op\n\t\t\tif (currentStatus.status === newStatus) {\n\t\t\t\tthis.log.debug(`Status already \"${newStatus}\", skipping transition`, { featureId });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst allowed = VALID_TRANSITIONS[currentStatus.status];\n\t\t\tif (!allowed.includes(newStatus)) {\n\t\t\t\tthis.log.warn(`Invalid state transition: \"${currentStatus.status}\" → \"${newStatus}\"`, { featureId });\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid state transition: \"${currentStatus.status}\" → \"${newStatus}\" for feature \"${featureId}\". Allowed transitions: [${allowed.join(\", \")}]`,\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tcurrentStatus = {\n\t\t\t\tstatus: \"planned\",\n\t\t\t\tupdatedAt: new Date().toISOString(),\n\t\t\t};\n\t\t\t// New features can only start from planned. Validate planned → newStatus transition.\n\t\t\tif (newStatus !== \"planned\") {\n\t\t\t\tconst allowed = VALID_TRANSITIONS.planned;\n\t\t\t\tif (!allowed.includes(newStatus)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Invalid state transition: \"planned\" → \"${newStatus}\" for new feature \"${featureId}\". Allowed transitions: [${allowed.join(\", \")}]`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst updated: FeatureStatus = {\n\t\t\tstatus: newStatus,\n\t\t\tupdatedAt: new Date().toISOString(),\n\t\t};\n\t\tawait writeFile(statusPath, `${JSON.stringify(updated, null, \"\\t\")}\\n`, \"utf-8\");\n\n\t\t// Sync with plan.json\n\t\tawait this.syncPlanFeatureStatus(featureId, newStatus);\n\t}\n\n\t/** Syncs the feature's status within plan.json. */\n\tprivate async syncPlanFeatureStatus(featureId: string, status: FeatureStatusValue): Promise<void> {\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tif (!(await this.fileExists(planPath))) {\n\t\t\treturn;\n\t\t}\n\t\tconst plan = await this.loadPlan();\n\t\tconst feature = plan.features.find((f) => f.featureId === featureId);\n\t\tif (feature) {\n\t\t\tfeature.status = status;\n\t\t\tplan.updatedAt = new Date().toISOString();\n\t\t\tawait this.savePlan(plan);\n\t\t}\n\t}\n\n\t// ─── Artifacts ───────────────────────────────────────────────────────────\n\n\t/** Returns the absolute path for an artifact file. */\n\tgetArtifactPath(featureId: string, artifact: ArtifactName): string {\n\t\treturn join(this.getFeatureDir(featureId), artifact);\n\t}\n\n\t/** Checks if an artifact file exists. */\n\tasync hasArtifact(featureId: string, artifact: ArtifactName): Promise<boolean> {\n\t\treturn this.fileExists(this.getArtifactPath(featureId, artifact));\n\t}\n\n\t/** Reads an artifact file. */\n\tasync readArtifact(featureId: string, artifact: ArtifactName): Promise<string> {\n\t\treturn readFile(this.getArtifactPath(featureId, artifact), \"utf-8\");\n\t}\n\n\t/** Writes an artifact file. Auto-creates the feature directory if missing. */\n\tasync writeArtifact(featureId: string, artifact: ArtifactName, content: string): Promise<void> {\n\t\tthis.log.debug(`Writing artifact: ${artifact}`, { featureId });\n\t\tawait this.ensureFeatureDir(featureId);\n\t\tawait writeFile(this.getArtifactPath(featureId, artifact), content, \"utf-8\");\n\t}\n\n\t/** Writes a global artifact file to the .vibe/ root. */\n\tasync writeGlobalArtifact(filename: string, content: string): Promise<void> {\n\t\tawait writeFile(join(this.vibeDir, filename), content, \"utf-8\");\n\t}\n\n\t/** Reads a global artifact file from the .vibe/ root. */\n\tasync readGlobalArtifact(filename: string): Promise<string> {\n\t\treturn readFile(join(this.vibeDir, filename), \"utf-8\");\n\t}\n\n\t/** Checks if a global artifact file exists. */\n\tasync hasGlobalArtifact(filename: string): Promise<boolean> {\n\t\treturn this.fileExists(join(this.vibeDir, filename));\n\t}\n\n\t// ─── Standards ───────────────────────────────────────────────────────────\n\n\t/** Returns a list of .md files in .vibe/standards/ (filenames only). */\n\tasync listStandardFiles(): Promise<string[]> {\n\t\tif (!(await this.fileExists(this.standardsDir))) {\n\t\t\treturn [];\n\t\t}\n\t\tconst entries = await readdir(this.standardsDir);\n\t\treturn entries.filter((e) => e.endsWith(\".md\")).sort();\n\t}\n\n\t/** Resolves a standards source path to an absolute path. */\n\tresolveStandardSource(source: string): string {\n\t\tif (isAbsolute(source)) {\n\t\t\treturn source;\n\t\t}\n\t\treturn resolve(this.projectRoot, source);\n\t}\n\n\t/** Checks if a standard file exists in .vibe/standards/. */\n\tasync hasStandardFile(fileName: string): Promise<boolean> {\n\t\treturn this.fileExists(join(this.standardsDir, fileName));\n\t}\n\n\t/** Reads all standard files and returns them as Map<filename, content>. */\n\tasync readAllStandards(): Promise<Map<string, string>> {\n\t\tconst files = await this.listStandardFiles();\n\t\tconst result = new Map<string, string>();\n\t\tfor (const fileName of files) {\n\t\t\tconst content = await readFile(join(this.standardsDir, fileName), \"utf-8\");\n\t\t\tresult.set(fileName, content);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/** Writes a single standard file. */\n\tasync writeStandard(fileName: string, content: string): Promise<void> {\n\t\tawait writeFile(join(this.standardsDir, fileName), content, \"utf-8\");\n\t}\n\n\t// ─── Requirements ────────────────────────────────────────────────────────\n\n\t/** Returns the path to .vibe/requirements.md. */\n\tgetRequirementsPath(): string {\n\t\treturn join(this.vibeDir, \"requirements.md\");\n\t}\n\n\t/** Checks if requirements.md exists. */\n\tasync hasRequirements(): Promise<boolean> {\n\t\treturn this.fileExists(this.getRequirementsPath());\n\t}\n\n\t/** Reads requirements.md. */\n\tasync readRequirements(): Promise<string> {\n\t\treturn readFile(this.getRequirementsPath(), \"utf-8\");\n\t}\n\n\t/** Writes requirements.md. */\n\tasync writeRequirements(content: string): Promise<void> {\n\t\tawait writeFile(this.getRequirementsPath(), content, \"utf-8\");\n\t}\n\n\t/** Deletes requirements.md. */\n\tasync clearRequirements(): Promise<void> {\n\t\tconst filePath = this.getRequirementsPath();\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t// ─── System Design ───────────────────────────────────────────────────────\n\n\t/** Returns the path to .vibe/system-design.md. */\n\tgetSystemDesignPath(): string {\n\t\treturn join(this.vibeDir, \"system-design.md\");\n\t}\n\n\t/** Checks if system-design.md exists. */\n\tasync hasSystemDesign(): Promise<boolean> {\n\t\treturn this.fileExists(this.getSystemDesignPath());\n\t}\n\n\t/** Reads system-design.md. */\n\tasync readSystemDesign(): Promise<string> {\n\t\treturn readFile(this.getSystemDesignPath(), \"utf-8\");\n\t}\n\n\t/** Writes system-design.md. */\n\tasync writeSystemDesign(content: string): Promise<void> {\n\t\tawait writeFile(this.getSystemDesignPath(), content, \"utf-8\");\n\t}\n\n\t/** Deletes system-design.md. */\n\tasync clearSystemDesign(): Promise<void> {\n\t\tconst filePath = this.getSystemDesignPath();\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t/** Deletes plan.json. */\n\tasync clearPlan(): Promise<void> {\n\t\tconst planPath = join(this.vibeDir, \"plan.json\");\n\t\tif (await this.fileExists(planPath)) {\n\t\t\tawait unlink(planPath);\n\t\t}\n\t}\n\n\t/** Recursively deletes the entire feature directory. */\n\tasync clearFeatureDir(featureId: string): Promise<void> {\n\t\tconst dir = this.getFeatureDir(featureId);\n\t\tif (await this.fileExists(dir)) {\n\t\t\tawait rm(dir, { recursive: true, force: true });\n\t\t}\n\t}\n\n\t/** Deletes all feature directories under features/. */\n\tasync clearAllFeatures(): Promise<void> {\n\t\tconst dir = this.getFeaturesDir();\n\t\tif (!(await this.fileExists(dir))) return;\n\t\tconst entries = await readdir(dir);\n\t\tfor (const entry of entries) {\n\t\t\tawait rm(join(dir, entry), { recursive: true, force: true });\n\t\t}\n\t}\n\n\t/** Deletes global agent history by role name. (e.g., \"discovery\" → discovery-*.json) */\n\tasync clearGlobalAgentHistoryByRole(role: string): Promise<void> {\n\t\tconst dir = this.getGlobalAgentHistoryDir();\n\t\tif (!(await this.fileExists(dir))) return;\n\t\tconst entries = await readdir(dir);\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.startsWith(`${role}-`) && entry.endsWith(\".json\")) {\n\t\t\t\tawait unlink(join(dir, entry));\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Deletes a global artifact. */\n\tasync clearGlobalArtifact(filename: string): Promise<void> {\n\t\tconst filePath = join(this.vibeDir, filename);\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t// ─── Project Context ─────────────────────────────────────────────────────\n\n\t/** Returns the path to .vibe/project-context.md. */\n\tgetProjectContextPath(): string {\n\t\treturn join(this.vibeDir, \"project-context.md\");\n\t}\n\n\t/** Checks if project-context.md exists. */\n\tasync hasProjectContext(): Promise<boolean> {\n\t\treturn this.fileExists(this.getProjectContextPath());\n\t}\n\n\t/** Reads project-context.md. */\n\tasync readProjectContext(): Promise<string> {\n\t\treturn readFile(this.getProjectContextPath(), \"utf-8\");\n\t}\n\n\t/** Writes project-context.md. */\n\tasync writeProjectContext(content: string): Promise<void> {\n\t\tawait writeFile(this.getProjectContextPath(), content, \"utf-8\");\n\t}\n\n\t/** Checks if project-context.md is older than staleThresholdDays. */\n\tasync isProjectContextStale(thresholdDays: number): Promise<boolean> {\n\t\tconst contextPath = this.getProjectContextPath();\n\t\tif (!(await this.fileExists(contextPath))) {\n\t\t\treturn true;\n\t\t}\n\t\tconst fileStat = await stat(contextPath);\n\t\tconst ageMs = Date.now() - fileStat.mtimeMs;\n\t\tconst ageDays = ageMs / (1000 * 60 * 60 * 24);\n\t\treturn ageDays > thresholdDays;\n\t}\n\n\t// ─── Agent History (Feature Level) ───────────────────────────────────────\n\n\t/** Returns the agent history directory path for a feature. */\n\tgetAgentHistoryDir(featureId: string): string {\n\t\treturn join(this.getFeatureDir(featureId), \"agent-history\");\n\t}\n\n\t/** Returns the agent history file path. */\n\tgetAgentHistoryPath(featureId: string, role: string, action: string): string {\n\t\treturn join(this.getAgentHistoryDir(featureId), `${role}-${action}.json`);\n\t}\n\n\t/** Saves agent history. Auto-creates the directory if missing. */\n\tasync saveAgentHistory(featureId: string, checkpoint: AgentCheckpoint): Promise<void> {\n\t\tthis.log.debug(`Saving agent history: ${checkpoint.role}:${checkpoint.action}`, { featureId });\n\t\tconst dir = this.getAgentHistoryDir(featureId);\n\t\tawait mkdir(dir, { recursive: true });\n\t\tconst filePath = this.getAgentHistoryPath(featureId, checkpoint.role, checkpoint.action);\n\t\tawait writeFile(filePath, JSON.stringify(checkpoint, null, \"\\t\"), \"utf-8\");\n\t}\n\n\t/** Loads agent history. Returns null if not found. */\n\tasync loadAgentHistory(featureId: string, role: string, action: string): Promise<AgentCheckpoint | null> {\n\t\tconst filePath = this.getAgentHistoryPath(featureId, role, action);\n\t\tif (!(await this.fileExists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst raw = await readFile(filePath, \"utf-8\");\n\t\treturn JSON.parse(raw) as AgentCheckpoint;\n\t}\n\n\t/** Checks if agent history exists. */\n\tasync hasAgentHistory(featureId: string, role: string, action: string): Promise<boolean> {\n\t\treturn this.fileExists(this.getAgentHistoryPath(featureId, role, action));\n\t}\n\n\t/**\n\t * Loads prior action histories for the same role in chronological order.\n\t * Excludes the currentAction's own history (separated from retry checkpointing).\n\t */\n\tasync loadPriorAgentHistory(featureId: string, role: string, currentAction: string): Promise<AgentCheckpoint[]> {\n\t\tconst dir = this.getAgentHistoryDir(featureId);\n\t\tif (!(await this.fileExists(dir))) return [];\n\n\t\tconst entries = await readdir(dir);\n\t\tconst prefix = `${role}-`;\n\t\tconst checkpoints: AgentCheckpoint[] = [];\n\n\t\tfor (const entry of entries) {\n\t\t\tif (!entry.startsWith(prefix) || !entry.endsWith(\".json\")) continue;\n\t\t\tconst action = entry.slice(prefix.length, -5);\n\t\t\tif (action === currentAction) continue;\n\n\t\t\tconst raw = await readFile(join(dir, entry), \"utf-8\");\n\t\t\tcheckpoints.push(JSON.parse(raw) as AgentCheckpoint);\n\t\t}\n\n\t\treturn checkpoints.sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n\t}\n\n\t/** Returns all agent history filenames for a feature. */\n\tasync listAgentHistory(featureId: string): Promise<string[]> {\n\t\tconst dir = this.getAgentHistoryDir(featureId);\n\t\tif (!(await this.fileExists(dir))) {\n\t\t\treturn [];\n\t\t}\n\t\tconst entries = await readdir(dir);\n\t\treturn entries.filter((e) => e.endsWith(\".json\")).sort();\n\t}\n\n\t// ─── Agent History (Global Level) ────────────────────────────────────────\n\n\t/** Returns the project-level agent history directory path. */\n\tgetGlobalAgentHistoryDir(): string {\n\t\treturn join(this.vibeDir, \"agent-history\");\n\t}\n\n\t/** Returns the project-level agent history file path. */\n\tgetGlobalAgentHistoryPath(role: string, action: string): string {\n\t\treturn join(this.getGlobalAgentHistoryDir(), `${role}-${action}.json`);\n\t}\n\n\t/** Saves project-level agent history. */\n\tasync saveGlobalAgentHistory(checkpoint: AgentCheckpoint): Promise<void> {\n\t\tconst dir = this.getGlobalAgentHistoryDir();\n\t\tawait mkdir(dir, { recursive: true });\n\t\tconst filePath = this.getGlobalAgentHistoryPath(checkpoint.role, checkpoint.action);\n\t\tawait writeFile(filePath, JSON.stringify(checkpoint, null, \"\\t\"), \"utf-8\");\n\t}\n\n\t/** Loads project-level agent history. Returns null if not found. */\n\tasync loadGlobalAgentHistory(role: string, action: string): Promise<AgentCheckpoint | null> {\n\t\tconst filePath = this.getGlobalAgentHistoryPath(role, action);\n\t\tif (!(await this.fileExists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst raw = await readFile(filePath, \"utf-8\");\n\t\treturn JSON.parse(raw) as AgentCheckpoint;\n\t}\n\n\t/** Checks if project-level agent history exists. */\n\tasync hasGlobalAgentHistory(role: string, action: string): Promise<boolean> {\n\t\treturn this.fileExists(this.getGlobalAgentHistoryPath(role, action));\n\t}\n\n\t/** Returns a list of project-level agent history files. */\n\tasync listGlobalAgentHistory(): Promise<string[]> {\n\t\tconst dir = this.getGlobalAgentHistoryDir();\n\t\tif (!(await this.fileExists(dir))) {\n\t\t\treturn [];\n\t\t}\n\t\tconst entries = await readdir(dir);\n\t\treturn entries.filter((e) => e.endsWith(\".json\")).sort();\n\t}\n\n\t// ─── Orchestration State Persistence ─────────────────────────────────────\n\n\t/** Returns the path to orchestration-state.json. */\n\tgetOrchestrationStatePath(): string {\n\t\treturn join(this.vibeDir, \"orchestration-state.json\");\n\t}\n\n\t/** Saves orchestration state. Auto-creates .vibe/ directory if missing. */\n\tasync saveOrchestrationState(state: OrchestrationState): Promise<void> {\n\t\tawait mkdir(this.vibeDir, { recursive: true });\n\t\tawait writeFile(this.getOrchestrationStatePath(), `${JSON.stringify(state, null, \"\\t\")}\\n`, \"utf-8\");\n\t}\n\n\t/** Loads orchestration state. Returns null if not found. */\n\tasync loadOrchestrationState(): Promise<OrchestrationState | null> {\n\t\tconst filePath = this.getOrchestrationStatePath();\n\t\tif (!(await this.fileExists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst raw = await readFile(filePath, \"utf-8\");\n\t\treturn JSON.parse(raw) as OrchestrationState;\n\t}\n\n\t/** Deletes the orchestration state file. */\n\tasync clearOrchestrationState(): Promise<void> {\n\t\tconst filePath = this.getOrchestrationStatePath();\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t/** Checks if orchestration state file exists. */\n\tasync hasOrchestrationState(): Promise<boolean> {\n\t\treturn this.fileExists(this.getOrchestrationStatePath());\n\t}\n\n\t// ─── Pipeline State Persistence ──────────────────────────────────────────\n\n\t/** Returns the path to pipeline.json. */\n\tgetPipelineStatePath(featureId: string): string {\n\t\treturn join(this.getFeatureDir(featureId), \"pipeline.json\");\n\t}\n\n\t/** Saves pipeline state. */\n\tasync savePipelineState(featureId: string, state: PersistedPipeline): Promise<void> {\n\t\tawait this.ensureFeatureDir(featureId);\n\t\tawait writeFile(this.getPipelineStatePath(featureId), `${JSON.stringify(state, null, \"\\t\")}\\n`, \"utf-8\");\n\t}\n\n\t/** Loads pipeline state. Returns null if not found. */\n\tasync loadPipelineState(featureId: string): Promise<PersistedPipeline | null> {\n\t\tconst filePath = this.getPipelineStatePath(featureId);\n\t\tif (!(await this.fileExists(filePath))) {\n\t\t\treturn null;\n\t\t}\n\t\tconst raw = await readFile(filePath, \"utf-8\");\n\t\treturn JSON.parse(raw) as PersistedPipeline;\n\t}\n\n\t/** Deletes the pipeline state file. */\n\tasync clearPipelineState(featureId: string): Promise<void> {\n\t\tconst filePath = this.getPipelineStatePath(featureId);\n\t\tif (await this.fileExists(filePath)) {\n\t\t\tawait unlink(filePath);\n\t\t}\n\t}\n\n\t// ─── Reset ───────────────────────────────────────────────────────────────\n\n\t/** Deletes the entire .vibe/ directory and re-initializes from scratch. */\n\tasync reset(): Promise<void> {\n\t\tif (await this.fileExists(this.vibeDir)) {\n\t\t\tawait rm(this.vibeDir, { recursive: true, force: true });\n\t\t}\n\t\tawait this.init();\n\t}\n\n\t// ─── Helpers ─────────────────────────────────────────────────────────────\n\n\t/**\n\t * Ensures the project root .gitignore contains vibe-managed rules.\n\t * Appends a managed block if missing, or replaces it if already present.\n\t */\n\tprivate async ensureRootGitignore(): Promise<void> {\n\t\tconst gitignorePath = join(this.projectRoot, \".gitignore\");\n\t\tlet content = \"\";\n\t\tif (await this.fileExists(gitignorePath)) {\n\t\t\tcontent = await readFile(gitignorePath, \"utf-8\");\n\t\t}\n\n\t\tif (content.includes(VIBE_GITIGNORE_MARKER)) {\n\t\t\t// Replace existing managed block\n\t\t\tconst startIdx = content.indexOf(VIBE_GITIGNORE_MARKER);\n\t\t\tconst endIdx = content.indexOf(VIBE_GITIGNORE_MARKER_END);\n\t\t\tif (endIdx !== -1) {\n\t\t\t\tconst before = content.slice(0, startIdx);\n\t\t\t\tconst after = content.slice(endIdx + VIBE_GITIGNORE_MARKER_END.length);\n\t\t\t\tcontent = before + VIBE_GITIGNORE_BLOCK + after;\n\t\t\t}\n\t\t} else {\n\t\t\t// Append managed block\n\t\t\tconst separator = content.length > 0 && !content.endsWith(\"\\n\") ? \"\\n\\n\" : content.length > 0 ? \"\\n\" : \"\";\n\t\t\tcontent = `${content}${separator}${VIBE_GITIGNORE_BLOCK}\\n`;\n\t\t}\n\n\t\tawait writeFile(gitignorePath, content, \"utf-8\");\n\t}\n\n\tprivate async fileExists(path: string): Promise<boolean> {\n\t\ttry {\n\t\t\tawait access(path);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n}\n"]}
|
|
@@ -17,8 +17,6 @@ export interface SystemArchitectOptions {
|
|
|
17
17
|
onMessage?: (message: string) => void;
|
|
18
18
|
/** User feedback on rejection. Re-generates with feedback applied. */
|
|
19
19
|
feedback?: string;
|
|
20
|
-
/** Lightweight skill index. Included in the agent system prompt. */
|
|
21
|
-
availableSkills?: string;
|
|
22
20
|
/** Callback invoked when the agent is created (for abort wiring). */
|
|
23
21
|
onAgentCreated?: (agent: Agent) => void;
|
|
24
22
|
/** Callback invoked when the agent finishes execution. */
|
|
@@ -28,6 +26,15 @@ export interface SystemArchitectOptions {
|
|
|
28
26
|
export interface SystemArchitectResult {
|
|
29
27
|
/** Whether system-design.md was generated. */
|
|
30
28
|
completed: boolean;
|
|
29
|
+
/** Aggregated token usage. */
|
|
30
|
+
usage?: {
|
|
31
|
+
input: number;
|
|
32
|
+
output: number;
|
|
33
|
+
cacheRead: number;
|
|
34
|
+
cacheWrite: number;
|
|
35
|
+
totalTokens: number;
|
|
36
|
+
cost: number;
|
|
37
|
+
};
|
|
31
38
|
}
|
|
32
39
|
/**
|
|
33
40
|
* Runs the System Architect agent to generate system-design.md
|