cognitive-core 0.2.1 → 0.2.2
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/dist/atlas.d.ts +10 -0
- package/dist/atlas.d.ts.map +1 -1
- package/dist/atlas.js +65 -0
- package/dist/atlas.js.map +1 -1
- package/dist/learning/pipeline.d.ts +4 -31
- package/dist/learning/pipeline.d.ts.map +1 -1
- package/dist/learning/pipeline.js +12 -64
- package/dist/learning/pipeline.js.map +1 -1
- package/dist/memory/curated-loader.d.ts +21 -4
- package/dist/memory/curated-loader.d.ts.map +1 -1
- package/dist/memory/curated-loader.js +53 -16
- package/dist/memory/curated-loader.js.map +1 -1
- package/dist/memory/index.d.ts +2 -1
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +3 -1
- package/dist/memory/index.js.map +1 -1
- package/dist/memory/playbook.d.ts +6 -0
- package/dist/memory/playbook.d.ts.map +1 -1
- package/dist/memory/playbook.js +15 -0
- package/dist/memory/playbook.js.map +1 -1
- package/dist/memory/source-resolver.d.ts +120 -0
- package/dist/memory/source-resolver.d.ts.map +1 -0
- package/dist/memory/source-resolver.js +300 -0
- package/dist/memory/source-resolver.js.map +1 -0
- package/dist/types/config.d.ts +141 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +40 -0
- package/dist/types/config.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/workspace/types.d.ts +12 -54
- package/dist/workspace/types.d.ts.map +1 -1
- package/dist/workspace/types.js.map +1 -1
- package/package.json +2 -2
- package/playbooks/compound-engineering/adversarial-review.json +51 -0
- package/playbooks/compound-engineering/agent-native-architecture.json +59 -0
- package/playbooks/compound-engineering/agent-native-review.json +54 -0
- package/playbooks/compound-engineering/api-contract-review.json +52 -0
- package/playbooks/compound-engineering/brainstorm-requirements.json +55 -0
- package/playbooks/compound-engineering/bug-reproduction.json +62 -0
- package/playbooks/compound-engineering/confidence-calibration.json +49 -0
- package/playbooks/compound-engineering/correctness-review.json +49 -0
- package/playbooks/compound-engineering/data-migration-safety.json +59 -0
- package/playbooks/compound-engineering/deployment-verification.json +63 -0
- package/playbooks/compound-engineering/error-recovery-patterns.json +53 -0
- package/playbooks/compound-engineering/implementation-planning.json +64 -0
- package/playbooks/compound-engineering/issue-pattern-analysis.json +53 -0
- package/playbooks/compound-engineering/knowledge-compounding.json +63 -0
- package/playbooks/compound-engineering/learnings-research.json +54 -0
- package/playbooks/compound-engineering/maintainability-review.json +49 -0
- package/playbooks/compound-engineering/performance-review.json +54 -0
- package/playbooks/compound-engineering/plan-adversarial-review.json +56 -0
- package/playbooks/compound-engineering/plan-feasibility-review.json +56 -0
- package/playbooks/compound-engineering/project-standards-review.json +52 -0
- package/playbooks/compound-engineering/reliability-review.json +53 -0
- package/playbooks/compound-engineering/review-orchestration.json +64 -0
- package/playbooks/compound-engineering/security-review.json +54 -0
- package/playbooks/compound-engineering/systematic-execution.json +64 -0
- package/playbooks/compound-engineering/testing-review.json +50 -0
- package/src/atlas.ts +96 -0
- package/src/memory/curated-loader.ts +69 -16
- package/src/memory/index.ts +16 -0
- package/src/memory/playbook.ts +19 -0
- package/src/memory/source-resolver.ts +422 -0
- package/src/types/config.ts +46 -0
- package/src/types/index.ts +4 -0
- package/src/workspace/types.ts +22 -78
- package/tests/integration/curated-sources-e2e.test.ts +502 -0
- package/tests/memory/compound-engineering-seed.test.ts +338 -0
- package/tests/memory/curated-loader-extended.test.ts +225 -0
- package/tests/memory/playbook-quality-validation.test.ts +430 -0
- package/tests/memory/source-resolver.test.ts +700 -0
- package/.claude/settings.local.json +0 -11
- package/dist/learning/llm-extractor.d.ts +0 -88
- package/dist/learning/llm-extractor.d.ts.map +0 -1
- package/dist/learning/llm-extractor.js +0 -372
- package/dist/learning/llm-extractor.js.map +0 -1
- package/dist/learning/loop-coordinator.d.ts +0 -61
- package/dist/learning/loop-coordinator.d.ts.map +0 -1
- package/dist/learning/loop-coordinator.js +0 -96
- package/dist/learning/loop-coordinator.js.map +0 -1
- package/references/agent-workspace/CLAUDE.md +0 -74
- package/references/agent-workspace/README.md +0 -587
- package/references/agent-workspace/media/banner.png +0 -0
- package/references/agent-workspace/package-lock.json +0 -2061
- package/references/agent-workspace/package.json +0 -54
- package/references/agent-workspace/src/handle.ts +0 -122
- package/references/agent-workspace/src/index.ts +0 -32
- package/references/agent-workspace/src/manager.ts +0 -102
- package/references/agent-workspace/src/readers/json.ts +0 -71
- package/references/agent-workspace/src/readers/markdown.ts +0 -37
- package/references/agent-workspace/src/readers/raw.ts +0 -27
- package/references/agent-workspace/src/types.ts +0 -68
- package/references/agent-workspace/src/validation.ts +0 -93
- package/references/agent-workspace/src/writers/json.ts +0 -17
- package/references/agent-workspace/src/writers/markdown.ts +0 -27
- package/references/agent-workspace/src/writers/raw.ts +0 -22
- package/references/agent-workspace/tests/errors.test.ts +0 -652
- package/references/agent-workspace/tests/handle.test.ts +0 -144
- package/references/agent-workspace/tests/manager.test.ts +0 -124
- package/references/agent-workspace/tests/readers.test.ts +0 -205
- package/references/agent-workspace/tests/validation.test.ts +0 -196
- package/references/agent-workspace/tests/writers.test.ts +0 -108
- package/references/agent-workspace/tsconfig.json +0 -20
- package/references/agent-workspace/tsup.config.ts +0 -9
- package/references/minimem/.claude/settings.json +0 -7
- package/references/minimem/.sudocode/issues.jsonl +0 -18
- package/references/minimem/.sudocode/specs.jsonl +0 -1
- package/references/minimem/CLAUDE.md +0 -310
- package/references/minimem/README.md +0 -556
- package/references/minimem/claude-plugin/.claude-plugin/plugin.json +0 -10
- package/references/minimem/claude-plugin/.mcp.json +0 -7
- package/references/minimem/claude-plugin/README.md +0 -158
- package/references/minimem/claude-plugin/commands/recall.md +0 -47
- package/references/minimem/claude-plugin/commands/remember.md +0 -41
- package/references/minimem/claude-plugin/hooks/__tests__/hooks.test.ts +0 -272
- package/references/minimem/claude-plugin/hooks/hooks.json +0 -27
- package/references/minimem/claude-plugin/hooks/session-end.sh +0 -86
- package/references/minimem/claude-plugin/hooks/session-start.sh +0 -85
- package/references/minimem/claude-plugin/skills/memory/SKILL.md +0 -108
- package/references/minimem/package-lock.json +0 -5373
- package/references/minimem/package.json +0 -60
- package/references/minimem/scripts/postbuild.js +0 -35
- package/references/minimem/src/__tests__/edge-cases.test.ts +0 -371
- package/references/minimem/src/__tests__/errors.test.ts +0 -265
- package/references/minimem/src/__tests__/helpers.ts +0 -199
- package/references/minimem/src/__tests__/internal.test.ts +0 -407
- package/references/minimem/src/__tests__/knowledge.test.ts +0 -287
- package/references/minimem/src/__tests__/minimem.integration.test.ts +0 -1127
- package/references/minimem/src/__tests__/session.test.ts +0 -190
- package/references/minimem/src/cli/__tests__/commands.test.ts +0 -759
- package/references/minimem/src/cli/commands/__tests__/conflicts.test.ts +0 -141
- package/references/minimem/src/cli/commands/append.ts +0 -76
- package/references/minimem/src/cli/commands/config.ts +0 -262
- package/references/minimem/src/cli/commands/conflicts.ts +0 -413
- package/references/minimem/src/cli/commands/daemon.ts +0 -169
- package/references/minimem/src/cli/commands/index.ts +0 -12
- package/references/minimem/src/cli/commands/init.ts +0 -88
- package/references/minimem/src/cli/commands/mcp.ts +0 -177
- package/references/minimem/src/cli/commands/push-pull.ts +0 -213
- package/references/minimem/src/cli/commands/search.ts +0 -158
- package/references/minimem/src/cli/commands/status.ts +0 -84
- package/references/minimem/src/cli/commands/sync-init.ts +0 -290
- package/references/minimem/src/cli/commands/sync.ts +0 -70
- package/references/minimem/src/cli/commands/upsert.ts +0 -197
- package/references/minimem/src/cli/config.ts +0 -584
- package/references/minimem/src/cli/index.ts +0 -264
- package/references/minimem/src/cli/shared.ts +0 -161
- package/references/minimem/src/cli/sync/__tests__/central.test.ts +0 -152
- package/references/minimem/src/cli/sync/__tests__/conflicts.test.ts +0 -209
- package/references/minimem/src/cli/sync/__tests__/daemon.test.ts +0 -118
- package/references/minimem/src/cli/sync/__tests__/detection.test.ts +0 -207
- package/references/minimem/src/cli/sync/__tests__/integration.test.ts +0 -476
- package/references/minimem/src/cli/sync/__tests__/registry.test.ts +0 -363
- package/references/minimem/src/cli/sync/__tests__/state.test.ts +0 -255
- package/references/minimem/src/cli/sync/__tests__/validation.test.ts +0 -193
- package/references/minimem/src/cli/sync/__tests__/watcher.test.ts +0 -178
- package/references/minimem/src/cli/sync/central.ts +0 -292
- package/references/minimem/src/cli/sync/conflicts.ts +0 -204
- package/references/minimem/src/cli/sync/daemon.ts +0 -407
- package/references/minimem/src/cli/sync/detection.ts +0 -138
- package/references/minimem/src/cli/sync/index.ts +0 -107
- package/references/minimem/src/cli/sync/operations.ts +0 -373
- package/references/minimem/src/cli/sync/registry.ts +0 -279
- package/references/minimem/src/cli/sync/state.ts +0 -355
- package/references/minimem/src/cli/sync/validation.ts +0 -206
- package/references/minimem/src/cli/sync/watcher.ts +0 -234
- package/references/minimem/src/cli/version.ts +0 -34
- package/references/minimem/src/core/index.ts +0 -9
- package/references/minimem/src/core/indexer.ts +0 -628
- package/references/minimem/src/core/searcher.ts +0 -221
- package/references/minimem/src/db/schema.ts +0 -183
- package/references/minimem/src/db/sqlite-vec.ts +0 -24
- package/references/minimem/src/embeddings/__tests__/embeddings.test.ts +0 -431
- package/references/minimem/src/embeddings/batch-gemini.ts +0 -392
- package/references/minimem/src/embeddings/batch-openai.ts +0 -409
- package/references/minimem/src/embeddings/embeddings.ts +0 -434
- package/references/minimem/src/index.ts +0 -109
- package/references/minimem/src/internal.ts +0 -299
- package/references/minimem/src/minimem.ts +0 -1276
- package/references/minimem/src/search/__tests__/hybrid.test.ts +0 -247
- package/references/minimem/src/search/graph.ts +0 -234
- package/references/minimem/src/search/hybrid.ts +0 -151
- package/references/minimem/src/search/search.ts +0 -256
- package/references/minimem/src/server/__tests__/mcp.test.ts +0 -341
- package/references/minimem/src/server/__tests__/tools.test.ts +0 -364
- package/references/minimem/src/server/mcp.ts +0 -326
- package/references/minimem/src/server/tools.ts +0 -720
- package/references/minimem/src/session.ts +0 -460
- package/references/minimem/tsconfig.json +0 -19
- package/references/minimem/tsup.config.ts +0 -26
- package/references/minimem/vitest.config.ts +0 -24
- package/references/sessionlog/.husky/pre-commit +0 -1
- package/references/sessionlog/.lintstagedrc.json +0 -4
- package/references/sessionlog/.prettierignore +0 -4
- package/references/sessionlog/.prettierrc.json +0 -11
- package/references/sessionlog/LICENSE +0 -21
- package/references/sessionlog/README.md +0 -453
- package/references/sessionlog/eslint.config.js +0 -58
- package/references/sessionlog/package-lock.json +0 -3672
- package/references/sessionlog/package.json +0 -65
- package/references/sessionlog/src/__tests__/agent-hooks.test.ts +0 -570
- package/references/sessionlog/src/__tests__/agent-registry.test.ts +0 -127
- package/references/sessionlog/src/__tests__/claude-code-hooks.test.ts +0 -225
- package/references/sessionlog/src/__tests__/claude-generator.test.ts +0 -46
- package/references/sessionlog/src/__tests__/commit-msg.test.ts +0 -86
- package/references/sessionlog/src/__tests__/cursor-agent.test.ts +0 -224
- package/references/sessionlog/src/__tests__/e2e-live.test.ts +0 -890
- package/references/sessionlog/src/__tests__/event-log.test.ts +0 -183
- package/references/sessionlog/src/__tests__/flush-sentinel.test.ts +0 -105
- package/references/sessionlog/src/__tests__/gemini-agent.test.ts +0 -375
- package/references/sessionlog/src/__tests__/git-hooks.test.ts +0 -78
- package/references/sessionlog/src/__tests__/hook-managers.test.ts +0 -121
- package/references/sessionlog/src/__tests__/lifecycle-tasks.test.ts +0 -759
- package/references/sessionlog/src/__tests__/opencode-agent.test.ts +0 -338
- package/references/sessionlog/src/__tests__/redaction.test.ts +0 -136
- package/references/sessionlog/src/__tests__/session-repo.test.ts +0 -353
- package/references/sessionlog/src/__tests__/session-store.test.ts +0 -166
- package/references/sessionlog/src/__tests__/setup-ccweb.test.ts +0 -466
- package/references/sessionlog/src/__tests__/skill-live.test.ts +0 -461
- package/references/sessionlog/src/__tests__/summarize.test.ts +0 -348
- package/references/sessionlog/src/__tests__/task-plan-e2e.test.ts +0 -610
- package/references/sessionlog/src/__tests__/task-plan-live.test.ts +0 -632
- package/references/sessionlog/src/__tests__/transcript-timestamp.test.ts +0 -121
- package/references/sessionlog/src/__tests__/types.test.ts +0 -166
- package/references/sessionlog/src/__tests__/utils.test.ts +0 -333
- package/references/sessionlog/src/__tests__/validation.test.ts +0 -103
- package/references/sessionlog/src/__tests__/worktree.test.ts +0 -57
- package/references/sessionlog/src/agent/agents/claude-code.ts +0 -1089
- package/references/sessionlog/src/agent/agents/cursor.ts +0 -361
- package/references/sessionlog/src/agent/agents/gemini-cli.ts +0 -632
- package/references/sessionlog/src/agent/agents/opencode.ts +0 -540
- package/references/sessionlog/src/agent/registry.ts +0 -143
- package/references/sessionlog/src/agent/session-types.ts +0 -113
- package/references/sessionlog/src/agent/types.ts +0 -220
- package/references/sessionlog/src/cli.ts +0 -597
- package/references/sessionlog/src/commands/clean.ts +0 -133
- package/references/sessionlog/src/commands/disable.ts +0 -84
- package/references/sessionlog/src/commands/doctor.ts +0 -145
- package/references/sessionlog/src/commands/enable.ts +0 -202
- package/references/sessionlog/src/commands/explain.ts +0 -261
- package/references/sessionlog/src/commands/reset.ts +0 -105
- package/references/sessionlog/src/commands/resume.ts +0 -180
- package/references/sessionlog/src/commands/rewind.ts +0 -195
- package/references/sessionlog/src/commands/setup-ccweb.ts +0 -275
- package/references/sessionlog/src/commands/status.ts +0 -172
- package/references/sessionlog/src/config.ts +0 -165
- package/references/sessionlog/src/events/event-log.ts +0 -126
- package/references/sessionlog/src/git-operations.ts +0 -558
- package/references/sessionlog/src/hooks/git-hooks.ts +0 -165
- package/references/sessionlog/src/hooks/lifecycle.ts +0 -391
- package/references/sessionlog/src/index.ts +0 -650
- package/references/sessionlog/src/security/redaction.ts +0 -283
- package/references/sessionlog/src/session/state-machine.ts +0 -452
- package/references/sessionlog/src/store/checkpoint-store.ts +0 -509
- package/references/sessionlog/src/store/native-store.ts +0 -173
- package/references/sessionlog/src/store/provider-types.ts +0 -99
- package/references/sessionlog/src/store/session-store.ts +0 -266
- package/references/sessionlog/src/strategy/attribution.ts +0 -296
- package/references/sessionlog/src/strategy/common.ts +0 -207
- package/references/sessionlog/src/strategy/content-overlap.ts +0 -228
- package/references/sessionlog/src/strategy/manual-commit.ts +0 -988
- package/references/sessionlog/src/strategy/types.ts +0 -279
- package/references/sessionlog/src/summarize/claude-generator.ts +0 -115
- package/references/sessionlog/src/summarize/summarize.ts +0 -432
- package/references/sessionlog/src/types.ts +0 -508
- package/references/sessionlog/src/utils/chunk-files.ts +0 -49
- package/references/sessionlog/src/utils/commit-message.ts +0 -65
- package/references/sessionlog/src/utils/detect-agent.ts +0 -36
- package/references/sessionlog/src/utils/hook-managers.ts +0 -125
- package/references/sessionlog/src/utils/ide-tags.ts +0 -32
- package/references/sessionlog/src/utils/paths.ts +0 -79
- package/references/sessionlog/src/utils/preview-rewind.ts +0 -80
- package/references/sessionlog/src/utils/rewind-conflict.ts +0 -121
- package/references/sessionlog/src/utils/shadow-branch.ts +0 -109
- package/references/sessionlog/src/utils/string-utils.ts +0 -46
- package/references/sessionlog/src/utils/todo-extract.ts +0 -188
- package/references/sessionlog/src/utils/trailers.ts +0 -187
- package/references/sessionlog/src/utils/transcript-parse.ts +0 -177
- package/references/sessionlog/src/utils/transcript-timestamp.ts +0 -59
- package/references/sessionlog/src/utils/tree-ops.ts +0 -219
- package/references/sessionlog/src/utils/tty.ts +0 -72
- package/references/sessionlog/src/utils/validation.ts +0 -65
- package/references/sessionlog/src/utils/worktree.ts +0 -58
- package/references/sessionlog/src/wire-types.ts +0 -59
- package/references/sessionlog/templates/setup-env.sh +0 -153
- package/references/sessionlog/tsconfig.json +0 -18
- package/references/sessionlog/vitest.config.ts +0 -12
- package/references/skill-tree/.claude/settings.json +0 -6
- package/references/skill-tree/.sudocode/issues.jsonl +0 -19
- package/references/skill-tree/.sudocode/specs.jsonl +0 -3
- package/references/skill-tree/CLAUDE.md +0 -126
- package/references/skill-tree/README.md +0 -372
- package/references/skill-tree/docs/GAPS_v1.md +0 -221
- package/references/skill-tree/docs/INTEGRATION_PLAN.md +0 -467
- package/references/skill-tree/docs/TODOS.md +0 -91
- package/references/skill-tree/docs/anthropic_skill_guide.md +0 -1364
- package/references/skill-tree/docs/design/federated-skill-trees.md +0 -524
- package/references/skill-tree/docs/design/multi-agent-sync.md +0 -759
- package/references/skill-tree/docs/scraper/BRAINSTORM.md +0 -583
- package/references/skill-tree/docs/scraper/POC_PLAN.md +0 -420
- package/references/skill-tree/docs/scraper/README.md +0 -170
- package/references/skill-tree/examples/basic-usage.ts +0 -164
- package/references/skill-tree/package-lock.json +0 -1852
- package/references/skill-tree/package.json +0 -66
- package/references/skill-tree/scraper/README.md +0 -123
- package/references/skill-tree/scraper/docs/DESIGN.md +0 -683
- package/references/skill-tree/scraper/docs/PLAN.md +0 -336
- package/references/skill-tree/scraper/drizzle.config.ts +0 -10
- package/references/skill-tree/scraper/package-lock.json +0 -6329
- package/references/skill-tree/scraper/package.json +0 -68
- package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-description.md +0 -7
- package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-name.md +0 -7
- package/references/skill-tree/scraper/test/fixtures/minimal-skill/SKILL.md +0 -27
- package/references/skill-tree/scraper/test/fixtures/skill-json/SKILL.json +0 -21
- package/references/skill-tree/scraper/test/fixtures/skill-with-meta/SKILL.md +0 -54
- package/references/skill-tree/scraper/test/fixtures/skill-with-meta/_meta.json +0 -24
- package/references/skill-tree/scraper/test/fixtures/valid-skill/SKILL.md +0 -93
- package/references/skill-tree/scraper/test/fixtures/valid-skill/_meta.json +0 -22
- package/references/skill-tree/scraper/tsup.config.ts +0 -14
- package/references/skill-tree/scraper/vitest.config.ts +0 -17
- package/references/skill-tree/scripts/convert-to-vitest.ts +0 -166
- package/references/skill-tree/skills/skill-writer/SKILL.md +0 -339
- package/references/skill-tree/skills/skill-writer/references/examples.md +0 -326
- package/references/skill-tree/skills/skill-writer/references/patterns.md +0 -210
- package/references/skill-tree/skills/skill-writer/references/quality-checklist.md +0 -123
- package/references/skill-tree/test/run-all.ts +0 -106
- package/references/skill-tree/test/utils.ts +0 -128
- package/references/skill-tree/vitest.config.ts +0 -16
|
@@ -6,17 +6,30 @@
|
|
|
6
6
|
* drop all curated playbooks and reload from source files without
|
|
7
7
|
* losing extracted or imported playbooks.
|
|
8
8
|
*
|
|
9
|
+
* Supports recursive directory scanning and source-prefix-based
|
|
10
|
+
* deletion for per-source recreate (multiple sources don't clobber
|
|
11
|
+
* each other).
|
|
12
|
+
*
|
|
9
13
|
* Inspired by Dash's separation of curated knowledge (file-loaded)
|
|
10
14
|
* vs learnings (runtime-discovered).
|
|
11
15
|
*/
|
|
12
16
|
|
|
13
|
-
import { readFile, readdir
|
|
14
|
-
import { join, relative } from 'node:path';
|
|
17
|
+
import { readFile, readdir } from 'node:fs/promises';
|
|
18
|
+
import { join, relative, dirname } from 'node:path';
|
|
15
19
|
import { existsSync } from 'node:fs';
|
|
20
|
+
import { fileURLToPath } from 'node:url';
|
|
16
21
|
import type { PlaybookProvenance } from '../types/index.js';
|
|
17
22
|
import { createPlaybook } from '../types/index.js';
|
|
18
23
|
import type { PlaybookLibrary } from './playbook.js';
|
|
19
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Path to the bundled compound-engineering seed pack shipped with cognitive-core.
|
|
27
|
+
* Resolves relative to this file's location in the package.
|
|
28
|
+
*/
|
|
29
|
+
const __filename_curated = fileURLToPath(import.meta.url);
|
|
30
|
+
const __dirname_curated = dirname(__filename_curated);
|
|
31
|
+
export const BUNDLED_SEED_PACK_DIR = join(__dirname_curated, '../../playbooks/compound-engineering');
|
|
32
|
+
|
|
20
33
|
/**
|
|
21
34
|
* Schema for a curated playbook JSON file
|
|
22
35
|
*/
|
|
@@ -55,17 +68,49 @@ export interface CuratedLoadResult {
|
|
|
55
68
|
recreated: boolean;
|
|
56
69
|
}
|
|
57
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Options for loadCuratedPlaybooks
|
|
73
|
+
*/
|
|
74
|
+
export interface CuratedLoadOptions {
|
|
75
|
+
/** If true, delete existing curated playbooks before loading */
|
|
76
|
+
recreate?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Source identifier for provenance tracking.
|
|
79
|
+
* Used as prefix in provenance.sourceFile for per-source recreate.
|
|
80
|
+
* If provided and recreate is true, only playbooks from this source are deleted.
|
|
81
|
+
*/
|
|
82
|
+
sourceId?: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Recursively find all JSON files in a directory tree.
|
|
87
|
+
*/
|
|
88
|
+
async function findJsonFiles(dir: string): Promise<string[]> {
|
|
89
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
90
|
+
const files: string[] = [];
|
|
91
|
+
for (const entry of entries) {
|
|
92
|
+
const fullPath = join(dir, entry.name);
|
|
93
|
+
if (entry.isDirectory()) {
|
|
94
|
+
files.push(...await findJsonFiles(fullPath));
|
|
95
|
+
} else if (entry.name.endsWith('.json')) {
|
|
96
|
+
files.push(fullPath);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return files;
|
|
100
|
+
}
|
|
101
|
+
|
|
58
102
|
/**
|
|
59
103
|
* Load curated playbooks from a directory of JSON files into the library.
|
|
104
|
+
* Supports recursive directory scanning.
|
|
60
105
|
*
|
|
61
106
|
* @param curatedDir - Directory containing curated playbook JSON files
|
|
62
107
|
* @param library - PlaybookLibrary to load into
|
|
63
|
-
* @param options
|
|
108
|
+
* @param options - Load options (recreate, sourceId)
|
|
64
109
|
*/
|
|
65
110
|
export async function loadCuratedPlaybooks(
|
|
66
111
|
curatedDir: string,
|
|
67
112
|
library: PlaybookLibrary,
|
|
68
|
-
options?:
|
|
113
|
+
options?: CuratedLoadOptions
|
|
69
114
|
): Promise<CuratedLoadResult> {
|
|
70
115
|
const result: CuratedLoadResult = {
|
|
71
116
|
loaded: 0,
|
|
@@ -78,20 +123,23 @@ export async function loadCuratedPlaybooks(
|
|
|
78
123
|
return result;
|
|
79
124
|
}
|
|
80
125
|
|
|
81
|
-
// Recreate: drop
|
|
126
|
+
// Recreate: drop curated playbooks before loading
|
|
82
127
|
if (options?.recreate) {
|
|
83
|
-
|
|
128
|
+
if (options.sourceId) {
|
|
129
|
+
// Per-source recreate: only delete playbooks from this source
|
|
130
|
+
await library.deleteByCuratedSource(options.sourceId);
|
|
131
|
+
} else {
|
|
132
|
+
// Global recreate: delete all curated playbooks
|
|
133
|
+
await library.deleteByOrigin('curated');
|
|
134
|
+
}
|
|
84
135
|
result.recreated = true;
|
|
85
136
|
}
|
|
86
137
|
|
|
87
|
-
// Find all JSON files
|
|
88
|
-
const
|
|
89
|
-
const jsonFiles = files.filter((f) => f.endsWith('.json'));
|
|
138
|
+
// Find all JSON files recursively
|
|
139
|
+
const jsonFiles = await findJsonFiles(curatedDir);
|
|
90
140
|
|
|
91
|
-
for (const
|
|
92
|
-
const
|
|
93
|
-
const fileStat = await stat(filePath);
|
|
94
|
-
if (!fileStat.isFile()) continue;
|
|
141
|
+
for (const filePath of jsonFiles) {
|
|
142
|
+
const relativeToDir = relative(curatedDir, filePath);
|
|
95
143
|
|
|
96
144
|
try {
|
|
97
145
|
const content = await readFile(filePath, 'utf-8');
|
|
@@ -100,7 +148,7 @@ export async function loadCuratedPlaybooks(
|
|
|
100
148
|
// Validate required fields
|
|
101
149
|
if (!parsed.name || !parsed.applicability || !parsed.guidance) {
|
|
102
150
|
result.errors.push({
|
|
103
|
-
file,
|
|
151
|
+
file: relativeToDir,
|
|
104
152
|
error: 'Missing required fields: name, applicability, guidance',
|
|
105
153
|
});
|
|
106
154
|
continue;
|
|
@@ -113,10 +161,15 @@ export async function loadCuratedPlaybooks(
|
|
|
113
161
|
continue;
|
|
114
162
|
}
|
|
115
163
|
|
|
164
|
+
// Build sourceFile with optional source prefix
|
|
116
165
|
const relativePath = relative(process.cwd(), filePath);
|
|
166
|
+
const sourceFile = options?.sourceId
|
|
167
|
+
? `${options.sourceId}:${relativeToDir}`
|
|
168
|
+
: relativePath;
|
|
169
|
+
|
|
117
170
|
const provenance: PlaybookProvenance = {
|
|
118
171
|
origin: 'curated',
|
|
119
|
-
sourceFile
|
|
172
|
+
sourceFile,
|
|
120
173
|
curatedBy: parsed.curatedBy,
|
|
121
174
|
recordedAt: new Date(),
|
|
122
175
|
};
|
|
@@ -150,7 +203,7 @@ export async function loadCuratedPlaybooks(
|
|
|
150
203
|
result.loaded++;
|
|
151
204
|
} catch (error) {
|
|
152
205
|
result.errors.push({
|
|
153
|
-
file,
|
|
206
|
+
file: relativeToDir,
|
|
154
207
|
error: error instanceof Error ? error.message : String(error),
|
|
155
208
|
});
|
|
156
209
|
}
|
package/src/memory/index.ts
CHANGED
|
@@ -99,10 +99,26 @@ export type { SqlitePersistenceConfig } from '../persistence/index.js';
|
|
|
99
99
|
// Curated playbook loading
|
|
100
100
|
export {
|
|
101
101
|
loadCuratedPlaybooks,
|
|
102
|
+
BUNDLED_SEED_PACK_DIR,
|
|
102
103
|
type CuratedPlaybookFile,
|
|
103
104
|
type CuratedLoadResult,
|
|
105
|
+
type CuratedLoadOptions,
|
|
104
106
|
} from './curated-loader.js';
|
|
105
107
|
|
|
108
|
+
// Source resolver (git + local path resolution for curated sources)
|
|
109
|
+
export {
|
|
110
|
+
resolvePlaybookSource,
|
|
111
|
+
isGitSource,
|
|
112
|
+
parseGitSource,
|
|
113
|
+
discoverPlaybookDir,
|
|
114
|
+
sourceStateKey,
|
|
115
|
+
type ParsedGitSource,
|
|
116
|
+
type PlaybookManifest,
|
|
117
|
+
type SourceState,
|
|
118
|
+
type ResolveResult,
|
|
119
|
+
type ResolveOptions,
|
|
120
|
+
} from './source-resolver.js';
|
|
121
|
+
|
|
106
122
|
// Skill export (compile playbooks → Open Agent Skills format)
|
|
107
123
|
export {
|
|
108
124
|
compilePlaybookToSkill,
|
package/src/memory/playbook.ts
CHANGED
|
@@ -616,6 +616,25 @@ export class PlaybookLibrary {
|
|
|
616
616
|
return toDelete.length;
|
|
617
617
|
}
|
|
618
618
|
|
|
619
|
+
/**
|
|
620
|
+
* Delete curated playbooks whose provenance.sourceFile starts with the given prefix.
|
|
621
|
+
* Used by the source resolver to recreate playbooks from a specific source
|
|
622
|
+
* without affecting other curated sources.
|
|
623
|
+
*/
|
|
624
|
+
async deleteByCuratedSource(sourcePrefix: string): Promise<number> {
|
|
625
|
+
await this.init();
|
|
626
|
+
const toDelete = this.getAllSync().filter(
|
|
627
|
+
(p) =>
|
|
628
|
+
p.provenance?.origin === 'curated' &&
|
|
629
|
+
p.provenance.sourceFile?.startsWith(sourcePrefix),
|
|
630
|
+
);
|
|
631
|
+
for (const playbook of toDelete) {
|
|
632
|
+
this.persistence.deletePlaybook(playbook.id);
|
|
633
|
+
this._index.remove(playbook.id);
|
|
634
|
+
}
|
|
635
|
+
return toDelete.length;
|
|
636
|
+
}
|
|
637
|
+
|
|
619
638
|
/**
|
|
620
639
|
* Get provenance summary across all playbooks
|
|
621
640
|
*/
|
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source Resolver — Normalizes playbook sources (local paths, git URLs, shorthands)
|
|
3
|
+
* into local directory paths for the curated loader.
|
|
4
|
+
*
|
|
5
|
+
* Supports:
|
|
6
|
+
* - Local filesystem paths (pass-through)
|
|
7
|
+
* - Git URLs: "git:https://github.com/org/repo" or "git:https://github.com/org/repo#ref"
|
|
8
|
+
* - GitHub shorthand: "github:org/repo" or "github:org/repo#ref"
|
|
9
|
+
*
|
|
10
|
+
* Cloned repos are cached in a configurable directory (default: .atlas/curated-cache/).
|
|
11
|
+
* Cache freshness is controlled by maxAgeMs. Stale caches are refreshed on next resolve.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { execFile as execFileCb } from 'node:child_process';
|
|
15
|
+
import { existsSync, statSync, rmSync } from 'node:fs';
|
|
16
|
+
import { join } from 'node:path';
|
|
17
|
+
import { mkdir, readFile, readdir } from 'node:fs/promises';
|
|
18
|
+
import { promisify } from 'node:util';
|
|
19
|
+
|
|
20
|
+
const execFile = promisify(execFileCb);
|
|
21
|
+
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// Types
|
|
24
|
+
// ============================================================================
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Parsed git source components
|
|
28
|
+
*/
|
|
29
|
+
export interface ParsedGitSource {
|
|
30
|
+
url: string;
|
|
31
|
+
ref?: string;
|
|
32
|
+
cacheKey: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Manifest file (cognitive-core.json) at repo root
|
|
37
|
+
*/
|
|
38
|
+
export interface PlaybookManifest {
|
|
39
|
+
/** Relative path to playbook directory within the repo */
|
|
40
|
+
playbooks: string;
|
|
41
|
+
/** Optional version label */
|
|
42
|
+
version?: string;
|
|
43
|
+
/** Optional display name */
|
|
44
|
+
name?: string;
|
|
45
|
+
/** Optional description */
|
|
46
|
+
description?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* State persisted per resolved source (stored in system_state)
|
|
51
|
+
*/
|
|
52
|
+
export interface SourceState {
|
|
53
|
+
/** Original config source string */
|
|
54
|
+
source: string;
|
|
55
|
+
/** Resolved git URL (empty for local paths) */
|
|
56
|
+
url: string;
|
|
57
|
+
/** Requested ref (branch/tag/commit) */
|
|
58
|
+
ref: string;
|
|
59
|
+
/** Actual commit SHA loaded */
|
|
60
|
+
commitSha: string;
|
|
61
|
+
/** Local cache path */
|
|
62
|
+
cachePath: string;
|
|
63
|
+
/** Discovered playbook directory within cache */
|
|
64
|
+
playbookDir: string;
|
|
65
|
+
/** ISO timestamp of last successful load */
|
|
66
|
+
loadedAt: string;
|
|
67
|
+
/** Number of playbooks loaded from this source */
|
|
68
|
+
playbookCount: number;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Result of resolving a source
|
|
73
|
+
*/
|
|
74
|
+
export interface ResolveResult {
|
|
75
|
+
/** Local directory path containing playbook JSON files */
|
|
76
|
+
playbookDir: string;
|
|
77
|
+
/** Whether this is a git source */
|
|
78
|
+
isGit: boolean;
|
|
79
|
+
/** Commit SHA (only for git sources) */
|
|
80
|
+
commitSha?: string;
|
|
81
|
+
/** Whether the source was freshly cloned/updated */
|
|
82
|
+
updated: boolean;
|
|
83
|
+
/** Source identifier for provenance tracking */
|
|
84
|
+
sourceId: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Options for source resolution
|
|
89
|
+
*/
|
|
90
|
+
export interface ResolveOptions {
|
|
91
|
+
/** Cache directory (default: .atlas/curated-cache) */
|
|
92
|
+
cacheDir: string;
|
|
93
|
+
/** Maximum cache age in milliseconds before refreshing (default: 24h) */
|
|
94
|
+
maxAgeMs: number;
|
|
95
|
+
/** Force update regardless of cache age */
|
|
96
|
+
forceUpdate?: boolean;
|
|
97
|
+
/** Callback for loading/saving source state */
|
|
98
|
+
getSourceState?: (source: string) => SourceState | undefined;
|
|
99
|
+
setSourceState?: (source: string, state: SourceState) => void;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ============================================================================
|
|
103
|
+
// Public API
|
|
104
|
+
// ============================================================================
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Check if a source string is a git source (not a local path).
|
|
108
|
+
*/
|
|
109
|
+
export function isGitSource(source: string): boolean {
|
|
110
|
+
return (
|
|
111
|
+
source.startsWith('git:') ||
|
|
112
|
+
source.startsWith('github:') ||
|
|
113
|
+
source.startsWith('git@') ||
|
|
114
|
+
source.startsWith('git+')
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Parse a git source string into URL and optional ref components.
|
|
120
|
+
*
|
|
121
|
+
* Supported formats:
|
|
122
|
+
* - "git:https://github.com/org/repo"
|
|
123
|
+
* - "git:https://github.com/org/repo#v1.0.0"
|
|
124
|
+
* - "github:org/repo"
|
|
125
|
+
* - "github:org/repo#branch"
|
|
126
|
+
*/
|
|
127
|
+
export function parseGitSource(source: string): ParsedGitSource {
|
|
128
|
+
let raw = source;
|
|
129
|
+
|
|
130
|
+
// Strip prefix
|
|
131
|
+
if (raw.startsWith('git:')) {
|
|
132
|
+
raw = raw.slice(4);
|
|
133
|
+
} else if (raw.startsWith('git+')) {
|
|
134
|
+
raw = raw.slice(4);
|
|
135
|
+
} else if (raw.startsWith('github:')) {
|
|
136
|
+
const rest = raw.slice(7); // "org/repo" or "org/repo#ref"
|
|
137
|
+
const [path, ref] = rest.split('#', 2);
|
|
138
|
+
const url = `https://github.com/${path}.git`;
|
|
139
|
+
const cacheKey = `github.com/${path}`;
|
|
140
|
+
return { url, ref, cacheKey };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Parse ref from fragment
|
|
144
|
+
const hashIdx = raw.indexOf('#');
|
|
145
|
+
let url: string;
|
|
146
|
+
let ref: string | undefined;
|
|
147
|
+
|
|
148
|
+
if (hashIdx !== -1) {
|
|
149
|
+
url = raw.slice(0, hashIdx);
|
|
150
|
+
ref = raw.slice(hashIdx + 1);
|
|
151
|
+
} else {
|
|
152
|
+
url = raw;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Ensure .git suffix for HTTPS URLs
|
|
156
|
+
if (url.startsWith('https://') && !url.endsWith('.git')) {
|
|
157
|
+
url += '.git';
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Build cache key from URL (strip protocol + .git suffix)
|
|
161
|
+
const cacheKey = url
|
|
162
|
+
.replace(/^https?:\/\//, '')
|
|
163
|
+
.replace(/\.git$/, '');
|
|
164
|
+
|
|
165
|
+
return { url, ref, cacheKey };
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Resolve a playbook source to a local directory path.
|
|
170
|
+
*
|
|
171
|
+
* For local paths, returns the path as-is (after verifying it exists).
|
|
172
|
+
* For git sources, clones/updates to a cache directory and discovers
|
|
173
|
+
* the playbook directory within the repo.
|
|
174
|
+
*/
|
|
175
|
+
export async function resolvePlaybookSource(
|
|
176
|
+
source: string,
|
|
177
|
+
options: ResolveOptions,
|
|
178
|
+
): Promise<ResolveResult | null> {
|
|
179
|
+
// Local path — pass through
|
|
180
|
+
if (!isGitSource(source)) {
|
|
181
|
+
if (!existsSync(source)) {
|
|
182
|
+
console.warn(`[source-resolver] Local path does not exist: ${source}`);
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
playbookDir: source,
|
|
187
|
+
isGit: false,
|
|
188
|
+
updated: false,
|
|
189
|
+
sourceId: source,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Git source — parse, clone/update, discover
|
|
194
|
+
const parsed = parseGitSource(source);
|
|
195
|
+
const cachePath = join(options.cacheDir, parsed.cacheKey);
|
|
196
|
+
|
|
197
|
+
try {
|
|
198
|
+
// Ensure cache parent dir exists
|
|
199
|
+
await mkdir(cachePath, { recursive: true });
|
|
200
|
+
|
|
201
|
+
const isCloned = existsSync(join(cachePath, '.git'));
|
|
202
|
+
|
|
203
|
+
if (!isCloned) {
|
|
204
|
+
// First-time clone
|
|
205
|
+
await gitClone(parsed.url, parsed.ref, cachePath);
|
|
206
|
+
} else if (shouldUpdate(source, options)) {
|
|
207
|
+
// Update existing cache
|
|
208
|
+
await gitUpdate(parsed.ref, cachePath);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Get current commit SHA
|
|
212
|
+
const commitSha = await gitRevParse(cachePath);
|
|
213
|
+
|
|
214
|
+
// Check if we already loaded this exact SHA
|
|
215
|
+
const prevState = options.getSourceState?.(source);
|
|
216
|
+
if (prevState && prevState.commitSha === commitSha && !options.forceUpdate) {
|
|
217
|
+
return {
|
|
218
|
+
playbookDir: prevState.playbookDir,
|
|
219
|
+
isGit: true,
|
|
220
|
+
commitSha,
|
|
221
|
+
updated: false,
|
|
222
|
+
sourceId: source,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Discover playbook directory
|
|
227
|
+
const playbookDir = await discoverPlaybookDir(cachePath);
|
|
228
|
+
if (!playbookDir) {
|
|
229
|
+
console.warn(`[source-resolver] No playbook directory found in ${source}`);
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Persist source state
|
|
234
|
+
const state: SourceState = {
|
|
235
|
+
source,
|
|
236
|
+
url: parsed.url,
|
|
237
|
+
ref: parsed.ref ?? '',
|
|
238
|
+
commitSha,
|
|
239
|
+
cachePath,
|
|
240
|
+
playbookDir,
|
|
241
|
+
loadedAt: new Date().toISOString(),
|
|
242
|
+
playbookCount: 0, // Updated by caller after loading
|
|
243
|
+
};
|
|
244
|
+
options.setSourceState?.(source, state);
|
|
245
|
+
|
|
246
|
+
return {
|
|
247
|
+
playbookDir,
|
|
248
|
+
isGit: true,
|
|
249
|
+
commitSha,
|
|
250
|
+
updated: true,
|
|
251
|
+
sourceId: source,
|
|
252
|
+
};
|
|
253
|
+
} catch (error) {
|
|
254
|
+
// If we have a cached version, use it despite the error
|
|
255
|
+
if (existsSync(join(cachePath, '.git'))) {
|
|
256
|
+
console.warn(
|
|
257
|
+
`[source-resolver] Failed to update ${source}, using cached version:`,
|
|
258
|
+
error instanceof Error ? error.message : String(error),
|
|
259
|
+
);
|
|
260
|
+
const prevState = options.getSourceState?.(source);
|
|
261
|
+
if (prevState) {
|
|
262
|
+
return {
|
|
263
|
+
playbookDir: prevState.playbookDir,
|
|
264
|
+
isGit: true,
|
|
265
|
+
commitSha: prevState.commitSha,
|
|
266
|
+
updated: false,
|
|
267
|
+
sourceId: source,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
// Try to discover even without state
|
|
271
|
+
const playbookDir = await discoverPlaybookDir(cachePath);
|
|
272
|
+
if (playbookDir) {
|
|
273
|
+
return {
|
|
274
|
+
playbookDir,
|
|
275
|
+
isGit: true,
|
|
276
|
+
updated: false,
|
|
277
|
+
sourceId: source,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
console.warn(
|
|
283
|
+
`[source-resolver] Failed to resolve ${source}, skipping:`,
|
|
284
|
+
error instanceof Error ? error.message : String(error),
|
|
285
|
+
);
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// ============================================================================
|
|
291
|
+
// Git operations
|
|
292
|
+
// ============================================================================
|
|
293
|
+
|
|
294
|
+
async function gitClone(url: string, ref: string | undefined, dest: string): Promise<void> {
|
|
295
|
+
// Remove the directory first since mkdir already created it
|
|
296
|
+
rmSync(dest, { recursive: true, force: true });
|
|
297
|
+
|
|
298
|
+
const args = ['clone', '--depth', '1', '--single-branch'];
|
|
299
|
+
if (ref) {
|
|
300
|
+
args.push('--branch', ref);
|
|
301
|
+
}
|
|
302
|
+
args.push(url, dest);
|
|
303
|
+
|
|
304
|
+
await execFile('git', args, { timeout: 60_000 });
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async function gitUpdate(ref: string | undefined, cachePath: string): Promise<void> {
|
|
308
|
+
const fetchArgs = ['fetch', 'origin'];
|
|
309
|
+
if (ref) {
|
|
310
|
+
fetchArgs.push(ref);
|
|
311
|
+
}
|
|
312
|
+
await execFile('git', fetchArgs, { cwd: cachePath, timeout: 30_000 });
|
|
313
|
+
|
|
314
|
+
// Always use FETCH_HEAD — works for branches, tags, and commits.
|
|
315
|
+
// Using origin/${ref} would break for tags (refs/tags/*, not refs/remotes/origin/*).
|
|
316
|
+
await execFile('git', ['reset', '--hard', 'FETCH_HEAD'], {
|
|
317
|
+
cwd: cachePath,
|
|
318
|
+
timeout: 10_000,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
async function gitRevParse(cachePath: string): Promise<string> {
|
|
323
|
+
const { stdout } = await execFile('git', ['rev-parse', 'HEAD'], {
|
|
324
|
+
cwd: cachePath,
|
|
325
|
+
timeout: 5_000,
|
|
326
|
+
});
|
|
327
|
+
return stdout.trim();
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// ============================================================================
|
|
331
|
+
// Playbook directory discovery
|
|
332
|
+
// ============================================================================
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Discover the playbook directory within a cloned repo.
|
|
336
|
+
*
|
|
337
|
+
* Search order:
|
|
338
|
+
* 1. Manifest file (cognitive-core.json) at repo root
|
|
339
|
+
* 2. Convention: playbooks/ directory
|
|
340
|
+
* 3. Convention: curated-playbooks/ directory
|
|
341
|
+
* 4. Root directory if it contains .json files matching schema
|
|
342
|
+
*/
|
|
343
|
+
export async function discoverPlaybookDir(repoRoot: string): Promise<string | null> {
|
|
344
|
+
// 1. Check for manifest
|
|
345
|
+
const manifestPath = join(repoRoot, 'cognitive-core.json');
|
|
346
|
+
if (existsSync(manifestPath)) {
|
|
347
|
+
try {
|
|
348
|
+
const content = await readFile(manifestPath, 'utf-8');
|
|
349
|
+
const manifest = JSON.parse(content) as PlaybookManifest;
|
|
350
|
+
if (manifest.playbooks) {
|
|
351
|
+
const dir = join(repoRoot, manifest.playbooks);
|
|
352
|
+
if (existsSync(dir)) {
|
|
353
|
+
return dir;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
} catch {
|
|
357
|
+
// Invalid manifest, fall through to convention
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// 2. Convention: playbooks/
|
|
362
|
+
const playbooksDir = join(repoRoot, 'playbooks');
|
|
363
|
+
if (existsSync(playbooksDir) && statSync(playbooksDir).isDirectory()) {
|
|
364
|
+
return playbooksDir;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// 3. Convention: curated-playbooks/
|
|
368
|
+
const curatedDir = join(repoRoot, 'curated-playbooks');
|
|
369
|
+
if (existsSync(curatedDir) && statSync(curatedDir).isDirectory()) {
|
|
370
|
+
return curatedDir;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// 4. Check if root has JSON files that look like playbooks
|
|
374
|
+
if (await hasPlaybookJsonFiles(repoRoot)) {
|
|
375
|
+
return repoRoot;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Check if a directory contains at least one JSON file that looks like a playbook.
|
|
383
|
+
*/
|
|
384
|
+
async function hasPlaybookJsonFiles(dir: string): Promise<boolean> {
|
|
385
|
+
try {
|
|
386
|
+
const files = await readdir(dir);
|
|
387
|
+
const jsonFiles = files.filter(f => f.endsWith('.json'));
|
|
388
|
+
if (jsonFiles.length === 0) return false;
|
|
389
|
+
|
|
390
|
+
// Check first JSON file for required playbook fields
|
|
391
|
+
const content = await readFile(join(dir, jsonFiles[0]), 'utf-8');
|
|
392
|
+
const parsed = JSON.parse(content);
|
|
393
|
+
return !!(parsed.name && parsed.applicability && parsed.guidance);
|
|
394
|
+
} catch {
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// ============================================================================
|
|
400
|
+
// Cache management
|
|
401
|
+
// ============================================================================
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Determine whether a cached source should be updated.
|
|
405
|
+
*/
|
|
406
|
+
function shouldUpdate(source: string, options: ResolveOptions): boolean {
|
|
407
|
+
if (options.forceUpdate) return true;
|
|
408
|
+
|
|
409
|
+
const state = options.getSourceState?.(source);
|
|
410
|
+
if (!state) return true; // No previous state, always update
|
|
411
|
+
|
|
412
|
+
const loadedAt = new Date(state.loadedAt).getTime();
|
|
413
|
+
const age = Date.now() - loadedAt;
|
|
414
|
+
return age > options.maxAgeMs;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Generate the system_state key for a source.
|
|
419
|
+
*/
|
|
420
|
+
export function sourceStateKey(source: string): string {
|
|
421
|
+
return `curated-source:${source}`;
|
|
422
|
+
}
|
package/src/types/config.ts
CHANGED
|
@@ -513,6 +513,45 @@ export const SkillTreeConfigSchema = z.object({
|
|
|
513
513
|
dbPath: z.string().default('skills.db'),
|
|
514
514
|
});
|
|
515
515
|
|
|
516
|
+
/**
|
|
517
|
+
* Curated playbook cache configuration (for git sources)
|
|
518
|
+
*/
|
|
519
|
+
export const CuratedCacheConfigSchema = z.object({
|
|
520
|
+
/** Cache directory for cloned repos (relative to storage.baseDir, default: curated-cache) */
|
|
521
|
+
dir: z.string().default('curated-cache'),
|
|
522
|
+
/** Maximum cache age in milliseconds before refreshing (default: 24h) */
|
|
523
|
+
maxAgeMs: z.number().default(24 * 60 * 60 * 1000),
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
export type CuratedCacheConfig = z.infer<typeof CuratedCacheConfigSchema>;
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Curated playbook configuration
|
|
530
|
+
*/
|
|
531
|
+
export const CuratedPlaybooksConfigSchema = z.object({
|
|
532
|
+
/** Load the bundled compound-engineering seed pack on init */
|
|
533
|
+
loadBundledSeedPack: z.boolean().default(false),
|
|
534
|
+
/** Additional directories to load curated playbooks from (backward compat) */
|
|
535
|
+
additionalDirs: z.array(z.string()).default([]),
|
|
536
|
+
/**
|
|
537
|
+
* Playbook sources — local paths or git URIs.
|
|
538
|
+
*
|
|
539
|
+
* Supported formats:
|
|
540
|
+
* - Local path: "/path/to/playbooks"
|
|
541
|
+
* - Git URL: "git:https://github.com/org/repo" or "git:https://github.com/org/repo#v1.0.0"
|
|
542
|
+
* - GitHub shorthand: "github:org/repo" or "github:org/repo#branch"
|
|
543
|
+
*
|
|
544
|
+
* Git sources are cloned to a local cache and refreshed based on cache.maxAgeMs.
|
|
545
|
+
*/
|
|
546
|
+
sources: z.array(z.string()).default([]),
|
|
547
|
+
/** Cache configuration for git-based sources */
|
|
548
|
+
cache: CuratedCacheConfigSchema.default({}),
|
|
549
|
+
/** Re-create curated playbooks on each init (useful when updating seed files) */
|
|
550
|
+
recreateOnInit: z.boolean().default(false),
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
export type CuratedPlaybooksConfig = z.infer<typeof CuratedPlaybooksConfigSchema>;
|
|
554
|
+
|
|
516
555
|
export type SkillTreeConfig = z.infer<typeof SkillTreeConfigSchema>;
|
|
517
556
|
|
|
518
557
|
/**
|
|
@@ -570,6 +609,8 @@ export const AtlasConfigSchema = z.object({
|
|
|
570
609
|
knowledgeBank: KnowledgeBankConfigSchema.default({}),
|
|
571
610
|
/** Skill-tree storage configuration */
|
|
572
611
|
skillTree: SkillTreeConfigSchema.default({}),
|
|
612
|
+
/** Curated playbook seeding configuration */
|
|
613
|
+
curatedPlaybooks: CuratedPlaybooksConfigSchema.default({}),
|
|
573
614
|
/** Session bank configuration (Entire CLI integration) */
|
|
574
615
|
sessionBank: SessionBankConfigSchema.default({}),
|
|
575
616
|
/** Feature toggles for ruvector-inspired subsystems */
|
|
@@ -609,6 +650,11 @@ export function mergeConfig(
|
|
|
609
650
|
teamLearning: { ...base.teamLearning, ...overrides.teamLearning },
|
|
610
651
|
knowledgeBank: { ...base.knowledgeBank, ...overrides.knowledgeBank },
|
|
611
652
|
skillTree: { ...base.skillTree, ...overrides.skillTree },
|
|
653
|
+
curatedPlaybooks: {
|
|
654
|
+
...base.curatedPlaybooks,
|
|
655
|
+
...overrides.curatedPlaybooks,
|
|
656
|
+
cache: { ...base.curatedPlaybooks.cache, ...overrides.curatedPlaybooks?.cache },
|
|
657
|
+
},
|
|
612
658
|
sessionBank: { ...base.sessionBank, ...overrides.sessionBank },
|
|
613
659
|
features: { ...base.features, ...overrides.features },
|
|
614
660
|
});
|