akm-cli 0.9.0-rc.0 → 0.9.0-rc.13
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/CHANGELOG.md +1283 -22
- package/README.md +62 -37
- package/SECURITY.md +46 -31
- package/dist/akm +162 -38
- package/dist/akm-migrate +44 -0
- package/dist/assets/backends/schtasks-template.xml +2 -1
- package/dist/assets/hints/cli-hints-full.md +268 -118
- package/dist/assets/hints/cli-hints-short.md +87 -24
- package/dist/assets/{profiles → improve-strategies}/catchup.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/consolidate.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/default.json +6 -7
- package/dist/assets/improve-strategies/frequent.json +15 -0
- package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +4 -2
- package/dist/assets/{profiles → improve-strategies}/memory-focus.json +4 -1
- package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +5 -5
- package/dist/assets/{profiles → improve-strategies}/quick.json +4 -2
- package/dist/assets/improve-strategies/reflect-distill.json +30 -0
- package/dist/assets/{profiles → improve-strategies}/thorough.json +1 -1
- package/dist/assets/prompts/consolidate-system.md +5 -5
- package/dist/assets/prompts/extract-session.md +2 -6
- package/dist/assets/prompts/memory-infer-user.md +2 -3
- package/dist/assets/prompts/reflect-llm-framed-contract.md +11 -0
- package/dist/assets/prompts/reflect-llm-schema-contract.md +3 -0
- package/dist/assets/prompts/reflect-output-repair.md +3 -0
- package/dist/assets/prompts/workflow-unit-preamble.md +26 -0
- package/dist/assets/stash-skeleton/README.md +38 -10
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
- package/dist/assets/tasks/core/extract.yml +3 -2
- package/dist/assets/tasks/core/improve.yml +2 -1
- package/dist/assets/tasks/core/index-refresh.yml +1 -0
- package/dist/assets/tasks/core/sync.yml +1 -0
- package/dist/assets/tasks/core/version-check.yml +2 -1
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
- package/dist/assets/templates/html/health.html +5 -4
- package/dist/assets/workflows/workflow-template.md +31 -15
- package/dist/cli/invocation.js +279 -0
- package/dist/cli/parse-args.js +5 -90
- package/dist/cli/retired-commands.js +78 -0
- package/dist/cli/shared.js +158 -48
- package/dist/cli-node.mjs +2 -1
- package/dist/cli.js +747 -293
- package/dist/commands/agent/agent-dispatch.js +19 -18
- package/dist/commands/agent/agent-support.js +0 -24
- package/dist/commands/agent/contribute-cli.js +43 -97
- package/dist/commands/completions.js +80 -23
- package/dist/commands/config-cli.js +44 -281
- package/dist/commands/env/env-binding.js +99 -0
- package/dist/commands/env/env-cli.js +84 -224
- package/dist/commands/env/env.js +12 -163
- package/dist/commands/env/marker-path.js +6 -0
- package/dist/commands/env/secret-cli.js +45 -61
- package/dist/commands/env/secret.js +32 -62
- package/dist/commands/feedback-cli.js +179 -85
- package/dist/commands/health/accept-rate.js +58 -0
- package/dist/commands/health/advisories.js +7 -8
- package/dist/commands/health/checks.js +279 -94
- package/dist/commands/health/html-report.js +197 -578
- package/dist/commands/health/improve-metrics.js +277 -246
- package/dist/commands/health/llm-usage.js +19 -19
- package/dist/commands/health/md-report.js +16 -7
- package/dist/commands/health/metrics.js +67 -32
- package/dist/commands/health/renderers.js +47 -0
- package/dist/commands/health/report-view-model.js +508 -0
- package/dist/commands/health/stash-exposure.js +1 -1
- package/dist/commands/health/surfaces.js +16 -56
- package/dist/commands/health/task-runs.js +3 -67
- package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
- package/dist/commands/health/types-improve.js +29 -0
- package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
- package/dist/commands/health/types-result.js +7 -0
- package/dist/commands/health/types-runs.js +4 -0
- package/dist/commands/health/types-session-log.js +4 -0
- package/dist/commands/health/types-windows.js +4 -0
- package/dist/commands/health/types.js +26 -21
- package/dist/commands/health/windows.js +2 -3
- package/dist/commands/health.js +296 -167
- package/dist/commands/improve/anti-collapse.js +5 -5
- package/dist/commands/improve/autonomy-gate.js +68 -0
- package/dist/commands/improve/collapse-detector.js +65 -52
- package/dist/commands/improve/consolidate/chunking.js +9 -7
- package/dist/commands/improve/consolidate/eligibility.js +1 -23
- package/dist/commands/improve/consolidate/merge.js +4 -0
- package/dist/commands/improve/consolidate.js +454 -1354
- package/dist/commands/improve/content-hash.js +39 -0
- package/dist/commands/improve/distill/content-repair.js +4 -10
- package/dist/commands/improve/distill/promote-memory.js +89 -64
- package/dist/commands/improve/distill/quality-gate.js +118 -42
- package/dist/commands/improve/distill-guards.js +1 -1
- package/dist/commands/improve/distill-promotion-policy.js +33 -888
- package/dist/commands/improve/distill.js +607 -363
- package/dist/commands/improve/eligibility.js +165 -79
- package/dist/commands/improve/extract-cli.js +35 -126
- package/dist/commands/improve/extract-prompt.js +6 -35
- package/dist/commands/improve/extract.js +640 -391
- package/dist/commands/improve/feedback-valence.js +2 -12
- package/dist/commands/improve/improve-cli.js +134 -135
- package/dist/commands/improve/improve-result-file.js +30 -50
- package/dist/commands/improve/improve-run-types.js +4 -0
- package/dist/commands/improve/improve-strategies.js +135 -0
- package/dist/commands/improve/improve.js +904 -701
- package/dist/commands/improve/locks.js +64 -111
- package/dist/commands/improve/loop-stages.js +1110 -923
- package/dist/commands/improve/memory/derived-ref.js +124 -0
- package/dist/commands/improve/memory/memory-belief.js +79 -7
- package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
- package/dist/commands/improve/memory/memory-improve.js +25 -37
- package/dist/commands/improve/outcome-loop.js +25 -88
- package/dist/commands/improve/preparation.js +1034 -813
- package/dist/commands/improve/proactive-maintenance.js +34 -9
- package/dist/commands/improve/proposal-envelope.js +31 -0
- package/dist/commands/improve/reflect.js +983 -794
- package/dist/commands/improve/run-context.js +119 -0
- package/dist/commands/improve/salience.js +24 -127
- package/dist/commands/improve/session-asset.js +7 -3
- package/dist/commands/improve/shared.js +14 -34
- package/dist/commands/improve/source-identity.js +28 -0
- package/dist/commands/improve/triage.js +20 -17
- package/dist/commands/lint/base-linter.js +340 -313
- package/dist/commands/lint/env-key-rules.js +31 -47
- package/dist/commands/lint/index.js +185 -30
- package/dist/commands/{events.js → log.js} +28 -38
- package/dist/commands/migrate-cli.js +54 -0
- package/dist/commands/migration-tool.js +55 -0
- package/dist/commands/observability-cli.js +70 -208
- package/dist/commands/proposal/diff-format.js +50 -0
- package/dist/commands/proposal/drain-policies.js +0 -6
- package/dist/commands/proposal/drain.js +91 -40
- package/dist/commands/proposal/proposal-cli.js +134 -132
- package/dist/commands/proposal/proposal-types.js +56 -0
- package/dist/commands/proposal/proposal.js +83 -65
- package/dist/commands/proposal/propose-cli.js +88 -0
- package/dist/commands/proposal/propose.js +105 -88
- package/dist/commands/proposal/repository.js +1303 -278
- package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
- package/dist/commands/proposal/validators/proposal-validators.js +61 -12
- package/dist/commands/proposal/validators/proposals.js +6 -8
- package/dist/commands/read/curate.js +78 -73
- package/dist/commands/read/knowledge.js +510 -13
- package/dist/commands/read/registry-search.js +2 -2
- package/dist/commands/read/remember-cli.js +84 -15
- package/dist/commands/read/search-cli.js +203 -96
- package/dist/commands/read/search.js +126 -94
- package/dist/commands/read/show.js +226 -250
- package/dist/commands/registry-cli.js +34 -60
- package/dist/commands/remember.js +18 -57
- package/dist/commands/sources/add-cli.js +104 -49
- package/dist/commands/sources/bundle-cli.js +166 -0
- package/dist/commands/sources/bundle-config-ops.js +63 -0
- package/dist/commands/sources/info.js +27 -15
- package/dist/commands/sources/init.js +30 -40
- package/dist/commands/sources/installed-stashes.js +469 -172
- package/dist/commands/sources/migration-help.js +7 -4
- package/dist/commands/sources/schema-repair.js +10 -9
- package/dist/commands/sources/self-update.js +182 -121
- package/dist/commands/sources/source-add.js +169 -178
- package/dist/commands/sources/source-clone.js +144 -41
- package/dist/commands/sources/source-manage.js +94 -59
- package/dist/commands/sources/sources-cli.js +64 -205
- package/dist/commands/sources/stash-cli.js +91 -54
- package/dist/commands/sources/stash-skeleton.js +1 -1
- package/dist/commands/tasks/tasks-cli.js +106 -104
- package/dist/commands/tasks/tasks.js +445 -262
- package/dist/commands/workflow-cli.js +232 -121
- package/dist/core/action-contributors.js +1 -1
- package/dist/core/activation-policy.js +49 -0
- package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
- package/dist/core/adapter/adapters/akm-adapter.js +528 -0
- package/dist/core/adapter/adapters/akm-lint.js +392 -0
- package/dist/core/adapter/adapters/akm-metadata.js +387 -0
- package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
- package/dist/core/adapter/adapters/claude-adapter.js +61 -0
- package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
- package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
- package/dist/core/adapter/adapters/index.js +80 -0
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
- package/dist/core/adapter/adapters/okf-adapter.js +391 -0
- package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
- package/dist/core/adapter/adapters/shared.js +286 -0
- package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
- package/dist/core/adapter/bundle-adapter.js +4 -0
- package/dist/core/adapter/detect-adapter.js +17 -0
- package/dist/core/adapter/recognize-match.js +44 -0
- package/dist/core/adapter/registry.js +56 -0
- package/dist/core/adapter/types.js +4 -0
- package/dist/core/asset/akm-markdown.js +30 -0
- package/dist/core/asset/asset-placement.js +243 -0
- package/dist/core/asset/asset-ref.js +110 -79
- package/dist/core/asset/asset-serialize.js +20 -0
- package/dist/core/asset/frontmatter.js +28 -12
- package/dist/core/asset/markdown.js +40 -51
- package/dist/core/asset/resolve-ref.js +274 -0
- package/dist/core/asset/stash-meta.js +2 -2
- package/dist/core/bundle-id.js +51 -0
- package/dist/core/common.js +281 -86
- package/dist/core/config/config-io.js +42 -128
- package/dist/core/config/config-schema.js +233 -834
- package/dist/core/config/config-sources.js +162 -39
- package/dist/core/config/config-types.js +16 -11
- package/dist/core/config/config-version.js +29 -0
- package/dist/core/config/config-walker.js +126 -37
- package/dist/core/config/config.js +154 -331
- package/dist/core/config/deep-merge.js +41 -0
- package/dist/core/config/engine-semantics.js +28 -0
- package/dist/core/config/experimental.js +21 -0
- package/dist/core/config/schema/embedding.js +38 -0
- package/dist/core/config/schema/engines.js +116 -0
- package/dist/core/config/schema/experimental.js +47 -0
- package/dist/core/config/schema/feedback.js +31 -0
- package/dist/core/config/schema/improve-processes.js +389 -0
- package/dist/core/config/schema/improve.js +94 -0
- package/dist/core/config/schema/index-config.js +176 -0
- package/dist/core/config/schema/output.js +18 -0
- package/dist/core/config/schema/primitives.js +94 -0
- package/dist/core/config/schema/search.js +30 -0
- package/dist/core/config/schema/setup.js +18 -0
- package/dist/core/config/schema/sources-bundles.js +169 -0
- package/dist/core/config/schema/workflow.js +29 -0
- package/dist/core/env-secret-ref.js +155 -20
- package/dist/core/errors.js +17 -15
- package/dist/core/events-types.js +4 -0
- package/dist/core/events.js +46 -128
- package/dist/core/extra-params.js +62 -0
- package/dist/core/file-change.js +17 -0
- package/dist/core/file-lock.js +202 -57
- package/dist/core/fs-txn.js +392 -0
- package/dist/core/git-message.js +59 -0
- package/dist/core/improve-result.js +167 -0
- package/dist/core/json-schema.js +142 -0
- package/dist/core/lesson-lint.js +1 -17
- package/dist/core/logs-db.js +1 -1
- package/dist/core/maintenance-barrier.js +135 -0
- package/dist/core/migration-operation.js +44 -0
- package/dist/core/mutation-target.js +78 -0
- package/dist/core/paths.js +22 -25
- package/dist/core/platform.js +10 -0
- package/dist/core/recognition-util.js +128 -0
- package/dist/core/redaction.js +392 -0
- package/dist/core/standards/resolve-standards-context.js +36 -65
- package/dist/core/standards/resolve-stash-standards.js +2 -2
- package/dist/core/standards/resolve-type-conventions.js +5 -5
- package/dist/core/state/migrations.js +242 -11
- package/dist/core/state-db.js +98 -10
- package/dist/core/structured.js +1 -1
- package/dist/core/subprocess.js +303 -0
- package/dist/core/text-truncation.js +9 -5
- package/dist/core/time.js +20 -0
- package/dist/core/type-presentation.js +130 -0
- package/dist/core/warn.js +0 -3
- package/dist/core/write-source.js +834 -118
- package/dist/indexer/bundle-identity-guard.js +92 -0
- package/dist/indexer/db/graph-db.js +1 -25
- package/dist/indexer/db/llm-cache.js +1 -1
- package/dist/indexer/ensure-index.js +30 -9
- package/dist/indexer/graph/graph-boost.js +9 -30
- package/dist/indexer/graph/graph-extraction.js +41 -27
- package/dist/indexer/graph/graph-types.js +4 -0
- package/dist/indexer/index-writer-lock.js +93 -49
- package/dist/indexer/index-written-assets.js +100 -53
- package/dist/indexer/indexer.js +746 -329
- package/dist/indexer/init.js +18 -25
- package/dist/indexer/installations.js +142 -0
- package/dist/indexer/passes/dir-staleness.js +18 -10
- package/dist/indexer/passes/memory-inference.js +25 -15
- package/dist/indexer/passes/metadata.js +412 -243
- package/dist/indexer/scan/doc-to-entry.js +160 -0
- package/dist/indexer/scan/drain-dir.js +134 -0
- package/dist/indexer/search/db-search.js +292 -108
- package/dist/indexer/search/fts-query.js +64 -0
- package/dist/indexer/search/ranking-contributors.js +145 -25
- package/dist/indexer/search/ranking-types.js +4 -0
- package/dist/indexer/search/ranking.js +28 -71
- package/dist/indexer/search/search-attribution.js +67 -0
- package/dist/indexer/search/search-fields.js +18 -3
- package/dist/indexer/search/search-hit-enrichers.js +30 -40
- package/dist/indexer/search/search-source.js +157 -111
- package/dist/indexer/search/semantic-status.js +4 -1
- package/dist/indexer/usage/usage-events.js +10 -30
- package/dist/indexer/walk/file-context.js +3 -45
- package/dist/indexer/walk/matchers.js +42 -34
- package/dist/indexer/walk/path-resolver.js +11 -5
- package/dist/indexer/walk/walker.js +42 -14
- package/dist/integrations/agent/builder-shared.js +7 -0
- package/dist/integrations/agent/builders.js +5 -56
- package/dist/integrations/agent/config.js +3 -143
- package/dist/integrations/agent/detect.js +17 -2
- package/dist/integrations/agent/engine-resolution.js +231 -0
- package/dist/integrations/agent/index.js +1 -2
- package/dist/integrations/agent/model-aliases.js +16 -2
- package/dist/integrations/agent/profiles.js +36 -62
- package/dist/integrations/agent/prompts.js +46 -18
- package/dist/integrations/agent/runner-dispatch.js +93 -4
- package/dist/integrations/agent/runner.js +76 -208
- package/dist/integrations/agent/spawn.js +88 -196
- package/dist/integrations/harnesses/aider/agent-builder.js +114 -0
- package/dist/integrations/harnesses/aider/index.js +48 -0
- package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
- package/dist/integrations/harnesses/amazonq/agent-builder.js +147 -0
- package/dist/integrations/harnesses/amazonq/index.js +45 -0
- package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
- package/dist/integrations/harnesses/claude/agent-builder.js +46 -8
- package/dist/integrations/harnesses/claude/config-import.js +1 -3
- package/dist/integrations/harnesses/claude/index.js +24 -35
- package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
- package/dist/integrations/harnesses/claude/session-log.js +27 -75
- package/dist/integrations/harnesses/codex/agent-builder.js +138 -0
- package/dist/integrations/harnesses/codex/index.js +52 -0
- package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
- package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
- package/dist/integrations/harnesses/copilot/index.js +48 -0
- package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
- package/dist/integrations/harnesses/gemini/agent-builder.js +120 -0
- package/dist/integrations/harnesses/gemini/index.js +48 -0
- package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
- package/dist/integrations/harnesses/ids.js +24 -0
- package/dist/integrations/harnesses/index.js +54 -34
- package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
- package/dist/integrations/harnesses/opencode/config-import.js +1 -3
- package/dist/integrations/harnesses/opencode/index.js +14 -32
- package/dist/integrations/harnesses/opencode/session-log.js +67 -125
- package/dist/integrations/harnesses/opencode-sdk/harness.js +51 -0
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +681 -108
- package/dist/integrations/harnesses/openhands/agent-builder.js +128 -0
- package/dist/integrations/harnesses/openhands/index.js +48 -0
- package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
- package/dist/integrations/harnesses/pi/agent-builder.js +97 -0
- package/dist/integrations/harnesses/pi/index.js +45 -0
- package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
- package/dist/integrations/harnesses/shared.js +17 -0
- package/dist/integrations/harnesses/types.js +43 -32
- package/dist/integrations/lockfile.js +211 -24
- package/dist/integrations/session-logs/index.js +36 -39
- package/dist/integrations/session-logs/provider-base.js +113 -0
- package/dist/llm/client.js +182 -110
- package/dist/llm/embedders/deterministic.js +2 -2
- package/dist/llm/embedders/remote.js +21 -9
- package/dist/llm/feature-gate.js +17 -57
- package/dist/llm/graph-extract.js +12 -13
- package/dist/llm/index-passes.js +8 -42
- package/dist/llm/memory-infer.js +144 -1
- package/dist/llm/metadata-enhance.js +45 -30
- package/dist/llm/structured-call.js +16 -8
- package/dist/llm/usage-persist.js +30 -5
- package/dist/llm/usage-telemetry.js +59 -6
- package/dist/output/cli-hints.js +1 -2
- package/dist/output/command-registry.js +27 -0
- package/dist/output/context.js +22 -7
- package/dist/output/format-exempt.js +80 -0
- package/dist/output/generic-render.js +251 -0
- package/dist/output/html-render.js +11 -16
- package/dist/output/render-registry.js +57 -0
- package/dist/output/renderers.js +14 -279
- package/dist/output/shapes/curate.js +10 -1
- package/dist/output/shapes/events.js +12 -7
- package/dist/output/shapes/helpers.js +58 -84
- package/dist/output/shapes/passthrough.js +11 -39
- package/dist/output/shapes/proposal/producer.js +15 -7
- package/dist/output/shapes/registry.js +12 -6
- package/dist/output/shapes.js +0 -9
- package/dist/output/text/{init.js → bundle-create.js} +3 -1
- package/dist/output/text/bundle-show.js +7 -0
- package/dist/output/text/command-format.js +562 -0
- package/dist/output/text/env.js +1 -3
- package/dist/output/text/events.js +8 -7
- package/dist/output/text/helpers.js +15 -1164
- package/dist/output/text/proposal/producer.js +4 -2
- package/dist/output/text/proposal-format.js +202 -0
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/registry.js +12 -6
- package/dist/output/text/show-directives.js +117 -0
- package/dist/output/text/show-format.js +103 -0
- package/dist/output/text/sync.js +5 -0
- package/dist/output/text/workflow-format.js +332 -0
- package/dist/output/text/workflow.js +3 -2
- package/dist/output/text.js +10 -19
- package/dist/registry/factory.js +4 -6
- package/dist/registry/origin-resolve.js +16 -27
- package/dist/registry/providers/skills-sh.js +3 -3
- package/dist/registry/providers/static-index.js +15 -25
- package/dist/registry/resolve.js +43 -94
- package/dist/registry/semver.js +43 -0
- package/dist/runtime.js +81 -12
- package/dist/scripts/akm-migrate.js +35529 -0
- package/dist/setup/detect.js +5 -7
- package/dist/setup/detected-engines.js +136 -0
- package/dist/setup/engine-config.js +100 -0
- package/dist/setup/registry-stash-loader.js +3 -3
- package/dist/setup/semantic-assets.js +12 -9
- package/dist/setup/setup.js +444 -208
- package/dist/setup/steps/connection-shared.js +120 -0
- package/dist/setup/steps/connection.js +108 -305
- package/dist/setup/steps/platforms.js +13 -12
- package/dist/setup/steps/semantic.js +15 -3
- package/dist/setup/steps/sources.js +21 -15
- package/dist/setup/steps/stashdir.js +6 -4
- package/dist/setup/steps/tasks.js +236 -119
- package/dist/setup/steps.js +3 -2
- package/dist/sources/freshness.js +39 -0
- package/dist/sources/provider-factory.js +11 -17
- package/dist/sources/providers/filesystem.js +2 -3
- package/dist/sources/providers/git-install.js +278 -34
- package/dist/sources/providers/git-provider.js +54 -56
- package/dist/sources/providers/git-stash.js +420 -91
- package/dist/sources/providers/git.js +2 -2
- package/dist/sources/providers/npm.js +16 -19
- package/dist/sources/providers/provider-utils.js +47 -22
- package/dist/sources/providers/sync-from-ref.js +3 -9
- package/dist/sources/providers/website.js +2 -2
- package/dist/sources/resolve.js +11 -10
- package/dist/sources/snapshot-fetchers/types.js +4 -0
- package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
- package/dist/storage/database.js +60 -4
- package/dist/storage/engines/sqlite-migrations.js +156 -5
- package/dist/storage/locations.js +1 -2
- package/dist/storage/repositories/canaries-repository.js +1 -1
- package/dist/storage/repositories/events-repository.js +51 -11
- package/dist/storage/repositories/improve-runs-repository.js +6 -32
- package/dist/storage/repositories/index-connection.js +79 -0
- package/dist/storage/repositories/index-db.js +4 -3
- package/dist/storage/repositories/index-entries-repository.js +863 -0
- package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
- package/dist/storage/repositories/index-entry-types.js +4 -0
- package/dist/storage/repositories/index-fts-repository.js +167 -0
- package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
- package/dist/storage/repositories/index-meta-repository.js +49 -0
- package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
- package/dist/storage/repositories/index-sql.js +12 -0
- package/dist/storage/repositories/index-utility-repository.js +356 -0
- package/dist/storage/repositories/index-vec-repository.js +250 -0
- package/dist/storage/repositories/outcome-repository.js +119 -0
- package/dist/storage/repositories/proposals-repository.js +317 -75
- package/dist/storage/repositories/registry-cache.js +1 -1
- package/dist/storage/repositories/salience-repository.js +172 -0
- package/dist/storage/repositories/task-history-repository.js +110 -3
- package/dist/storage/repositories/workflow-runs-repository.js +240 -19
- package/dist/tasks/backends/cron.js +169 -46
- package/dist/tasks/backends/exec-utils.js +76 -3
- package/dist/tasks/backends/index.js +6 -9
- package/dist/tasks/backends/launchd.js +292 -55
- package/dist/tasks/backends/schtasks.js +557 -70
- package/dist/tasks/backends/types.js +4 -0
- package/dist/tasks/command-executable.js +93 -0
- package/dist/tasks/embedded.js +56 -38
- package/dist/tasks/parser.js +156 -64
- package/dist/tasks/resolve-akm-bin.js +144 -51
- package/dist/tasks/runner.js +377 -209
- package/dist/tasks/schedule.js +108 -19
- package/dist/tasks/scheduler-invocation.js +296 -0
- package/dist/tasks/schema.js +1 -1
- package/dist/tasks/task-id.js +35 -0
- package/dist/tasks/validator.js +30 -16
- package/dist/text-import-hook.mjs +1 -1
- package/dist/workflows/authoring/authoring.js +104 -43
- package/dist/workflows/authoring/scope-key.js +1 -1
- package/dist/workflows/cli.js +0 -16
- package/dist/workflows/concurrency-policy.js +15 -0
- package/dist/workflows/exec/brief.js +450 -0
- package/dist/workflows/exec/frozen-judge.js +47 -0
- package/dist/workflows/exec/native-executor.js +1038 -0
- package/dist/workflows/exec/param-secrets.js +115 -0
- package/dist/workflows/exec/report.js +1460 -0
- package/dist/workflows/exec/run-workflow.js +602 -0
- package/dist/workflows/exec/scheduler.js +71 -0
- package/dist/workflows/exec/step-work.js +1190 -0
- package/dist/workflows/exec/unit-writer.js +23 -0
- package/dist/workflows/exec/workflow-engine-gate.js +67 -0
- package/dist/workflows/exec/worktree.js +171 -0
- package/dist/workflows/ir/compile.js +246 -0
- package/dist/workflows/ir/freeze.js +233 -0
- package/dist/workflows/ir/params.js +54 -0
- package/dist/workflows/ir/plan-hash.js +68 -0
- package/dist/workflows/ir/schema.js +540 -0
- package/dist/workflows/parser.js +878 -304
- package/dist/workflows/program/expressions.js +181 -0
- package/dist/workflows/program/schema.js +51 -0
- package/dist/workflows/renderer.js +100 -45
- package/dist/workflows/resource-limits.js +22 -0
- package/dist/workflows/runtime/agent-identity.js +59 -14
- package/dist/workflows/runtime/checkin.js +1 -1
- package/dist/workflows/runtime/plan-classifier.js +131 -0
- package/dist/workflows/runtime/runs.js +376 -119
- package/dist/workflows/runtime/unit-checkin.js +45 -0
- package/dist/workflows/runtime/unit-phases.js +20 -0
- package/dist/workflows/runtime/workflow-asset-loader.js +241 -40
- package/dist/workflows/schema.js +1 -11
- package/dist/workflows/validate-summary.js +2 -3
- package/dist/workflows/validator.js +52 -30
- package/docs/README.md +42 -78
- package/docs/migration/README.md +8 -0
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +9 -8
- package/docs/migration/release-notes/0.9.0.md +158 -14
- package/docs/migration/v0.7-to-v0.8.md +46 -47
- package/docs/migration/v0.8-to-v0.9.md +844 -0
- package/docs/reference/README.md +12 -0
- package/docs/reference/data-and-telemetry.md +333 -0
- package/package.json +21 -17
- package/schemas/akm-asset-envelope.json +93 -0
- package/schemas/akm-config.json +4636 -0
- package/schemas/akm-task.json +87 -0
- package/schemas/akm-workflow.json +373 -0
- package/dist/akm-migrate-storage +0 -38
- package/dist/assets/help/help-accept.md +0 -12
- package/dist/assets/help/help-improve.md +0 -84
- package/dist/assets/help/help-proposals.md +0 -17
- package/dist/assets/help/help-propose.md +0 -17
- package/dist/assets/help/help-reject.md +0 -11
- package/dist/assets/profiles/frequent.json +0 -13
- package/dist/assets/profiles/recombine-only.json +0 -21
- package/dist/assets/profiles/reflect-distill.json +0 -30
- package/dist/assets/profiles/synthesize.json +0 -15
- package/dist/assets/prompts/procedural-system.md +0 -44
- package/dist/assets/prompts/recombine-system.md +0 -40
- package/dist/assets/prompts/staleness-detect-system.md +0 -6
- package/dist/assets/tasks/core/backup.yml +0 -4
- package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
- package/dist/assets/templates/html/default.html +0 -78
- package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
- package/dist/assets/wiki/index-template.md +0 -12
- package/dist/assets/wiki/ingest-workflow-template.md +0 -83
- package/dist/assets/wiki/log-template.md +0 -8
- package/dist/assets/wiki/schema-template.md +0 -61
- package/dist/cli/config-migrate.js +0 -150
- package/dist/cli/config-validate.js +0 -39
- package/dist/commands/graph/graph-cli.js +0 -124
- package/dist/commands/graph/graph.js +0 -487
- package/dist/commands/improve/calibration.js +0 -161
- package/dist/commands/improve/dedup.js +0 -482
- package/dist/commands/improve/extract-watch.js +0 -140
- package/dist/commands/improve/hot-probation.js +0 -45
- package/dist/commands/improve/improve-auto-accept.js +0 -276
- package/dist/commands/improve/improve-profiles.js +0 -168
- package/dist/commands/improve/procedural.js +0 -398
- package/dist/commands/improve/recombine.js +0 -818
- package/dist/commands/improve/schema-similarity-gate.js +0 -168
- package/dist/commands/lint/agent-linter.js +0 -44
- package/dist/commands/lint/command-linter.js +0 -44
- package/dist/commands/lint/default-linter.js +0 -16
- package/dist/commands/lint/fact-linter.js +0 -39
- package/dist/commands/lint/knowledge-linter.js +0 -16
- package/dist/commands/lint/memory-linter.js +0 -61
- package/dist/commands/lint/registry.js +0 -41
- package/dist/commands/lint/skill-linter.js +0 -45
- package/dist/commands/lint/task-linter.js +0 -50
- package/dist/commands/lint/workflow-linter.js +0 -81
- package/dist/commands/proposal/legacy-import.js +0 -115
- package/dist/commands/sources/history.js +0 -196
- package/dist/commands/tasks/default-tasks.js +0 -186
- package/dist/commands/wiki-cli.js +0 -292
- package/dist/core/asset/asset-registry.js +0 -76
- package/dist/core/asset/asset-spec.js +0 -259
- package/dist/core/config/config-migration.js +0 -602
- package/dist/core/deep-merge.js +0 -38
- package/dist/core/eval/rank-metrics.js +0 -113
- package/dist/core/ripgrep/install.js +0 -163
- package/dist/core/ripgrep/resolve.js +0 -81
- package/dist/indexer/db/db.js +0 -1413
- package/dist/indexer/manifest.js +0 -170
- package/dist/indexer/passes/metadata-contributors.js +0 -31
- package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
- package/dist/integrations/harnesses/opencode-sdk/index.js +0 -49
- package/dist/llm/call-ai.js +0 -62
- package/dist/llm/memory-infer-impl.js +0 -138
- package/dist/output/shapes/distill.js +0 -14
- package/dist/output/shapes/history.js +0 -11
- package/dist/output/text/distill.js +0 -6
- package/dist/output/text/enable-disable.js +0 -8
- package/dist/output/text/history.js +0 -6
- package/dist/output/text/wiki.js +0 -16
- package/dist/registry/build-index.js +0 -386
- package/dist/scripts/migrate-storage.js +0 -19108
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -9411
- package/dist/scripts/migrations/v16-to-v17.js +0 -141
- package/dist/setup/legacy-config.js +0 -106
- package/dist/storage/repositories/consolidation-repository.js +0 -38
- package/dist/storage/repositories/recombine-repository.js +0 -213
- package/dist/wiki/wiki-templates.js +0 -15
- package/dist/wiki/wiki.js +0 -1012
- package/dist/workflows/db.js +0 -215
- package/docs/data-and-telemetry.md +0 -226
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
import { randomBytes } from "node:crypto";
|
|
4
5
|
import fs from "node:fs";
|
|
5
6
|
import path from "node:path";
|
|
6
|
-
import {
|
|
7
|
+
import { akmAdapter } from "../../core/adapter/adapters/akm-adapter.js";
|
|
8
|
+
import { stashDirNames } from "../../core/asset/asset-placement.js";
|
|
7
9
|
import { resolveStashDir } from "../../core/common.js";
|
|
8
|
-
import { getSources, loadConfig } from "../../core/config/config.js";
|
|
10
|
+
import { getSources, loadConfig, resolveConfiguredSources } from "../../core/config/config.js";
|
|
9
11
|
import { UsageError } from "../../core/errors.js";
|
|
10
|
-
import { sanitizeCommitMessage } from "../../core/
|
|
12
|
+
import { sanitizeCommitMessage } from "../../core/git-message.js";
|
|
13
|
+
import { lockContentRootFor } from "../../integrations/lockfile.js";
|
|
11
14
|
import { runGit } from "./git-install.js";
|
|
12
15
|
import { getCachePaths, parseGitRepoUrl } from "./git-provider.js";
|
|
13
16
|
/**
|
|
@@ -22,15 +25,46 @@ import { getCachePaths, parseGitRepoUrl } from "./git-provider.js";
|
|
|
22
25
|
export function isGitBackedStash(stashDir) {
|
|
23
26
|
return fs.existsSync(path.join(stashDir, ".git"));
|
|
24
27
|
}
|
|
28
|
+
/** Return repo-relative dirty/staged paths without changing the index. */
|
|
29
|
+
export function listGitChangedPaths(repoDir) {
|
|
30
|
+
const result = runGit(["-C", repoDir, "status", "--porcelain", "-z", "--untracked-files=all"]);
|
|
31
|
+
if (result.status !== 0)
|
|
32
|
+
return [];
|
|
33
|
+
const records = result.stdout.split("\0");
|
|
34
|
+
const paths = [];
|
|
35
|
+
for (let i = 0; i < records.length; i++) {
|
|
36
|
+
const record = records[i];
|
|
37
|
+
if (!record)
|
|
38
|
+
continue;
|
|
39
|
+
const status = record.slice(0, 2);
|
|
40
|
+
paths.push(record.slice(3));
|
|
41
|
+
if (status.includes("R") || status.includes("C")) {
|
|
42
|
+
const previousPath = records[++i];
|
|
43
|
+
if (previousPath)
|
|
44
|
+
paths.push(previousPath);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return paths;
|
|
48
|
+
}
|
|
49
|
+
export class GitStashPushError extends Error {
|
|
50
|
+
commit;
|
|
51
|
+
constructor(message, commit) {
|
|
52
|
+
super(message);
|
|
53
|
+
this.name = "GitStashPushError";
|
|
54
|
+
this.commit = commit;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const GIT_PUSH_TIMEOUT_MS = 120_000;
|
|
58
|
+
const ZERO_OID = "0000000000000000000000000000000000000000";
|
|
25
59
|
/**
|
|
26
|
-
* Resolve the writable
|
|
27
|
-
*
|
|
28
|
-
* primary stash writable, otherwise `undefined` (leave the per-stash default
|
|
29
|
-
* untouched). Extracted so `akm sync`, `akm improve`'s end-of-run sync, and the
|
|
30
|
-
* CLI body all derive this identically instead of re-copying the expression.
|
|
60
|
+
* Resolve the writable flag for an end-of-run / `akm sync` commit from the
|
|
61
|
+
* configured default bundle.
|
|
31
62
|
*/
|
|
32
63
|
export function resolveWritableOverride(config) {
|
|
33
|
-
|
|
64
|
+
const source = resolveConfiguredSources(config).find((entry) => entry.name === config.defaultBundle);
|
|
65
|
+
if (!source)
|
|
66
|
+
return undefined;
|
|
67
|
+
return (source.writable ?? source.type === "filesystem") ? true : undefined;
|
|
34
68
|
}
|
|
35
69
|
/**
|
|
36
70
|
* Commit (and optionally push) local changes in a git-backed stash.
|
|
@@ -49,7 +83,7 @@ export function resolveWritableOverride(config) {
|
|
|
49
83
|
* primary stash dir (e.g. `akm improve`'s end-of-run sync, whose pre-commit
|
|
50
84
|
* gate validates that exact directory) pass it here so the gate and the commit
|
|
51
85
|
* operate on the SAME directory instead of independently calling
|
|
52
|
-
* `resolveStashDir(
|
|
86
|
+
* `resolveStashDir()`. When absent, behaviour is unchanged.
|
|
53
87
|
*/
|
|
54
88
|
export function saveGitStash(name, message, writableOverride, options) {
|
|
55
89
|
// `push: false` (from `akm sync --no-push`) commits but never pushes, even
|
|
@@ -62,8 +96,13 @@ export function saveGitStash(name, message, writableOverride, options) {
|
|
|
62
96
|
// Empty result falls back to the timestamped default.
|
|
63
97
|
const sanitized = message ? sanitizeCommitMessage(message) : "";
|
|
64
98
|
const commitMessage = sanitized || `akm save ${timestamp}`;
|
|
99
|
+
const transactionId = options?.transactionId;
|
|
100
|
+
if (transactionId !== undefined && !/^[A-Za-z0-9._-]{1,128}$/.test(transactionId)) {
|
|
101
|
+
throw new Error("Invalid Git transaction identifier.");
|
|
102
|
+
}
|
|
65
103
|
let repoDir;
|
|
66
104
|
let writable = false;
|
|
105
|
+
let managedContentRoot;
|
|
67
106
|
if (name) {
|
|
68
107
|
const config = loadConfig();
|
|
69
108
|
const stash = findGitStashByTarget(getSources(config), name);
|
|
@@ -72,17 +111,28 @@ export function saveGitStash(name, message, writableOverride, options) {
|
|
|
72
111
|
if (stash.type !== "git") {
|
|
73
112
|
throw new UsageError(`Stash "${name}" is not a git stash (type: ${stash.type})`);
|
|
74
113
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
114
|
+
const lockedRoot = lockContentRootFor(stash.name, stash.type);
|
|
115
|
+
if (lockedRoot) {
|
|
116
|
+
const topLevel = runGit(["-C", lockedRoot, "rev-parse", "--show-toplevel"]);
|
|
117
|
+
if (topLevel.status !== 0 || !topLevel.stdout.trim()) {
|
|
118
|
+
throw new UsageError(`Managed Git stash "${name}" is not a checkout at ${lockedRoot}`);
|
|
119
|
+
}
|
|
120
|
+
repoDir = path.resolve(topLevel.stdout.trim());
|
|
121
|
+
managedContentRoot = path.resolve(lockedRoot);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
if (!stash.url)
|
|
125
|
+
throw new UsageError(`Stash "${name}" has no URL configured`);
|
|
126
|
+
const repo = parseGitRepoUrl(stash.url);
|
|
127
|
+
repoDir = getCachePaths(repo.canonicalUrl).repoDir;
|
|
128
|
+
}
|
|
79
129
|
writable = stash.writable === true;
|
|
80
130
|
}
|
|
81
131
|
else {
|
|
82
132
|
// Honour an explicit primary-stash dir override (keeps the improve gate and
|
|
83
133
|
// the commit on the same directory); otherwise resolve the default.
|
|
84
|
-
repoDir = options?.repoDir ?? resolveStashDir(
|
|
85
|
-
// Allow caller to
|
|
134
|
+
repoDir = options?.repoDir ?? resolveStashDir();
|
|
135
|
+
// Allow the caller to pass the configured default bundle's writability.
|
|
86
136
|
if (writableOverride !== undefined) {
|
|
87
137
|
writable = writableOverride;
|
|
88
138
|
}
|
|
@@ -91,12 +141,11 @@ export function saveGitStash(name, message, writableOverride, options) {
|
|
|
91
141
|
if (!isGitBackedStash(repoDir)) {
|
|
92
142
|
return { committed: false, pushed: false, skipped: true, reason: "not a git repository", output: "" };
|
|
93
143
|
}
|
|
94
|
-
// Nothing to commit?
|
|
95
144
|
const statusResult = runGit(["-C", repoDir, "status", "--porcelain"]);
|
|
96
145
|
if (statusResult.error || statusResult.status !== 0) {
|
|
97
146
|
throw new Error(`git status failed: ${statusResult.error?.message || statusResult.stderr?.trim() || "unknown error"}`);
|
|
98
147
|
}
|
|
99
|
-
if (!statusResult.stdout.trim()) {
|
|
148
|
+
if (!statusResult.stdout.trim() && options?.paths === undefined) {
|
|
100
149
|
return { committed: false, pushed: false, skipped: false, output: "nothing to commit, working tree clean" };
|
|
101
150
|
}
|
|
102
151
|
// Scoped staging (#476 + the auto-sync incident): NEVER refuse akm's commit
|
|
@@ -107,103 +156,383 @@ export function saveGitStash(name, message, writableOverride, options) {
|
|
|
107
156
|
//
|
|
108
157
|
// Precedence:
|
|
109
158
|
// 1. Explicit modified-file list (`options.paths`) — stage exactly those.
|
|
110
|
-
// 2.
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (stagedResult.status === 0) {
|
|
159
|
+
// 2. A lock-backed content root, or managed adapter pathspecs for an
|
|
160
|
+
// ordinary stash. Both stay below AKM's resolved content boundary.
|
|
161
|
+
// 3. No resolvable managed path — no commit. Broad staging is never safe
|
|
162
|
+
// because it can absorb unrelated work already present in the index.
|
|
163
|
+
const managedRelativeRoot = managedContentRoot
|
|
164
|
+
? path.relative(repoDir, managedContentRoot).replaceAll(path.sep, "/")
|
|
165
|
+
: "";
|
|
166
|
+
const changedPaths = listGitChangedPaths(repoDir);
|
|
167
|
+
const requestedPaths = normalizeExactPaths(repoDir, options?.paths ??
|
|
168
|
+
(managedRelativeRoot && managedRelativeRoot !== ".." && !managedRelativeRoot.startsWith("../")
|
|
169
|
+
? changedPaths.filter((changedPath) => changedPath === managedRelativeRoot || changedPath.startsWith(`${managedRelativeRoot}/`))
|
|
170
|
+
: managedFallbackPaths(repoDir, changedPaths)));
|
|
171
|
+
if (requestedPaths.length === 0) {
|
|
124
172
|
return { committed: false, pushed: false, skipped: false, output: "nothing to commit" };
|
|
125
173
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
repoDir,
|
|
131
|
-
"-c",
|
|
132
|
-
"user.name=akm",
|
|
133
|
-
"-c",
|
|
134
|
-
"user.email=akm@local",
|
|
135
|
-
"commit",
|
|
136
|
-
"-m",
|
|
137
|
-
commitMessage,
|
|
138
|
-
]);
|
|
139
|
-
if (commitResult.status !== 0) {
|
|
140
|
-
throw new Error(`git commit failed: ${commitResult.stderr?.trim() || "unknown error"}`);
|
|
174
|
+
assertNoIgnoredExactPaths(repoDir, requestedPaths);
|
|
175
|
+
const baseHead = readOptionalHead(repoDir);
|
|
176
|
+
if (options?.expectedBaseHead !== undefined && (baseHead ?? null) !== options.expectedBaseHead) {
|
|
177
|
+
throw new Error(`Git target advanced before its exact-path commit could be created.`);
|
|
141
178
|
}
|
|
142
|
-
// Push only when there is a remote AND the stash is marked writable
|
|
143
179
|
const remoteResult = runGit(["-C", repoDir, "remote"]);
|
|
144
180
|
if (remoteResult.status !== 0) {
|
|
145
181
|
throw new Error(`git remote failed: ${remoteResult.stderr?.trim() || "unknown error"}`);
|
|
146
182
|
}
|
|
147
183
|
const hasRemote = remoteResult.stdout.trim().length > 0;
|
|
148
|
-
|
|
149
|
-
|
|
184
|
+
const pushTarget = hasRemote && writable && allowPush ? readActualUpstream(repoDir, baseHead) : undefined;
|
|
185
|
+
const exactCommit = createExactPathCommit(repoDir, {
|
|
186
|
+
baseHead,
|
|
187
|
+
commitMessage,
|
|
188
|
+
paths: requestedPaths,
|
|
189
|
+
transactionId,
|
|
190
|
+
expectedSnapshots: options?.expectedSnapshots,
|
|
191
|
+
});
|
|
192
|
+
if (!exactCommit) {
|
|
193
|
+
return { committed: false, pushed: false, skipped: false, output: "nothing to commit" };
|
|
150
194
|
}
|
|
151
|
-
|
|
195
|
+
if (!pushTarget) {
|
|
196
|
+
return {
|
|
197
|
+
committed: true,
|
|
198
|
+
pushed: false,
|
|
199
|
+
skipped: false,
|
|
200
|
+
output: `commit ${exactCommit}`,
|
|
201
|
+
commit: exactCommit,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
const pushResult = runGit([
|
|
205
|
+
"-C",
|
|
206
|
+
repoDir,
|
|
207
|
+
"push",
|
|
208
|
+
`--force-with-lease=${pushTarget.mergeRef}:${pushTarget.upstreamHead}`,
|
|
209
|
+
pushTarget.remote,
|
|
210
|
+
`${exactCommit}:${pushTarget.mergeRef}`,
|
|
211
|
+
], { timeout: GIT_PUSH_TIMEOUT_MS });
|
|
152
212
|
if (pushResult.status !== 0) {
|
|
153
|
-
throw new
|
|
213
|
+
throw new GitStashPushError(`git push failed: ${pushResult.stderr?.trim() || "unknown error"}`, exactCommit);
|
|
154
214
|
}
|
|
155
215
|
return {
|
|
156
216
|
committed: true,
|
|
157
217
|
pushed: true,
|
|
158
218
|
skipped: false,
|
|
159
|
-
output:
|
|
219
|
+
output: pushResult.stdout.trim() || "changes committed and pushed",
|
|
220
|
+
commit: exactCommit,
|
|
160
221
|
};
|
|
161
222
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
* the caller then detects "nothing staged" via `git diff --cached --quiet`).
|
|
167
|
-
*
|
|
168
|
-
* @param paths Optional explicit repo-relative paths akm wrote this run. When
|
|
169
|
-
* provided and non-empty, exactly those are staged (chunked to stay under
|
|
170
|
-
* argv length limits). Otherwise we fall back to the managed pathspecs, and
|
|
171
|
-
* finally to `git add -A` only if no managed pathspec exists on disk.
|
|
172
|
-
*/
|
|
173
|
-
function stageScopedChanges(repoDir, paths) {
|
|
174
|
-
// Precedence 1: explicit modified-file list.
|
|
175
|
-
const explicit = (paths ?? []).filter((p) => typeof p === "string" && p.length > 0);
|
|
176
|
-
if (explicit.length > 0) {
|
|
177
|
-
return addPathspecsChunked(repoDir, explicit);
|
|
178
|
-
}
|
|
179
|
-
// Precedence 2: managed pathspecs that exist on disk (TYPE_DIRS + `.akm`).
|
|
180
|
-
const managed = [...Object.values(TYPE_DIRS), ".akm"].filter((dir) => fs.existsSync(path.join(repoDir, dir)));
|
|
181
|
-
if (managed.length > 0) {
|
|
182
|
-
return addPathspecsChunked(repoDir, managed);
|
|
183
|
-
}
|
|
184
|
-
// Precedence 3 (last resort): nothing akm-managed resolved on disk. Stage
|
|
185
|
-
// everything. This is the ONLY branch that can include unrelated non-akm
|
|
186
|
-
// files — it is the explicit, maintainer-approved "or all files if we cannot
|
|
187
|
-
// determine the exact file list" fallback and should be rare/never in
|
|
188
|
-
// practice (a git-backed stash always has at least one managed subtree once
|
|
189
|
-
// akm has written to it).
|
|
190
|
-
const addAll = runGit(["-C", repoDir, "add", "-A"]);
|
|
191
|
-
return addAll.status === 0;
|
|
223
|
+
function managedFallbackPaths(repoDir, changedPaths) {
|
|
224
|
+
const ownedDirs = akmAdapter.directoryList?.({ id: "akm", adapter: "akm", root: repoDir, writable: false }) ?? stashDirNames();
|
|
225
|
+
const prefixes = [...ownedDirs, ".akm"];
|
|
226
|
+
return changedPaths.filter((changedPath) => prefixes.some((prefix) => changedPath === prefix || changedPath.startsWith(`${prefix}/`)));
|
|
192
227
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
228
|
+
function normalizeExactPaths(repoDir, paths) {
|
|
229
|
+
const normalized = [...new Set(paths.map((value) => value.replaceAll(path.sep, "/")))];
|
|
230
|
+
for (const filePath of normalized) {
|
|
231
|
+
const absolute = path.resolve(repoDir, filePath);
|
|
232
|
+
const relative = path.relative(repoDir, absolute).replaceAll(path.sep, "/");
|
|
233
|
+
if (!filePath ||
|
|
234
|
+
filePath.includes("\0") ||
|
|
235
|
+
path.isAbsolute(filePath) ||
|
|
236
|
+
relative !== filePath ||
|
|
237
|
+
relative === ".." ||
|
|
238
|
+
relative.startsWith("../")) {
|
|
239
|
+
throw new Error(`Unsafe exact Git path: ${filePath || "<empty>"}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return normalized;
|
|
243
|
+
}
|
|
244
|
+
function runExactPathChunks(repoDir, command, paths, options = {}) {
|
|
198
245
|
const CHUNK = 500;
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
246
|
+
const results = [];
|
|
247
|
+
for (let i = 0; i < paths.length; i += CHUNK) {
|
|
248
|
+
results.push(runGit(["--literal-pathspecs", "-C", repoDir, ...command, "--", ...paths.slice(i, i + CHUNK)], {
|
|
249
|
+
env: options.env,
|
|
250
|
+
}));
|
|
251
|
+
}
|
|
252
|
+
return results;
|
|
253
|
+
}
|
|
254
|
+
export function listIgnoredExactPaths(repoDir, paths) {
|
|
255
|
+
if (paths.length === 0)
|
|
256
|
+
return [];
|
|
257
|
+
const input = `${paths.join("\0")}\0`;
|
|
258
|
+
const result = runGit(["-C", repoDir, "check-ignore", "-z", "--stdin"], { input });
|
|
259
|
+
if (result.status === 1)
|
|
260
|
+
return [];
|
|
261
|
+
if (result.status !== 0) {
|
|
262
|
+
throw new Error(`git check-ignore failed: ${result.stderr.trim() || "unknown error"}`);
|
|
263
|
+
}
|
|
264
|
+
return result.stdout.split("\0").filter(Boolean);
|
|
265
|
+
}
|
|
266
|
+
export function assertNoIgnoredExactPaths(repoDir, paths) {
|
|
267
|
+
const ignored = listIgnoredExactPaths(repoDir, normalizeExactPaths(repoDir, paths));
|
|
268
|
+
if (ignored.length > 0) {
|
|
269
|
+
throw new UsageError(`Exact Git publication path is ignored: ${ignored[0]}. Update .gitignore or choose a tracked destination before writing.`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
/** Reject exact staged/unstaged paths before an AKM filesystem mutation. */
|
|
273
|
+
export function assertGitExactPathsClean(repoDir, paths) {
|
|
274
|
+
const normalized = normalizeExactPaths(repoDir, paths);
|
|
275
|
+
assertNoIgnoredExactPaths(repoDir, normalized);
|
|
276
|
+
for (const result of runExactPathChunks(repoDir, ["status", "--porcelain=v1", "-z", "--untracked-files=all"], normalized)) {
|
|
277
|
+
if (result.status !== 0) {
|
|
278
|
+
throw new Error(`git status failed: ${result.stderr.trim() || "unknown error"}`);
|
|
279
|
+
}
|
|
280
|
+
if (result.stdout.length > 0) {
|
|
281
|
+
const record = result.stdout.split("\0").find(Boolean) ?? "";
|
|
282
|
+
throw new UsageError(`Exact Git operation path has staged or unstaged work: ${record.slice(3)}. Commit, stash, or discard that path before retrying.`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function readOptionalHead(repoDir) {
|
|
287
|
+
const result = runGit(["-C", repoDir, "rev-parse", "--verify", "HEAD"]);
|
|
288
|
+
return result.status === 0 && result.stdout.trim() ? result.stdout.trim() : undefined;
|
|
289
|
+
}
|
|
290
|
+
function readBranchRef(repoDir) {
|
|
291
|
+
const result = runGit(["-C", repoDir, "symbolic-ref", "--quiet", "HEAD"]);
|
|
292
|
+
if (result.status !== 0 || !result.stdout.trim()) {
|
|
293
|
+
throw new UsageError(`Writable Git target at ${repoDir} is detached from a branch.`);
|
|
294
|
+
}
|
|
295
|
+
return result.stdout.trim();
|
|
296
|
+
}
|
|
297
|
+
function readActualUpstream(repoDir, baseHead) {
|
|
298
|
+
if (!baseHead)
|
|
299
|
+
throw new UsageError(`Writable Git target at ${repoDir} has no commit to publish.`);
|
|
300
|
+
const branchRef = readBranchRef(repoDir);
|
|
301
|
+
const branch = branchRef.replace(/^refs\/heads\//, "");
|
|
302
|
+
const remote = runGit(["-C", repoDir, "config", "--get", `branch.${branch}.remote`]);
|
|
303
|
+
const merge = runGit(["-C", repoDir, "config", "--get", `branch.${branch}.merge`]);
|
|
304
|
+
const upstream = runGit(["-C", repoDir, "rev-parse", "--verify", "@{u}"]);
|
|
305
|
+
if (remote.status !== 0 || merge.status !== 0 || upstream.status !== 0) {
|
|
306
|
+
throw new UsageError(`Writable Git target at ${repoDir} has no configured upstream branch.`);
|
|
307
|
+
}
|
|
308
|
+
const upstreamHead = upstream.stdout.trim();
|
|
309
|
+
if (!upstreamHead || upstreamHead !== baseHead) {
|
|
310
|
+
throw new UsageError(`Writable Git target at ${repoDir} is not synchronized with its actual upstream.`);
|
|
311
|
+
}
|
|
312
|
+
return { remote: remote.stdout.trim(), mergeRef: merge.stdout.trim(), upstreamHead };
|
|
313
|
+
}
|
|
314
|
+
function readIndexEntries(repoDir, paths) {
|
|
315
|
+
const entries = new Map(paths.map((filePath) => [filePath, []]));
|
|
316
|
+
for (const result of runExactPathChunks(repoDir, ["ls-files", "--stage", "-z"], paths)) {
|
|
202
317
|
if (result.status !== 0)
|
|
318
|
+
throw new Error(`Cannot inspect Git index: ${result.stderr.trim() || "unknown error"}`);
|
|
319
|
+
for (const record of result.stdout.split("\0")) {
|
|
320
|
+
if (!record)
|
|
321
|
+
continue;
|
|
322
|
+
const tab = record.indexOf("\t");
|
|
323
|
+
const match = record.slice(0, tab).match(/^(\d+) ([0-9a-f]+) (\d+)$/);
|
|
324
|
+
if (tab < 0 || !match)
|
|
325
|
+
throw new Error(`Cannot parse Git index entry.`);
|
|
326
|
+
const filePath = record.slice(tab + 1);
|
|
327
|
+
entries.get(filePath)?.push({ mode: match[1], oid: match[2], stage: Number(match[3]) });
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return entries;
|
|
331
|
+
}
|
|
332
|
+
function readTreeStates(repoDir, treeish, paths) {
|
|
333
|
+
const states = new Map(paths.map((filePath) => [filePath, null]));
|
|
334
|
+
if (!treeish)
|
|
335
|
+
return states;
|
|
336
|
+
for (const result of runExactPathChunks(repoDir, ["ls-tree", "-z", treeish], paths)) {
|
|
337
|
+
if (result.status !== 0)
|
|
338
|
+
throw new Error(`Cannot inspect Git tree: ${result.stderr.trim() || "unknown error"}`);
|
|
339
|
+
for (const record of result.stdout.split("\0")) {
|
|
340
|
+
if (!record)
|
|
341
|
+
continue;
|
|
342
|
+
const tab = record.indexOf("\t");
|
|
343
|
+
const match = record.slice(0, tab).match(/^(\d+) blob ([0-9a-f]+)$/);
|
|
344
|
+
if (tab < 0 || !match)
|
|
345
|
+
throw new Error(`Exact Git path is not a blob.`);
|
|
346
|
+
const mode = match[1];
|
|
347
|
+
if (mode !== "100644" && mode !== "100755" && mode !== "120000") {
|
|
348
|
+
throw new Error(`Unsupported Git mode ${mode}.`);
|
|
349
|
+
}
|
|
350
|
+
states.set(record.slice(tab + 1), { mode, oid: match[2] });
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return states;
|
|
354
|
+
}
|
|
355
|
+
function assertIndexMatchesBase(paths, indexEntries, baseStates) {
|
|
356
|
+
if (indexMatchesTree(paths, indexEntries, baseStates))
|
|
357
|
+
return;
|
|
358
|
+
const dirtyPath = paths.find((filePath) => {
|
|
359
|
+
const entries = indexEntries.get(filePath) ?? [];
|
|
360
|
+
const base = baseStates.get(filePath) ?? null;
|
|
361
|
+
return !(base === null
|
|
362
|
+
? entries.length === 0
|
|
363
|
+
: entries.length === 1 &&
|
|
364
|
+
entries[0]?.stage === 0 &&
|
|
365
|
+
entries[0]?.mode === base.mode &&
|
|
366
|
+
entries[0]?.oid === base.oid);
|
|
367
|
+
});
|
|
368
|
+
throw new UsageError(`Exact Git operation path has staged work: ${dirtyPath ?? paths[0]}. Commit, stash, or discard that path before retrying.`);
|
|
369
|
+
}
|
|
370
|
+
function indexMatchesTree(paths, indexEntries, treeStates) {
|
|
371
|
+
for (const filePath of paths) {
|
|
372
|
+
const entries = indexEntries.get(filePath) ?? [];
|
|
373
|
+
const state = treeStates.get(filePath) ?? null;
|
|
374
|
+
if (!(state === null
|
|
375
|
+
? entries.length === 0
|
|
376
|
+
: entries.length === 1 &&
|
|
377
|
+
entries[0]?.stage === 0 &&
|
|
378
|
+
entries[0]?.mode === state.mode &&
|
|
379
|
+
entries[0]?.oid === state.oid)) {
|
|
203
380
|
return false;
|
|
381
|
+
}
|
|
204
382
|
}
|
|
205
383
|
return true;
|
|
206
384
|
}
|
|
385
|
+
/** Repair only the stale base index left by a crash after an exact commit CAS. */
|
|
386
|
+
export function reconcileGitExactPathIndex(repoDir, baseCommit, commit, paths) {
|
|
387
|
+
const normalized = normalizeExactPaths(repoDir, paths);
|
|
388
|
+
const current = readIndexEntries(repoDir, normalized);
|
|
389
|
+
const committedStates = readTreeStates(repoDir, commit, normalized);
|
|
390
|
+
if (indexMatchesTree(normalized, current, committedStates))
|
|
391
|
+
return;
|
|
392
|
+
const baseStates = readTreeStates(repoDir, baseCommit, normalized);
|
|
393
|
+
if (!indexMatchesTree(normalized, current, baseStates)) {
|
|
394
|
+
throw new UsageError(`Exact Git operation path has staged work after transaction recovery. Commit, stash, or discard it before retrying.`);
|
|
395
|
+
}
|
|
396
|
+
for (const result of runExactPathChunks(repoDir, ["reset", "--quiet", commit], normalized)) {
|
|
397
|
+
if (result.status !== 0)
|
|
398
|
+
throw new Error(`git index cleanup failed during exact transaction recovery`);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
function captureWorktreeState(repoDir, filePath) {
|
|
402
|
+
const absolutePath = path.join(repoDir, filePath);
|
|
403
|
+
let stat;
|
|
404
|
+
try {
|
|
405
|
+
stat = fs.lstatSync(absolutePath);
|
|
406
|
+
}
|
|
407
|
+
catch (error) {
|
|
408
|
+
if (error.code === "ENOENT")
|
|
409
|
+
return null;
|
|
410
|
+
throw error;
|
|
411
|
+
}
|
|
412
|
+
let mode;
|
|
413
|
+
let result;
|
|
414
|
+
if (stat.isSymbolicLink()) {
|
|
415
|
+
mode = "120000";
|
|
416
|
+
result = runGit(["-C", repoDir, "hash-object", "--stdin"], { input: fs.readlinkSync(absolutePath) });
|
|
417
|
+
}
|
|
418
|
+
else if (stat.isFile()) {
|
|
419
|
+
mode = stat.mode & 0o111 ? "100755" : "100644";
|
|
420
|
+
result = runGit(["-C", repoDir, "hash-object", `--path=${filePath}`, "--", absolutePath]);
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
423
|
+
throw new Error(`Exact Git publication path is not a file: ${filePath}`);
|
|
424
|
+
}
|
|
425
|
+
if (result.status !== 0 || !result.stdout.trim()) {
|
|
426
|
+
throw new Error(`Cannot hash exact Git publication path: ${filePath}`);
|
|
427
|
+
}
|
|
428
|
+
return { oid: result.stdout.trim(), mode };
|
|
429
|
+
}
|
|
430
|
+
function samePathState(left, right) {
|
|
431
|
+
return left === null ? right === null : right !== null && left.oid === right.oid && left.mode === right.mode;
|
|
432
|
+
}
|
|
433
|
+
function assertWorktreeMatchesExpected(repoDir, paths, expected) {
|
|
434
|
+
for (const filePath of paths) {
|
|
435
|
+
if (!samePathState(captureWorktreeState(repoDir, filePath), expected.get(filePath) ?? null)) {
|
|
436
|
+
throw new Error(`Exact Git publication path changed while committing: ${filePath}`);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
function sameIndexEntries(left, right) {
|
|
441
|
+
return JSON.stringify([...left]) === JSON.stringify([...right]);
|
|
442
|
+
}
|
|
443
|
+
function resetRealIndexPaths(repoDir, commit, paths, initial) {
|
|
444
|
+
const current = readIndexEntries(repoDir, paths);
|
|
445
|
+
if (!sameIndexEntries(initial, current))
|
|
446
|
+
return;
|
|
447
|
+
for (const result of runExactPathChunks(repoDir, ["reset", "--quiet", commit], paths)) {
|
|
448
|
+
if (result.status !== 0)
|
|
449
|
+
throw new Error(`git index cleanup failed after exact commit`);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
function createExactPathCommit(repoDir, options) {
|
|
453
|
+
const branchRef = readBranchRef(repoDir);
|
|
454
|
+
const baseStates = readTreeStates(repoDir, options.baseHead, options.paths);
|
|
455
|
+
const initialIndex = readIndexEntries(repoDir, options.paths);
|
|
456
|
+
assertIndexMatchesBase(options.paths, initialIndex, baseStates);
|
|
457
|
+
const expected = new Map();
|
|
458
|
+
for (const filePath of options.paths) {
|
|
459
|
+
expected.set(filePath, options.expectedSnapshots && Object.hasOwn(options.expectedSnapshots, filePath)
|
|
460
|
+
? (options.expectedSnapshots[filePath] ?? null)
|
|
461
|
+
: captureWorktreeState(repoDir, filePath));
|
|
462
|
+
}
|
|
463
|
+
const gitIndex = runGit(["-C", repoDir, "rev-parse", "--git-path", "index"]);
|
|
464
|
+
if (gitIndex.status !== 0 || !gitIndex.stdout.trim())
|
|
465
|
+
throw new Error(`Cannot resolve Git index path.`);
|
|
466
|
+
const realIndexPath = path.resolve(repoDir, gitIndex.stdout.trim());
|
|
467
|
+
const temporaryIndex = `${realIndexPath}.akm-${process.pid}-${randomBytes(6).toString("hex")}`;
|
|
468
|
+
const env = { GIT_INDEX_FILE: temporaryIndex };
|
|
469
|
+
try {
|
|
470
|
+
const seeded = options.baseHead
|
|
471
|
+
? runGit(["-C", repoDir, "read-tree", options.baseHead], { env })
|
|
472
|
+
: runGit(["-C", repoDir, "read-tree", "--empty"], { env });
|
|
473
|
+
if (seeded.status !== 0)
|
|
474
|
+
throw new Error(`Cannot seed temporary Git index: ${seeded.stderr.trim()}`);
|
|
475
|
+
const stagePaths = options.paths.filter((filePath) => (expected.get(filePath) ?? null) !== null || (baseStates.get(filePath) ?? null) !== null);
|
|
476
|
+
for (const result of runExactPathChunks(repoDir, ["add", "-A"], stagePaths, { env })) {
|
|
477
|
+
if (result.status !== 0)
|
|
478
|
+
throw new Error(`Cannot stage exact Git paths: ${result.stderr.trim()}`);
|
|
479
|
+
}
|
|
480
|
+
const tree = runGit(["-C", repoDir, "write-tree"], { env });
|
|
481
|
+
if (tree.status !== 0 || !tree.stdout.trim())
|
|
482
|
+
throw new Error(`Cannot write exact Git tree.`);
|
|
483
|
+
const treeOid = tree.stdout.trim();
|
|
484
|
+
const committedStates = readTreeStates(repoDir, treeOid, options.paths);
|
|
485
|
+
for (const filePath of options.paths) {
|
|
486
|
+
if (!samePathState(committedStates.get(filePath) ?? null, expected.get(filePath) ?? null)) {
|
|
487
|
+
throw new Error(`Exact Git publication path changed while committing: ${filePath}`);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
assertWorktreeMatchesExpected(repoDir, options.paths, expected);
|
|
491
|
+
const baseTreeResult = options.baseHead
|
|
492
|
+
? runGit(["-C", repoDir, "rev-parse", `${options.baseHead}^{tree}`])
|
|
493
|
+
: undefined;
|
|
494
|
+
if (baseTreeResult && (baseTreeResult.status !== 0 || !baseTreeResult.stdout.trim())) {
|
|
495
|
+
throw new Error(`Cannot inspect base Git tree.`);
|
|
496
|
+
}
|
|
497
|
+
const baseTree = baseTreeResult?.stdout.trim() ?? "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
498
|
+
if (treeOid === baseTree)
|
|
499
|
+
return null;
|
|
500
|
+
const body = options.transactionId
|
|
501
|
+
? `${options.commitMessage}\n\nAKM-Transaction: ${options.transactionId}\n`
|
|
502
|
+
: `${options.commitMessage}\n`;
|
|
503
|
+
const commit = runGit([
|
|
504
|
+
"-C",
|
|
505
|
+
repoDir,
|
|
506
|
+
"-c",
|
|
507
|
+
"user.name=akm",
|
|
508
|
+
"-c",
|
|
509
|
+
"user.email=akm@local",
|
|
510
|
+
"commit-tree",
|
|
511
|
+
treeOid,
|
|
512
|
+
...(options.baseHead ? ["-p", options.baseHead] : []),
|
|
513
|
+
], { input: body });
|
|
514
|
+
if (commit.status !== 0 || !commit.stdout.trim()) {
|
|
515
|
+
throw new Error(`git commit-tree failed: ${commit.stderr.trim() || "unknown error"}`);
|
|
516
|
+
}
|
|
517
|
+
const commitOid = commit.stdout.trim();
|
|
518
|
+
const currentBranch = readBranchRef(repoDir);
|
|
519
|
+
const currentHead = readOptionalHead(repoDir);
|
|
520
|
+
if (currentBranch !== branchRef || currentHead !== options.baseHead) {
|
|
521
|
+
throw new Error(`Git target changed before its exact commit could be attached.`);
|
|
522
|
+
}
|
|
523
|
+
assertWorktreeMatchesExpected(repoDir, options.paths, expected);
|
|
524
|
+
const update = runGit(["-C", repoDir, "update-ref", branchRef, commitOid, options.baseHead ?? ZERO_OID]);
|
|
525
|
+
if (update.status !== 0) {
|
|
526
|
+
throw new Error(`Git target advanced before its exact commit could be attached.`);
|
|
527
|
+
}
|
|
528
|
+
resetRealIndexPaths(repoDir, commitOid, options.paths, initialIndex);
|
|
529
|
+
return commitOid;
|
|
530
|
+
}
|
|
531
|
+
finally {
|
|
532
|
+
fs.rmSync(temporaryIndex, { force: true });
|
|
533
|
+
fs.rmSync(`${temporaryIndex}.lock`, { force: true });
|
|
534
|
+
}
|
|
535
|
+
}
|
|
207
536
|
function findGitStashByTarget(stashes, target) {
|
|
208
537
|
return stashes.find((stash) => matchesGitStashTarget(stash, target));
|
|
209
538
|
}
|
|
@@ -8,6 +8,6 @@
|
|
|
8
8
|
//
|
|
9
9
|
// Re-exported here so every consumer (and every `spyOn(gitProvider, …)` test)
|
|
10
10
|
// keeps importing from a single module namespace.
|
|
11
|
-
export { classifyCloneFailure, cloneRepo,
|
|
11
|
+
export { classifyCloneFailure, cloneRepo, inspectGitUpstream, runGit, syncExistingWritableCheckout, } from "./git-install.js";
|
|
12
12
|
export { ensureGitMirror, GitSourceProvider, getCachePaths, parseGitRepoUrl, syncMirroredRepo, } from "./git-provider.js";
|
|
13
|
-
export { isGitBackedStash, resolveWritableOverride, saveGitStash, } from "./git-stash.js";
|
|
13
|
+
export { GitStashPushError, isGitBackedStash, listGitChangedPaths, resolveWritableOverride, saveGitStash, } from "./git-stash.js";
|