cognitive-core 0.2.0 → 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/.claude/settings.json +111 -2
- package/.sessionlog/settings.json +4 -0
- 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/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/learning/index.d.ts +1 -1
- package/dist/learning/index.d.ts.map +1 -1
- package/dist/learning/index.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/learning/unified-pipeline.d.ts +30 -0
- package/dist/learning/unified-pipeline.d.ts.map +1 -1
- package/dist/learning/unified-pipeline.js +207 -0
- package/dist/learning/unified-pipeline.js.map +1 -1
- package/dist/memory/candidate-retrieval.d.ts.map +1 -1
- package/dist/memory/candidate-retrieval.js +3 -1
- package/dist/memory/candidate-retrieval.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/utils/error-classifier.js +8 -8
- package/dist/utils/error-classifier.js.map +1 -1
- package/dist/workspace/efficacy-toolkit.d.ts +164 -0
- package/dist/workspace/efficacy-toolkit.d.ts.map +1 -0
- package/dist/workspace/efficacy-toolkit.js +281 -0
- package/dist/workspace/efficacy-toolkit.js.map +1 -0
- package/dist/workspace/index.d.ts +2 -1
- package/dist/workspace/index.d.ts.map +1 -1
- package/dist/workspace/index.js +3 -1
- package/dist/workspace/index.js.map +1 -1
- package/dist/workspace/templates/index.d.ts +3 -0
- package/dist/workspace/templates/index.d.ts.map +1 -1
- package/dist/workspace/templates/index.js +6 -0
- package/dist/workspace/templates/index.js.map +1 -1
- package/dist/workspace/templates/playbook-decay-detection.d.ts +46 -0
- package/dist/workspace/templates/playbook-decay-detection.d.ts.map +1 -0
- package/dist/workspace/templates/playbook-decay-detection.js +197 -0
- package/dist/workspace/templates/playbook-decay-detection.js.map +1 -0
- package/dist/workspace/templates/playbook-efficacy-audit.d.ts +46 -0
- package/dist/workspace/templates/playbook-efficacy-audit.d.ts.map +1 -0
- package/dist/workspace/templates/playbook-efficacy-audit.js +160 -0
- package/dist/workspace/templates/playbook-efficacy-audit.js.map +1 -0
- package/dist/workspace/templates/playbook-lifecycle-review.d.ts +51 -0
- package/dist/workspace/templates/playbook-lifecycle-review.d.ts.map +1 -0
- package/dist/workspace/templates/playbook-lifecycle-review.js +187 -0
- package/dist/workspace/templates/playbook-lifecycle-review.js.map +1 -0
- 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 +8 -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/index.ts +27 -0
- package/src/learning/index.ts +1 -0
- package/src/learning/unified-pipeline.ts +271 -1
- package/src/memory/candidate-retrieval.ts +2 -1
- 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/utils/error-classifier.ts +8 -8
- package/src/workspace/efficacy-toolkit.ts +496 -0
- package/src/workspace/index.ts +29 -0
- package/src/workspace/templates/index.ts +24 -0
- package/src/workspace/templates/playbook-decay-detection.ts +272 -0
- package/src/workspace/templates/playbook-efficacy-audit.ts +246 -0
- package/src/workspace/templates/playbook-lifecycle-review.ts +274 -0
- package/src/workspace/types.ts +22 -78
- package/tests/fixtures/behavioral-trajectories.ts +210 -0
- package/tests/integration/curated-sources-e2e.test.ts +502 -0
- package/tests/integration/pipeline-data-correctness.test.ts +794 -0
- package/tests/learning/meta-learner.test.ts +418 -0
- package/tests/learning/pipeline-memory-updates.test.ts +721 -0
- package/tests/learning/unified-pipeline-efficacy.test.ts +232 -0
- package/tests/memory/candidate-retrieval.test.ts +167 -0
- package/tests/memory/compound-engineering-seed.test.ts +338 -0
- package/tests/memory/curated-loader-extended.test.ts +225 -0
- package/tests/memory/meta.test.ts +399 -0
- package/tests/memory/playbook-quality-validation.test.ts +430 -0
- package/tests/memory/source-resolver.test.ts +700 -0
- package/tests/search/evaluator.test.ts +257 -0
- package/tests/search/verification-runner.test.ts +357 -0
- package/tests/utils/error-classifier.test.ts +149 -0
- package/tests/utils/trajectory-helpers.test.ts +163 -0
- package/tests/workspace/efficacy-toolkit.test.ts +404 -0
- package/tests/workspace/templates/playbook-efficacy.test.ts +377 -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
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Registry system for sync path collision prevention
|
|
3
|
-
*
|
|
4
|
-
* The registry is stored in the central repo as .minimem-registry.json
|
|
5
|
-
* and tracks which local directories are mapped to which paths.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import fs from "node:fs/promises";
|
|
9
|
-
import path from "node:path";
|
|
10
|
-
import os from "node:os";
|
|
11
|
-
import crypto from "node:crypto";
|
|
12
|
-
|
|
13
|
-
const REGISTRY_FILENAME = ".minimem-registry.json";
|
|
14
|
-
|
|
15
|
-
export type RegistryMapping = {
|
|
16
|
-
/** Path in central repo (e.g., "global/", "work/") */
|
|
17
|
-
path: string;
|
|
18
|
-
/** Local directory path (with ~ for home) */
|
|
19
|
-
localPath: string;
|
|
20
|
-
/** Machine identifier */
|
|
21
|
-
machineId: string;
|
|
22
|
-
/** Last sync timestamp (ISO format) */
|
|
23
|
-
lastSync: string;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export type Registry = {
|
|
27
|
-
version: number;
|
|
28
|
-
mappings: RegistryMapping[];
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export type CollisionCheckResult = "none" | "same-machine" | "collision";
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Get the registry file path for a central repo
|
|
35
|
-
*/
|
|
36
|
-
export function getRegistryPath(centralRepo: string): string {
|
|
37
|
-
return path.join(centralRepo, REGISTRY_FILENAME);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Create an empty registry
|
|
42
|
-
*/
|
|
43
|
-
export function createEmptyRegistry(): Registry {
|
|
44
|
-
return {
|
|
45
|
-
version: 1,
|
|
46
|
-
mappings: [],
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Read registry from central repo
|
|
52
|
-
* Returns empty registry if file doesn't exist
|
|
53
|
-
*/
|
|
54
|
-
export async function readRegistry(centralRepo: string): Promise<Registry> {
|
|
55
|
-
const registryPath = getRegistryPath(centralRepo);
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
const content = await fs.readFile(registryPath, "utf-8");
|
|
59
|
-
const registry = JSON.parse(content) as Registry;
|
|
60
|
-
|
|
61
|
-
// Validate basic structure
|
|
62
|
-
if (!registry.mappings || !Array.isArray(registry.mappings)) {
|
|
63
|
-
return createEmptyRegistry();
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return registry;
|
|
67
|
-
} catch (error) {
|
|
68
|
-
// File doesn't exist or is invalid
|
|
69
|
-
return createEmptyRegistry();
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Write registry to central repo atomically
|
|
75
|
-
* Writes to temp file then renames to avoid corruption
|
|
76
|
-
*/
|
|
77
|
-
export async function writeRegistry(
|
|
78
|
-
centralRepo: string,
|
|
79
|
-
registry: Registry
|
|
80
|
-
): Promise<void> {
|
|
81
|
-
const registryPath = getRegistryPath(centralRepo);
|
|
82
|
-
const tempPath = `${registryPath}.${crypto.randomBytes(4).toString("hex")}.tmp`;
|
|
83
|
-
|
|
84
|
-
// Ensure version is set
|
|
85
|
-
registry.version = registry.version || 1;
|
|
86
|
-
|
|
87
|
-
// Write to temp file
|
|
88
|
-
await fs.writeFile(tempPath, JSON.stringify(registry, null, 2), "utf-8");
|
|
89
|
-
|
|
90
|
-
// Atomic rename
|
|
91
|
-
await fs.rename(tempPath, registryPath);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Normalize a path for comparison
|
|
96
|
-
* Expands ~ and resolves to absolute path
|
|
97
|
-
*/
|
|
98
|
-
export function normalizePath(filePath: string): string {
|
|
99
|
-
if (filePath.startsWith("~/")) {
|
|
100
|
-
return path.resolve(os.homedir(), filePath.slice(2));
|
|
101
|
-
}
|
|
102
|
-
if (filePath === "~") {
|
|
103
|
-
return os.homedir();
|
|
104
|
-
}
|
|
105
|
-
return path.resolve(filePath);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Compress a path for storage
|
|
110
|
-
* Replaces home directory with ~
|
|
111
|
-
*/
|
|
112
|
-
export function compressPath(filePath: string): string {
|
|
113
|
-
const home = os.homedir();
|
|
114
|
-
const resolved = path.resolve(filePath);
|
|
115
|
-
if (resolved.startsWith(home)) {
|
|
116
|
-
return "~" + resolved.slice(home.length);
|
|
117
|
-
}
|
|
118
|
-
return resolved;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Normalize central repo path (remove trailing slash, etc.)
|
|
123
|
-
*/
|
|
124
|
-
export function normalizeRepoPath(repoPath: string): string {
|
|
125
|
-
// Remove trailing slashes but keep at least one char
|
|
126
|
-
let normalized = repoPath.replace(/\/+$/, "");
|
|
127
|
-
if (normalized === "") {
|
|
128
|
-
normalized = "/";
|
|
129
|
-
}
|
|
130
|
-
// Ensure it ends with / for directory paths (except root)
|
|
131
|
-
if (!normalized.endsWith("/") && normalized !== "/") {
|
|
132
|
-
normalized += "/";
|
|
133
|
-
}
|
|
134
|
-
return normalized;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Check if a path mapping would collide with existing mappings
|
|
139
|
-
*
|
|
140
|
-
* Returns:
|
|
141
|
-
* - "none": path is free, can be used
|
|
142
|
-
* - "same-machine": same machine already has this path, can update
|
|
143
|
-
* - "collision": different machine has this path, blocked
|
|
144
|
-
*/
|
|
145
|
-
export function checkCollision(
|
|
146
|
-
registry: Registry,
|
|
147
|
-
centralPath: string,
|
|
148
|
-
localPath: string,
|
|
149
|
-
machineId: string
|
|
150
|
-
): CollisionCheckResult {
|
|
151
|
-
const normalizedCentralPath = normalizeRepoPath(centralPath);
|
|
152
|
-
const normalizedLocalPath = normalizePath(localPath);
|
|
153
|
-
|
|
154
|
-
for (const mapping of registry.mappings) {
|
|
155
|
-
const mappingCentralPath = normalizeRepoPath(mapping.path);
|
|
156
|
-
const mappingLocalPath = normalizePath(mapping.localPath);
|
|
157
|
-
|
|
158
|
-
// Check if central path matches
|
|
159
|
-
if (mappingCentralPath === normalizedCentralPath) {
|
|
160
|
-
// Same machine, same or different local path - can update
|
|
161
|
-
if (mapping.machineId === machineId) {
|
|
162
|
-
return "same-machine";
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Different machine - collision
|
|
166
|
-
return "collision";
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return "none";
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Add or update a mapping in the registry
|
|
175
|
-
*/
|
|
176
|
-
export function addMapping(
|
|
177
|
-
registry: Registry,
|
|
178
|
-
mapping: RegistryMapping
|
|
179
|
-
): Registry {
|
|
180
|
-
const normalizedPath = normalizeRepoPath(mapping.path);
|
|
181
|
-
const normalizedLocalPath = compressPath(mapping.localPath);
|
|
182
|
-
|
|
183
|
-
// Remove existing mapping for this path+machine combination
|
|
184
|
-
const filteredMappings = registry.mappings.filter(
|
|
185
|
-
(m) =>
|
|
186
|
-
!(
|
|
187
|
-
normalizeRepoPath(m.path) === normalizedPath &&
|
|
188
|
-
m.machineId === mapping.machineId
|
|
189
|
-
)
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
// Add new mapping
|
|
193
|
-
filteredMappings.push({
|
|
194
|
-
...mapping,
|
|
195
|
-
path: normalizedPath,
|
|
196
|
-
localPath: normalizedLocalPath,
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
return {
|
|
200
|
-
...registry,
|
|
201
|
-
mappings: filteredMappings,
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Remove a mapping from the registry
|
|
207
|
-
*/
|
|
208
|
-
export function removeMapping(
|
|
209
|
-
registry: Registry,
|
|
210
|
-
centralPath: string,
|
|
211
|
-
machineId: string
|
|
212
|
-
): Registry {
|
|
213
|
-
const normalizedPath = normalizeRepoPath(centralPath);
|
|
214
|
-
|
|
215
|
-
const filteredMappings = registry.mappings.filter(
|
|
216
|
-
(m) =>
|
|
217
|
-
!(normalizeRepoPath(m.path) === normalizedPath && m.machineId === machineId)
|
|
218
|
-
);
|
|
219
|
-
|
|
220
|
-
return {
|
|
221
|
-
...registry,
|
|
222
|
-
mappings: filteredMappings,
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Find a mapping by central path and machine ID
|
|
228
|
-
*/
|
|
229
|
-
export function findMapping(
|
|
230
|
-
registry: Registry,
|
|
231
|
-
centralPath: string,
|
|
232
|
-
machineId: string
|
|
233
|
-
): RegistryMapping | undefined {
|
|
234
|
-
const normalizedPath = normalizeRepoPath(centralPath);
|
|
235
|
-
|
|
236
|
-
return registry.mappings.find(
|
|
237
|
-
(m) =>
|
|
238
|
-
normalizeRepoPath(m.path) === normalizedPath && m.machineId === machineId
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Get all mappings for a specific machine
|
|
244
|
-
*/
|
|
245
|
-
export function getMachineMappings(
|
|
246
|
-
registry: Registry,
|
|
247
|
-
machineId: string
|
|
248
|
-
): RegistryMapping[] {
|
|
249
|
-
return registry.mappings.filter((m) => m.machineId === machineId);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Update the lastSync timestamp for a mapping
|
|
254
|
-
*/
|
|
255
|
-
export function updateLastSync(
|
|
256
|
-
registry: Registry,
|
|
257
|
-
centralPath: string,
|
|
258
|
-
machineId: string
|
|
259
|
-
): Registry {
|
|
260
|
-
const normalizedPath = normalizeRepoPath(centralPath);
|
|
261
|
-
|
|
262
|
-
const mappings = registry.mappings.map((m) => {
|
|
263
|
-
if (
|
|
264
|
-
normalizeRepoPath(m.path) === normalizedPath &&
|
|
265
|
-
m.machineId === machineId
|
|
266
|
-
) {
|
|
267
|
-
return {
|
|
268
|
-
...m,
|
|
269
|
-
lastSync: new Date().toISOString(),
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
return m;
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
return {
|
|
276
|
-
...registry,
|
|
277
|
-
mappings,
|
|
278
|
-
};
|
|
279
|
-
}
|
|
@@ -1,355 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sync state tracking with content hashing
|
|
3
|
-
*
|
|
4
|
-
* Tracks file hashes to detect changes between local directories
|
|
5
|
-
* and the central repository. Uses 2-way comparison (local vs remote).
|
|
6
|
-
*
|
|
7
|
-
* Conflict resolution: Last-write-wins
|
|
8
|
-
* - Push: local overwrites remote
|
|
9
|
-
* - Pull: remote overwrites local
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import fs from "node:fs/promises";
|
|
13
|
-
import path from "node:path";
|
|
14
|
-
import crypto from "node:crypto";
|
|
15
|
-
import { minimatch } from "minimatch";
|
|
16
|
-
|
|
17
|
-
const STATE_FILENAME = "sync-state.json";
|
|
18
|
-
const STATE_DIR = ".minimem";
|
|
19
|
-
|
|
20
|
-
export type FileHashInfo = {
|
|
21
|
-
/** SHA-256 hash of local file content */
|
|
22
|
-
localHash: string;
|
|
23
|
-
/** SHA-256 hash of remote file content */
|
|
24
|
-
remoteHash: string;
|
|
25
|
-
/** Last modified timestamp (ISO) */
|
|
26
|
-
lastModified: string;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
export type SyncState = {
|
|
30
|
-
/** Version for future migrations */
|
|
31
|
-
version: number;
|
|
32
|
-
/** Last sync timestamp (ISO) */
|
|
33
|
-
lastSync: string | null;
|
|
34
|
-
/** Central repo path this directory syncs to */
|
|
35
|
-
centralPath: string;
|
|
36
|
-
/** File hashes keyed by relative path */
|
|
37
|
-
files: Record<string, FileHashInfo>;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Get the sync state file path for a directory
|
|
42
|
-
*/
|
|
43
|
-
export function getSyncStatePath(dir: string): string {
|
|
44
|
-
return path.join(dir, STATE_DIR, STATE_FILENAME);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Create an empty sync state
|
|
49
|
-
*/
|
|
50
|
-
export function createEmptySyncState(centralPath: string): SyncState {
|
|
51
|
-
return {
|
|
52
|
-
version: 2, // Bumped version for simplified state
|
|
53
|
-
lastSync: null,
|
|
54
|
-
centralPath,
|
|
55
|
-
files: {},
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Load sync state from a directory
|
|
61
|
-
* Returns empty state if file doesn't exist
|
|
62
|
-
*/
|
|
63
|
-
export async function loadSyncState(
|
|
64
|
-
dir: string,
|
|
65
|
-
centralPath: string
|
|
66
|
-
): Promise<SyncState> {
|
|
67
|
-
const statePath = getSyncStatePath(dir);
|
|
68
|
-
|
|
69
|
-
try {
|
|
70
|
-
const content = await fs.readFile(statePath, "utf-8");
|
|
71
|
-
const state = JSON.parse(content) as SyncState;
|
|
72
|
-
|
|
73
|
-
// Validate basic structure
|
|
74
|
-
if (!state.files || typeof state.files !== "object") {
|
|
75
|
-
return createEmptySyncState(centralPath);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Update centralPath if it changed
|
|
79
|
-
state.centralPath = centralPath;
|
|
80
|
-
|
|
81
|
-
// Migrate v1 state (remove lastSyncedHash if present)
|
|
82
|
-
if (state.version === 1) {
|
|
83
|
-
for (const file of Object.keys(state.files)) {
|
|
84
|
-
const entry = state.files[file] as FileHashInfo & { lastSyncedHash?: string };
|
|
85
|
-
delete entry.lastSyncedHash;
|
|
86
|
-
}
|
|
87
|
-
state.version = 2;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return state;
|
|
91
|
-
} catch {
|
|
92
|
-
return createEmptySyncState(centralPath);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Save sync state atomically
|
|
98
|
-
*/
|
|
99
|
-
export async function saveSyncState(
|
|
100
|
-
dir: string,
|
|
101
|
-
state: SyncState
|
|
102
|
-
): Promise<void> {
|
|
103
|
-
const statePath = getSyncStatePath(dir);
|
|
104
|
-
const stateDir = path.dirname(statePath);
|
|
105
|
-
const tempPath = `${statePath}.${crypto.randomBytes(4).toString("hex")}.tmp`;
|
|
106
|
-
|
|
107
|
-
// Ensure directory exists
|
|
108
|
-
await fs.mkdir(stateDir, { recursive: true });
|
|
109
|
-
|
|
110
|
-
// Ensure version is set
|
|
111
|
-
state.version = state.version || 2;
|
|
112
|
-
|
|
113
|
-
// Write to temp file
|
|
114
|
-
await fs.writeFile(tempPath, JSON.stringify(state, null, 2), "utf-8");
|
|
115
|
-
|
|
116
|
-
// Atomic rename
|
|
117
|
-
await fs.rename(tempPath, statePath);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Compute SHA-256 hash of a file's content
|
|
122
|
-
*/
|
|
123
|
-
export async function computeFileHash(filePath: string): Promise<string> {
|
|
124
|
-
const content = await fs.readFile(filePath);
|
|
125
|
-
return crypto.createHash("sha256").update(content).digest("hex");
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Compute hash of string content
|
|
130
|
-
*/
|
|
131
|
-
export function computeContentHash(content: string | Buffer): string {
|
|
132
|
-
return crypto.createHash("sha256").update(content).digest("hex");
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* List files matching include/exclude patterns
|
|
137
|
-
*/
|
|
138
|
-
export async function listSyncableFiles(
|
|
139
|
-
dir: string,
|
|
140
|
-
include: string[],
|
|
141
|
-
exclude: string[]
|
|
142
|
-
): Promise<string[]> {
|
|
143
|
-
const files: string[] = [];
|
|
144
|
-
|
|
145
|
-
async function walkDir(currentDir: string, relativePath: string = "") {
|
|
146
|
-
const entries = await fs.readdir(currentDir, { withFileTypes: true });
|
|
147
|
-
|
|
148
|
-
for (const entry of entries) {
|
|
149
|
-
const entryPath = path.join(currentDir, entry.name);
|
|
150
|
-
const relPath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
|
|
151
|
-
|
|
152
|
-
// Skip .minimem directory
|
|
153
|
-
if (entry.name === ".minimem") continue;
|
|
154
|
-
|
|
155
|
-
if (entry.isDirectory()) {
|
|
156
|
-
await walkDir(entryPath, relPath);
|
|
157
|
-
} else if (entry.isFile()) {
|
|
158
|
-
// Check include patterns
|
|
159
|
-
const matchesInclude = include.some((pattern) =>
|
|
160
|
-
minimatch(relPath, pattern)
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
// Check exclude patterns
|
|
164
|
-
const matchesExclude = exclude.some((pattern) =>
|
|
165
|
-
minimatch(relPath, pattern)
|
|
166
|
-
);
|
|
167
|
-
|
|
168
|
-
if (matchesInclude && !matchesExclude) {
|
|
169
|
-
files.push(relPath);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
try {
|
|
176
|
-
await walkDir(dir);
|
|
177
|
-
} catch (error) {
|
|
178
|
-
// Directory might not exist yet
|
|
179
|
-
if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
180
|
-
throw error;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
return files.sort();
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Get file hash info, computing hash if file exists
|
|
189
|
-
*/
|
|
190
|
-
export async function getFileHashInfo(
|
|
191
|
-
filePath: string
|
|
192
|
-
): Promise<{ exists: boolean; hash?: string; mtime?: string }> {
|
|
193
|
-
try {
|
|
194
|
-
const stat = await fs.stat(filePath);
|
|
195
|
-
const hash = await computeFileHash(filePath);
|
|
196
|
-
return {
|
|
197
|
-
exists: true,
|
|
198
|
-
hash,
|
|
199
|
-
mtime: stat.mtime.toISOString(),
|
|
200
|
-
};
|
|
201
|
-
} catch {
|
|
202
|
-
return { exists: false };
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Sync status for a file (2-way comparison)
|
|
208
|
-
*
|
|
209
|
-
* With last-write-wins, there are no conflicts:
|
|
210
|
-
* - Push operations: local changes overwrite remote
|
|
211
|
-
* - Pull operations: remote changes overwrite local
|
|
212
|
-
*/
|
|
213
|
-
export type FileSyncStatus =
|
|
214
|
-
| "unchanged" // Both same
|
|
215
|
-
| "local-modified" // Local differs from remote (push will overwrite remote)
|
|
216
|
-
| "remote-modified"// Remote differs from local (pull will overwrite local)
|
|
217
|
-
| "local-only" // File exists only locally
|
|
218
|
-
| "remote-only"; // File exists only on remote
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Compare local and remote files to determine sync status
|
|
222
|
-
* Simple 2-way comparison (no 3-way merge needed with last-write-wins)
|
|
223
|
-
*/
|
|
224
|
-
export function getFileSyncStatus(
|
|
225
|
-
localHash: string | null,
|
|
226
|
-
remoteHash: string | null
|
|
227
|
-
): FileSyncStatus {
|
|
228
|
-
// Both exist and are the same
|
|
229
|
-
if (localHash && remoteHash && localHash === remoteHash) {
|
|
230
|
-
return "unchanged";
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// File exists in both but differs
|
|
234
|
-
if (localHash && remoteHash && localHash !== remoteHash) {
|
|
235
|
-
// With last-write-wins, caller decides direction
|
|
236
|
-
// Return "local-modified" to indicate a difference
|
|
237
|
-
return "local-modified";
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// File only exists locally
|
|
241
|
-
if (localHash && !remoteHash) {
|
|
242
|
-
return "local-only";
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// File only exists on remote
|
|
246
|
-
if (!localHash && remoteHash) {
|
|
247
|
-
return "remote-only";
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return "unchanged";
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* Update sync state after a successful sync
|
|
255
|
-
*/
|
|
256
|
-
export function updateSyncStateAfterSync(
|
|
257
|
-
state: SyncState,
|
|
258
|
-
filePath: string,
|
|
259
|
-
hash: string
|
|
260
|
-
): SyncState {
|
|
261
|
-
return {
|
|
262
|
-
...state,
|
|
263
|
-
lastSync: new Date().toISOString(),
|
|
264
|
-
files: {
|
|
265
|
-
...state.files,
|
|
266
|
-
[filePath]: {
|
|
267
|
-
localHash: hash,
|
|
268
|
-
remoteHash: hash,
|
|
269
|
-
lastModified: new Date().toISOString(),
|
|
270
|
-
},
|
|
271
|
-
},
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Remove a file from sync state
|
|
277
|
-
*/
|
|
278
|
-
export function removeFileFromSyncState(
|
|
279
|
-
state: SyncState,
|
|
280
|
-
filePath: string
|
|
281
|
-
): SyncState {
|
|
282
|
-
const { [filePath]: _, ...remainingFiles } = state.files;
|
|
283
|
-
return {
|
|
284
|
-
...state,
|
|
285
|
-
files: remainingFiles,
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* Build a complete sync state by scanning files
|
|
291
|
-
*/
|
|
292
|
-
export async function buildSyncState(
|
|
293
|
-
localDir: string,
|
|
294
|
-
remoteDir: string,
|
|
295
|
-
centralPath: string,
|
|
296
|
-
include: string[],
|
|
297
|
-
exclude: string[]
|
|
298
|
-
): Promise<{
|
|
299
|
-
state: SyncState;
|
|
300
|
-
changes: Array<{
|
|
301
|
-
file: string;
|
|
302
|
-
status: FileSyncStatus;
|
|
303
|
-
localHash: string | null;
|
|
304
|
-
remoteHash: string | null;
|
|
305
|
-
}>;
|
|
306
|
-
}> {
|
|
307
|
-
const state = createEmptySyncState(centralPath);
|
|
308
|
-
const changes: Array<{
|
|
309
|
-
file: string;
|
|
310
|
-
status: FileSyncStatus;
|
|
311
|
-
localHash: string | null;
|
|
312
|
-
remoteHash: string | null;
|
|
313
|
-
}> = [];
|
|
314
|
-
|
|
315
|
-
// Get all files from both sides
|
|
316
|
-
const [localFiles, remoteFiles] = await Promise.all([
|
|
317
|
-
listSyncableFiles(localDir, include, exclude),
|
|
318
|
-
listSyncableFiles(remoteDir, include, exclude),
|
|
319
|
-
]);
|
|
320
|
-
|
|
321
|
-
const allFiles = new Set([...localFiles, ...remoteFiles]);
|
|
322
|
-
|
|
323
|
-
for (const file of allFiles) {
|
|
324
|
-
const localPath = path.join(localDir, file);
|
|
325
|
-
const remotePath = path.join(remoteDir, file);
|
|
326
|
-
|
|
327
|
-
const [localInfo, remoteInfo] = await Promise.all([
|
|
328
|
-
getFileHashInfo(localPath),
|
|
329
|
-
getFileHashInfo(remotePath),
|
|
330
|
-
]);
|
|
331
|
-
|
|
332
|
-
const status = getFileSyncStatus(
|
|
333
|
-
localInfo.hash ?? null,
|
|
334
|
-
remoteInfo.hash ?? null
|
|
335
|
-
);
|
|
336
|
-
|
|
337
|
-
if (status !== "unchanged") {
|
|
338
|
-
changes.push({
|
|
339
|
-
file,
|
|
340
|
-
status,
|
|
341
|
-
localHash: localInfo.hash ?? null,
|
|
342
|
-
remoteHash: remoteInfo.hash ?? null,
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// Update state with current hashes
|
|
347
|
-
state.files[file] = {
|
|
348
|
-
localHash: localInfo.hash ?? "",
|
|
349
|
-
remoteHash: remoteInfo.hash ?? "",
|
|
350
|
-
lastModified: localInfo.mtime ?? remoteInfo.mtime ?? new Date().toISOString(),
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
return { state, changes };
|
|
355
|
-
}
|