akm-cli 0.7.0 → 0.7.1
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/package.json +8 -8
- package/dist/tests/add-website-source.test.js +0 -119
- package/dist/tests/agent/agent-config-loader.test.js +0 -70
- package/dist/tests/agent/agent-config.test.js +0 -221
- package/dist/tests/agent/agent-detect.test.js +0 -100
- package/dist/tests/agent/agent-spawn.test.js +0 -234
- package/dist/tests/agent-output.test.js +0 -186
- package/dist/tests/architecture/agent-no-llm-sdk-guard.test.js +0 -103
- package/dist/tests/architecture/agent-spawn-seam.test.js +0 -193
- package/dist/tests/architecture/llm-stateless-seam.test.js +0 -112
- package/dist/tests/asset-ref.test.js +0 -192
- package/dist/tests/asset-registry.test.js +0 -103
- package/dist/tests/asset-spec.test.js +0 -241
- package/dist/tests/bench/attribution.test.js +0 -996
- package/dist/tests/bench/cleanup-sigint.test.js +0 -83
- package/dist/tests/bench/cleanup.js +0 -234
- package/dist/tests/bench/cleanup.test.js +0 -166
- package/dist/tests/bench/cli.js +0 -1018
- package/dist/tests/bench/cli.test.js +0 -445
- package/dist/tests/bench/compare.test.js +0 -556
- package/dist/tests/bench/corpus.js +0 -317
- package/dist/tests/bench/corpus.test.js +0 -258
- package/dist/tests/bench/doctor.js +0 -525
- package/dist/tests/bench/driver.js +0 -401
- package/dist/tests/bench/driver.test.js +0 -584
- package/dist/tests/bench/environment.js +0 -233
- package/dist/tests/bench/environment.test.js +0 -199
- package/dist/tests/bench/evolve-metrics.js +0 -179
- package/dist/tests/bench/evolve-metrics.test.js +0 -187
- package/dist/tests/bench/evolve.js +0 -647
- package/dist/tests/bench/evolve.test.js +0 -624
- package/dist/tests/bench/failure-modes.test.js +0 -349
- package/dist/tests/bench/feedback-integrity.test.js +0 -457
- package/dist/tests/bench/leakage.test.js +0 -228
- package/dist/tests/bench/learning-curve.test.js +0 -134
- package/dist/tests/bench/metrics.js +0 -2395
- package/dist/tests/bench/metrics.test.js +0 -1150
- package/dist/tests/bench/no-os-tmpdir-invariant.test.js +0 -43
- package/dist/tests/bench/opencode-config.js +0 -194
- package/dist/tests/bench/opencode-config.test.js +0 -370
- package/dist/tests/bench/report.js +0 -1885
- package/dist/tests/bench/report.test.js +0 -1038
- package/dist/tests/bench/run-config.js +0 -355
- package/dist/tests/bench/run-config.test.js +0 -298
- package/dist/tests/bench/run-curate-test.js +0 -32
- package/dist/tests/bench/run-failing-tasks.js +0 -56
- package/dist/tests/bench/run-full-bench.js +0 -51
- package/dist/tests/bench/run-items36-targeted.js +0 -69
- package/dist/tests/bench/run-nano-quick.js +0 -42
- package/dist/tests/bench/run-waveg-targeted.js +0 -62
- package/dist/tests/bench/runner.js +0 -699
- package/dist/tests/bench/runner.test.js +0 -958
- package/dist/tests/bench/search-bridge.test.js +0 -331
- package/dist/tests/bench/tmp.js +0 -131
- package/dist/tests/bench/trajectory.js +0 -116
- package/dist/tests/bench/trajectory.test.js +0 -127
- package/dist/tests/bench/verifier.js +0 -114
- package/dist/tests/bench/verifier.test.js +0 -118
- package/dist/tests/bench/workflow-evaluator.js +0 -557
- package/dist/tests/bench/workflow-evaluator.test.js +0 -421
- package/dist/tests/bench/workflow-spec.js +0 -345
- package/dist/tests/bench/workflow-spec.test.js +0 -363
- package/dist/tests/bench/workflow-trace.js +0 -472
- package/dist/tests/bench/workflow-trace.test.js +0 -254
- package/dist/tests/benchmark-search-quality.js +0 -536
- package/dist/tests/benchmark-suite.js +0 -1441
- package/dist/tests/capture-cli.test.js +0 -112
- package/dist/tests/cli-errors.test.js +0 -204
- package/dist/tests/commands/events.test.js +0 -370
- package/dist/tests/commands/history.test.js +0 -418
- package/dist/tests/commands/import.test.js +0 -103
- package/dist/tests/commands/proposal-cli.test.js +0 -209
- package/dist/tests/commands/reflect-propose-cli.test.js +0 -333
- package/dist/tests/commands/remember.test.js +0 -97
- package/dist/tests/commands/scope-flags.test.js +0 -300
- package/dist/tests/commands/search.test.js +0 -537
- package/dist/tests/commands/show-indexer-parity.test.js +0 -117
- package/dist/tests/commands/show.test.js +0 -294
- package/dist/tests/common.test.js +0 -266
- package/dist/tests/completions.test.js +0 -142
- package/dist/tests/config-cli.test.js +0 -193
- package/dist/tests/config-llm-features.test.js +0 -139
- package/dist/tests/config.test.js +0 -569
- package/dist/tests/contracts/migration-baseline.test.js +0 -43
- package/dist/tests/contracts/reflect-propose-envelope.test.js +0 -139
- package/dist/tests/contracts/spec-helpers.js +0 -46
- package/dist/tests/contracts/v1-spec-section-11-proposal-queue.test.js +0 -228
- package/dist/tests/contracts/v1-spec-section-12-agent-config.test.js +0 -56
- package/dist/tests/contracts/v1-spec-section-13-lesson-type.test.js +0 -34
- package/dist/tests/contracts/v1-spec-section-14-llm-features.test.js +0 -94
- package/dist/tests/contracts/v1-spec-section-4-1-asset-types.test.js +0 -39
- package/dist/tests/contracts/v1-spec-section-4-2-quality-rules.test.js +0 -44
- package/dist/tests/contracts/v1-spec-section-5-configuration.test.js +0 -47
- package/dist/tests/contracts/v1-spec-section-6-orchestration.test.js +0 -40
- package/dist/tests/contracts/v1-spec-section-7-module-layout.test.js +0 -58
- package/dist/tests/contracts/v1-spec-section-8-extension-points.test.js +0 -34
- package/dist/tests/contracts/v1-spec-section-9-4-cli-surface.test.js +0 -75
- package/dist/tests/contracts/v1-spec-section-9-7-llm-agent-boundary.test.js +0 -36
- package/dist/tests/core/write-source.test.js +0 -366
- package/dist/tests/curate-command.test.js +0 -87
- package/dist/tests/db-scoring.test.js +0 -201
- package/dist/tests/db.test.js +0 -654
- package/dist/tests/distill-cli-flag.test.js +0 -208
- package/dist/tests/distill.test.js +0 -515
- package/dist/tests/docker-install.test.js +0 -120
- package/dist/tests/e2e.test.js +0 -1419
- package/dist/tests/embedder.test.js +0 -340
- package/dist/tests/embedding-model-config.test.js +0 -379
- package/dist/tests/feedback-command.test.js +0 -172
- package/dist/tests/file-context.test.js +0 -552
- package/dist/tests/fixtures/scripts/git/summarize-diff.js +0 -9
- package/dist/tests/fixtures/scripts/lint/eslint-check.js +0 -7
- package/dist/tests/fixtures/stashes/load.js +0 -166
- package/dist/tests/fixtures/stashes/load.test.js +0 -97
- package/dist/tests/fixtures/stashes/ranking-baseline/scripts/mem0-search.js +0 -12
- package/dist/tests/frontmatter.test.js +0 -190
- package/dist/tests/fts-field-weighting.test.js +0 -254
- package/dist/tests/fuzzy-search.test.js +0 -230
- package/dist/tests/git-provider-clone.test.js +0 -45
- package/dist/tests/github.test.js +0 -161
- package/dist/tests/graph-boost-ranking.test.js +0 -305
- package/dist/tests/graph-extraction.test.js +0 -282
- package/dist/tests/helpers/usage-events.js +0 -8
- package/dist/tests/index-pass-llm.test.js +0 -161
- package/dist/tests/indexer.test.js +0 -570
- package/dist/tests/info-command.test.js +0 -166
- package/dist/tests/init.test.js +0 -69
- package/dist/tests/install-script.test.js +0 -246
- package/dist/tests/integration/agent-real-profile.test.js +0 -94
- package/dist/tests/issue-36-repro.test.js +0 -304
- package/dist/tests/issues-191-194.test.js +0 -160
- package/dist/tests/lesson-lint.test.js +0 -111
- package/dist/tests/llm-client.test.js +0 -115
- package/dist/tests/llm-feature-gate.test.js +0 -151
- package/dist/tests/llm.test.js +0 -139
- package/dist/tests/lockfile.test.js +0 -216
- package/dist/tests/manifest.test.js +0 -205
- package/dist/tests/markdown.test.js +0 -126
- package/dist/tests/matchers-unit.test.js +0 -189
- package/dist/tests/memory-inference.test.js +0 -299
- package/dist/tests/merge-scoring.test.js +0 -136
- package/dist/tests/metadata.test.js +0 -313
- package/dist/tests/migration-help.test.js +0 -89
- package/dist/tests/origin-resolve.test.js +0 -124
- package/dist/tests/output-baseline.test.js +0 -218
- package/dist/tests/output-shapes-unit.test.js +0 -478
- package/dist/tests/parallel-search.test.js +0 -272
- package/dist/tests/parameter-metadata.test.js +0 -365
- package/dist/tests/paths.test.js +0 -177
- package/dist/tests/progressive-disclosure.test.js +0 -280
- package/dist/tests/proposals.test.js +0 -279
- package/dist/tests/proposed-quality.test.js +0 -271
- package/dist/tests/provider-registry.test.js +0 -32
- package/dist/tests/ranking-regression.test.js +0 -548
- package/dist/tests/reflect-propose.test.js +0 -455
- package/dist/tests/registry-build-index.test.js +0 -394
- package/dist/tests/registry-cli.test.js +0 -290
- package/dist/tests/registry-index-v2.test.js +0 -430
- package/dist/tests/registry-install.test.js +0 -728
- package/dist/tests/registry-providers/parity.test.js +0 -189
- package/dist/tests/registry-providers/skills-sh.test.js +0 -309
- package/dist/tests/registry-providers/static-index.test.js +0 -238
- package/dist/tests/registry-resolve.test.js +0 -126
- package/dist/tests/registry-search.test.js +0 -923
- package/dist/tests/remember-frontmatter.test.js +0 -378
- package/dist/tests/remember-unit.test.js +0 -123
- package/dist/tests/ripgrep-install.test.js +0 -251
- package/dist/tests/ripgrep-resolve.test.js +0 -108
- package/dist/tests/ripgrep.test.js +0 -163
- package/dist/tests/save-command.test.js +0 -94
- package/dist/tests/save-trust-qa-fixes.test.js +0 -270
- package/dist/tests/scoring-pipeline.test.js +0 -648
- package/dist/tests/search-include-proposed-cli.test.js +0 -118
- package/dist/tests/self-update.test.js +0 -442
- package/dist/tests/semantic-search-e2e.test.js +0 -512
- package/dist/tests/semantic-status.test.js +0 -471
- package/dist/tests/setup-run.integration.js +0 -877
- package/dist/tests/setup-wizard.test.js +0 -198
- package/dist/tests/setup.test.js +0 -131
- package/dist/tests/source-add.test.js +0 -11
- package/dist/tests/source-clone.test.js +0 -254
- package/dist/tests/source-manage.test.js +0 -366
- package/dist/tests/source-providers/filesystem.test.js +0 -82
- package/dist/tests/source-providers/git.test.js +0 -252
- package/dist/tests/source-providers/website.test.js +0 -128
- package/dist/tests/source-qa-fixes.test.js +0 -286
- package/dist/tests/source-registry.test.js +0 -350
- package/dist/tests/source-resolve.test.js +0 -100
- package/dist/tests/source-source.test.js +0 -281
- package/dist/tests/source.test.js +0 -533
- package/dist/tests/tar-utils-scan.test.js +0 -73
- package/dist/tests/toggle-components.test.js +0 -73
- package/dist/tests/usage-telemetry.test.js +0 -265
- package/dist/tests/utility-scoring.test.js +0 -558
- package/dist/tests/vault-load-error.test.js +0 -78
- package/dist/tests/vault-qa-fixes.test.js +0 -194
- package/dist/tests/vault.test.js +0 -429
- package/dist/tests/vector-search.test.js +0 -608
- package/dist/tests/walker.test.js +0 -252
- package/dist/tests/wave2-cluster-bc.test.js +0 -228
- package/dist/tests/wave2-cluster-d.test.js +0 -180
- package/dist/tests/wave2-cluster-e.test.js +0 -179
- package/dist/tests/wiki-qa-fixes.test.js +0 -270
- package/dist/tests/wiki.test.js +0 -529
- package/dist/tests/workflow-cli.test.js +0 -271
- package/dist/tests/workflow-markdown.test.js +0 -171
- package/dist/tests/workflow-path-escape.test.js +0 -132
- package/dist/tests/workflow-qa-fixes.test.js +0 -395
- package/dist/tests/workflows/indexer-rejection.test.js +0 -213
- /package/dist/{src/cli.js → cli.js} +0 -0
- /package/dist/{src/commands → commands}/completions.js +0 -0
- /package/dist/{src/commands → commands}/config-cli.js +0 -0
- /package/dist/{src/commands → commands}/curate.js +0 -0
- /package/dist/{src/commands → commands}/distill.js +0 -0
- /package/dist/{src/commands → commands}/events.js +0 -0
- /package/dist/{src/commands → commands}/history.js +0 -0
- /package/dist/{src/commands → commands}/info.js +0 -0
- /package/dist/{src/commands → commands}/init.js +0 -0
- /package/dist/{src/commands → commands}/install-audit.js +0 -0
- /package/dist/{src/commands → commands}/installed-stashes.js +0 -0
- /package/dist/{src/commands → commands}/migration-help.js +0 -0
- /package/dist/{src/commands → commands}/proposal.js +0 -0
- /package/dist/{src/commands → commands}/propose.js +0 -0
- /package/dist/{src/commands → commands}/reflect.js +0 -0
- /package/dist/{src/commands → commands}/registry-search.js +0 -0
- /package/dist/{src/commands → commands}/remember.js +0 -0
- /package/dist/{src/commands → commands}/search.js +0 -0
- /package/dist/{src/commands → commands}/self-update.js +0 -0
- /package/dist/{src/commands → commands}/show.js +0 -0
- /package/dist/{src/commands → commands}/source-add.js +0 -0
- /package/dist/{src/commands → commands}/source-clone.js +0 -0
- /package/dist/{src/commands → commands}/source-manage.js +0 -0
- /package/dist/{src/commands → commands}/vault.js +0 -0
- /package/dist/{src/core → core}/asset-ref.js +0 -0
- /package/dist/{src/core → core}/asset-registry.js +0 -0
- /package/dist/{src/core → core}/asset-spec.js +0 -0
- /package/dist/{src/core → core}/common.js +0 -0
- /package/dist/{src/core → core}/config.js +0 -0
- /package/dist/{src/core → core}/errors.js +0 -0
- /package/dist/{src/core → core}/events.js +0 -0
- /package/dist/{src/core → core}/frontmatter.js +0 -0
- /package/dist/{src/core → core}/lesson-lint.js +0 -0
- /package/dist/{src/core → core}/markdown.js +0 -0
- /package/dist/{src/core → core}/paths.js +0 -0
- /package/dist/{src/core → core}/proposals.js +0 -0
- /package/dist/{src/core → core}/warn.js +0 -0
- /package/dist/{src/core → core}/write-source.js +0 -0
- /package/dist/{src/indexer → indexer}/db-search.js +0 -0
- /package/dist/{src/indexer → indexer}/db.js +0 -0
- /package/dist/{src/indexer → indexer}/file-context.js +0 -0
- /package/dist/{src/indexer → indexer}/graph-boost.js +0 -0
- /package/dist/{src/indexer → indexer}/graph-extraction.js +0 -0
- /package/dist/{src/indexer → indexer}/indexer.js +0 -0
- /package/dist/{src/indexer → indexer}/manifest.js +0 -0
- /package/dist/{src/indexer → indexer}/matchers.js +0 -0
- /package/dist/{src/indexer → indexer}/memory-inference.js +0 -0
- /package/dist/{src/indexer → indexer}/metadata.js +0 -0
- /package/dist/{src/indexer → indexer}/search-fields.js +0 -0
- /package/dist/{src/indexer → indexer}/search-source.js +0 -0
- /package/dist/{src/indexer → indexer}/semantic-status.js +0 -0
- /package/dist/{src/indexer → indexer}/usage-events.js +0 -0
- /package/dist/{src/indexer → indexer}/walker.js +0 -0
- /package/dist/{src/integrations → integrations}/agent/config.js +0 -0
- /package/dist/{src/integrations → integrations}/agent/detect.js +0 -0
- /package/dist/{src/integrations → integrations}/agent/index.js +0 -0
- /package/dist/{src/integrations → integrations}/agent/profiles.js +0 -0
- /package/dist/{src/integrations → integrations}/agent/prompts.js +0 -0
- /package/dist/{src/integrations → integrations}/agent/spawn.js +0 -0
- /package/dist/{src/integrations → integrations}/github.js +0 -0
- /package/dist/{src/integrations → integrations}/lockfile.js +0 -0
- /package/dist/{src/llm → llm}/client.js +0 -0
- /package/dist/{src/llm → llm}/embedder.js +0 -0
- /package/dist/{src/llm → llm}/embedders/cache.js +0 -0
- /package/dist/{src/llm → llm}/embedders/local.js +0 -0
- /package/dist/{src/llm → llm}/embedders/remote.js +0 -0
- /package/dist/{src/llm → llm}/embedders/types.js +0 -0
- /package/dist/{src/llm → llm}/feature-gate.js +0 -0
- /package/dist/{src/llm → llm}/graph-extract.js +0 -0
- /package/dist/{src/llm → llm}/index-passes.js +0 -0
- /package/dist/{src/llm → llm}/memory-infer.js +0 -0
- /package/dist/{src/llm → llm}/metadata-enhance.js +0 -0
- /package/dist/{src/output → output}/cli-hints.js +0 -0
- /package/dist/{src/output → output}/context.js +0 -0
- /package/dist/{src/output → output}/renderers.js +0 -0
- /package/dist/{src/output → output}/shapes.js +0 -0
- /package/dist/{src/output → output}/text.js +0 -0
- /package/dist/{src/registry → registry}/build-index.js +0 -0
- /package/dist/{src/registry → registry}/create-provider-registry.js +0 -0
- /package/dist/{src/registry → registry}/factory.js +0 -0
- /package/dist/{src/registry → registry}/origin-resolve.js +0 -0
- /package/dist/{src/registry → registry}/providers/index.js +0 -0
- /package/dist/{src/registry → registry}/providers/skills-sh.js +0 -0
- /package/dist/{src/registry → registry}/providers/static-index.js +0 -0
- /package/dist/{src/registry → registry}/providers/types.js +0 -0
- /package/dist/{src/registry → registry}/resolve.js +0 -0
- /package/dist/{src/registry → registry}/types.js +0 -0
- /package/dist/{src/setup → setup}/detect.js +0 -0
- /package/dist/{src/setup → setup}/ripgrep-install.js +0 -0
- /package/dist/{src/setup → setup}/ripgrep-resolve.js +0 -0
- /package/dist/{src/setup → setup}/setup.js +0 -0
- /package/dist/{src/setup → setup}/steps.js +0 -0
- /package/dist/{src/sources → sources}/include.js +0 -0
- /package/dist/{src/sources → sources}/provider-factory.js +0 -0
- /package/dist/{src/sources → sources}/provider.js +0 -0
- /package/dist/{src/sources → sources}/providers/filesystem.js +0 -0
- /package/dist/{src/sources → sources}/providers/git.js +0 -0
- /package/dist/{src/sources → sources}/providers/index.js +0 -0
- /package/dist/{src/sources → sources}/providers/install-types.js +0 -0
- /package/dist/{src/sources → sources}/providers/npm.js +0 -0
- /package/dist/{src/sources → sources}/providers/provider-utils.js +0 -0
- /package/dist/{src/sources → sources}/providers/sync-from-ref.js +0 -0
- /package/dist/{src/sources → sources}/providers/tar-utils.js +0 -0
- /package/dist/{src/sources → sources}/providers/website.js +0 -0
- /package/dist/{src/sources → sources}/resolve.js +0 -0
- /package/dist/{src/sources → sources}/types.js +0 -0
- /package/dist/{src/templates → templates}/wiki-templates.js +0 -0
- /package/dist/{src/version.js → version.js} +0 -0
- /package/dist/{src/wiki → wiki}/wiki.js +0 -0
- /package/dist/{src/workflows → workflows}/authoring.js +0 -0
- /package/dist/{src/workflows → workflows}/cli.js +0 -0
- /package/dist/{src/workflows → workflows}/db.js +0 -0
- /package/dist/{src/workflows → workflows}/document-cache.js +0 -0
- /package/dist/{src/workflows → workflows}/parser.js +0 -0
- /package/dist/{src/workflows → workflows}/renderer.js +0 -0
- /package/dist/{src/workflows → workflows}/runs.js +0 -0
- /package/dist/{src/workflows → workflows}/schema.js +0 -0
- /package/dist/{src/workflows → workflows}/validator.js +0 -0
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import { afterAll, afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
2
|
-
import fs from "node:fs";
|
|
3
|
-
import os from "node:os";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { assembleInfo } from "../src/commands/info";
|
|
6
|
-
import { loadConfig, saveConfig } from "../src/core/config";
|
|
7
|
-
import { closeDatabase, openDatabase, rebuildFts, setMeta, upsertEntry } from "../src/indexer/db";
|
|
8
|
-
// ── Temp directory management ───────────────────────────────────────────────
|
|
9
|
-
const createdTmpDirs = [];
|
|
10
|
-
function tmpDir(label = "info") {
|
|
11
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), `akm-${label}-`));
|
|
12
|
-
createdTmpDirs.push(dir);
|
|
13
|
-
return dir;
|
|
14
|
-
}
|
|
15
|
-
afterAll(() => {
|
|
16
|
-
for (const dir of createdTmpDirs) {
|
|
17
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
// ── Environment isolation ───────────────────────────────────────────────────
|
|
21
|
-
const savedEnv = {};
|
|
22
|
-
beforeEach(() => {
|
|
23
|
-
savedEnv.XDG_CACHE_HOME = process.env.XDG_CACHE_HOME;
|
|
24
|
-
savedEnv.XDG_CONFIG_HOME = process.env.XDG_CONFIG_HOME;
|
|
25
|
-
savedEnv.AKM_STASH_DIR = process.env.AKM_STASH_DIR;
|
|
26
|
-
process.env.XDG_CACHE_HOME = tmpDir("cache");
|
|
27
|
-
process.env.XDG_CONFIG_HOME = tmpDir("config");
|
|
28
|
-
});
|
|
29
|
-
afterEach(() => {
|
|
30
|
-
for (const [key, val] of Object.entries(savedEnv)) {
|
|
31
|
-
if (val === undefined) {
|
|
32
|
-
delete process.env[key];
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
process.env[key] = val;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
// ── Helpers ─────────────────────────────────────────────────────────────────
|
|
40
|
-
function makeStashDir() {
|
|
41
|
-
const dir = tmpDir("stash");
|
|
42
|
-
// Create minimal stash structure
|
|
43
|
-
fs.mkdirSync(path.join(dir, "skills"), { recursive: true });
|
|
44
|
-
return dir;
|
|
45
|
-
}
|
|
46
|
-
function makeEntry(type, name) {
|
|
47
|
-
return {
|
|
48
|
-
type,
|
|
49
|
-
name,
|
|
50
|
-
description: `A test ${type}`,
|
|
51
|
-
tags: ["test"],
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
// ── Tests ───────────────────────────────────────────────────────────────────
|
|
55
|
-
describe("assembleInfo", () => {
|
|
56
|
-
test("returns a version string", () => {
|
|
57
|
-
const stashDir = makeStashDir();
|
|
58
|
-
process.env.AKM_STASH_DIR = stashDir;
|
|
59
|
-
const info = assembleInfo();
|
|
60
|
-
expect(typeof info.version).toBe("string");
|
|
61
|
-
expect(info.version.length).toBeGreaterThan(0);
|
|
62
|
-
});
|
|
63
|
-
test("returns assetTypes array with built-in types", () => {
|
|
64
|
-
const stashDir = makeStashDir();
|
|
65
|
-
process.env.AKM_STASH_DIR = stashDir;
|
|
66
|
-
const info = assembleInfo();
|
|
67
|
-
expect(Array.isArray(info.assetTypes)).toBe(true);
|
|
68
|
-
expect(info.assetTypes).toContain("skill");
|
|
69
|
-
expect(info.assetTypes).toContain("command");
|
|
70
|
-
expect(info.assetTypes).toContain("agent");
|
|
71
|
-
expect(info.assetTypes).toContain("knowledge");
|
|
72
|
-
expect(info.assetTypes).toContain("script");
|
|
73
|
-
expect(info.assetTypes).toContain("memory");
|
|
74
|
-
});
|
|
75
|
-
test("returns searchModes array", () => {
|
|
76
|
-
const stashDir = makeStashDir();
|
|
77
|
-
process.env.AKM_STASH_DIR = stashDir;
|
|
78
|
-
const info = assembleInfo();
|
|
79
|
-
expect(Array.isArray(info.searchModes)).toBe(true);
|
|
80
|
-
// fts is always available
|
|
81
|
-
expect(info.searchModes).toContain("fts");
|
|
82
|
-
});
|
|
83
|
-
test("works without an index (entryCount: 0)", () => {
|
|
84
|
-
const stashDir = makeStashDir();
|
|
85
|
-
process.env.AKM_STASH_DIR = stashDir;
|
|
86
|
-
const info = assembleInfo();
|
|
87
|
-
expect(info.indexStats.entryCount).toBe(0);
|
|
88
|
-
expect(info.indexStats.hasEmbeddings).toBe(false);
|
|
89
|
-
});
|
|
90
|
-
test("returns registries from config", () => {
|
|
91
|
-
const stashDir = makeStashDir();
|
|
92
|
-
process.env.AKM_STASH_DIR = stashDir;
|
|
93
|
-
const info = assembleInfo();
|
|
94
|
-
expect(Array.isArray(info.registries)).toBe(true);
|
|
95
|
-
// Default config has registries
|
|
96
|
-
const config = loadConfig();
|
|
97
|
-
const expected = config.registries ?? [];
|
|
98
|
-
expect(info.registries.length).toBe(expected.length);
|
|
99
|
-
});
|
|
100
|
-
test("includes indexStats when index exists with entries", () => {
|
|
101
|
-
const stashDir = makeStashDir();
|
|
102
|
-
process.env.AKM_STASH_DIR = stashDir;
|
|
103
|
-
// Create an index with some entries
|
|
104
|
-
const dbPath = path.join(tmpDir("db"), "test.db");
|
|
105
|
-
const db = openDatabase(dbPath);
|
|
106
|
-
const entry = makeEntry("skill", "test-skill");
|
|
107
|
-
upsertEntry(db, "skill:test-skill", "/fake/skill", "/fake/skill/test-skill", stashDir, entry, "test skill");
|
|
108
|
-
rebuildFts(db);
|
|
109
|
-
setMeta(db, "builtAt", "2026-03-17T00:00:00Z");
|
|
110
|
-
closeDatabase(db);
|
|
111
|
-
const info = assembleInfo({ dbPath });
|
|
112
|
-
expect(info.indexStats.entryCount).toBe(1);
|
|
113
|
-
expect(info.indexStats.lastBuiltAt).toBe("2026-03-17T00:00:00Z");
|
|
114
|
-
expect(typeof info.indexStats.vecAvailable).toBe("boolean");
|
|
115
|
-
});
|
|
116
|
-
test("returns sourceProviders from config", () => {
|
|
117
|
-
const stashDir = makeStashDir();
|
|
118
|
-
process.env.AKM_STASH_DIR = stashDir;
|
|
119
|
-
const info = assembleInfo();
|
|
120
|
-
expect(Array.isArray(info.sourceProviders)).toBe(true);
|
|
121
|
-
});
|
|
122
|
-
test("output is valid JSON-serializable", () => {
|
|
123
|
-
const stashDir = makeStashDir();
|
|
124
|
-
process.env.AKM_STASH_DIR = stashDir;
|
|
125
|
-
const info = assembleInfo();
|
|
126
|
-
const json = JSON.stringify(info);
|
|
127
|
-
const parsed = JSON.parse(json);
|
|
128
|
-
expect(parsed.version).toBe(info.version);
|
|
129
|
-
expect(parsed.assetTypes).toEqual(info.assetTypes);
|
|
130
|
-
expect(parsed.searchModes).toEqual(info.searchModes);
|
|
131
|
-
expect(parsed.indexStats).toEqual(info.indexStats);
|
|
132
|
-
});
|
|
133
|
-
test("reports pending semantic search status by default", () => {
|
|
134
|
-
const stashDir = makeStashDir();
|
|
135
|
-
process.env.AKM_STASH_DIR = stashDir;
|
|
136
|
-
const info = assembleInfo();
|
|
137
|
-
expect(info.searchModes).toContain("fts");
|
|
138
|
-
expect(info.searchModes).not.toContain("semantic");
|
|
139
|
-
expect(info.searchModes).not.toContain("hybrid");
|
|
140
|
-
expect(info.semanticSearch.mode).toBe("auto");
|
|
141
|
-
expect(info.semanticSearch.status).toBe("pending");
|
|
142
|
-
});
|
|
143
|
-
test("does not leak apiKey from registry options", () => {
|
|
144
|
-
const stashDir = makeStashDir();
|
|
145
|
-
process.env.AKM_STASH_DIR = stashDir;
|
|
146
|
-
// Write a config with a registry that has an apiKey in its options
|
|
147
|
-
const config = loadConfig();
|
|
148
|
-
config.registries = [
|
|
149
|
-
{
|
|
150
|
-
url: "https://example.com/registry",
|
|
151
|
-
name: "test-registry",
|
|
152
|
-
provider: "static-index",
|
|
153
|
-
options: { apiKey: "super-secret-key-12345" },
|
|
154
|
-
},
|
|
155
|
-
];
|
|
156
|
-
saveConfig(config);
|
|
157
|
-
const info = assembleInfo();
|
|
158
|
-
expect(info.registries).toHaveLength(1);
|
|
159
|
-
expect(info.registries[0].url).toBe("https://example.com/registry");
|
|
160
|
-
expect(info.registries[0].name).toBe("test-registry");
|
|
161
|
-
// Ensure apiKey is not present anywhere in the serialized output
|
|
162
|
-
const serialized = JSON.stringify(info);
|
|
163
|
-
expect(serialized).not.toContain("super-secret-key-12345");
|
|
164
|
-
expect(serialized).not.toContain("apiKey");
|
|
165
|
-
});
|
|
166
|
-
});
|
package/dist/tests/init.test.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for `akm init` (#284 GAP-HIGH 12).
|
|
3
|
-
*
|
|
4
|
-
* Verifies that `akmInit` materialises every registered asset-type directory
|
|
5
|
-
* on disk, including the `lessons/` directory required by the proposal queue.
|
|
6
|
-
* Adds a simple regression guard so a future TYPE_DIRS rename doesn't quietly
|
|
7
|
-
* drop the lessons folder from the bootstrap.
|
|
8
|
-
*/
|
|
9
|
-
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
10
|
-
import fs from "node:fs";
|
|
11
|
-
import os from "node:os";
|
|
12
|
-
import path from "node:path";
|
|
13
|
-
import { akmInit } from "../src/commands/init";
|
|
14
|
-
const tempDirs = [];
|
|
15
|
-
const savedEnv = {
|
|
16
|
-
XDG_CACHE_HOME: process.env.XDG_CACHE_HOME,
|
|
17
|
-
XDG_CONFIG_HOME: process.env.XDG_CONFIG_HOME,
|
|
18
|
-
HOME: process.env.HOME,
|
|
19
|
-
};
|
|
20
|
-
function makeTempDir(prefix) {
|
|
21
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
|
|
22
|
-
tempDirs.push(dir);
|
|
23
|
-
return dir;
|
|
24
|
-
}
|
|
25
|
-
beforeEach(() => {
|
|
26
|
-
process.env.XDG_CACHE_HOME = makeTempDir("akm-init-cache-");
|
|
27
|
-
process.env.XDG_CONFIG_HOME = makeTempDir("akm-init-config-");
|
|
28
|
-
process.env.HOME = makeTempDir("akm-init-home-");
|
|
29
|
-
});
|
|
30
|
-
afterEach(() => {
|
|
31
|
-
if (savedEnv.XDG_CACHE_HOME === undefined)
|
|
32
|
-
delete process.env.XDG_CACHE_HOME;
|
|
33
|
-
else
|
|
34
|
-
process.env.XDG_CACHE_HOME = savedEnv.XDG_CACHE_HOME;
|
|
35
|
-
if (savedEnv.XDG_CONFIG_HOME === undefined)
|
|
36
|
-
delete process.env.XDG_CONFIG_HOME;
|
|
37
|
-
else
|
|
38
|
-
process.env.XDG_CONFIG_HOME = savedEnv.XDG_CONFIG_HOME;
|
|
39
|
-
if (savedEnv.HOME === undefined)
|
|
40
|
-
delete process.env.HOME;
|
|
41
|
-
else
|
|
42
|
-
process.env.HOME = savedEnv.HOME;
|
|
43
|
-
for (const dir of tempDirs.splice(0)) {
|
|
44
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
describe("akm init", () => {
|
|
48
|
-
test("creates the lessons/ directory on disk under the stash root", async () => {
|
|
49
|
-
const stashDir = makeTempDir("akm-init-stash-");
|
|
50
|
-
// Remove dir so init reports created=true
|
|
51
|
-
fs.rmSync(stashDir, { recursive: true, force: true });
|
|
52
|
-
const result = await akmInit({ dir: stashDir });
|
|
53
|
-
expect(result.stashDir).toBe(stashDir);
|
|
54
|
-
expect(result.created).toBe(true);
|
|
55
|
-
expect(fs.existsSync(path.join(stashDir, "lessons"))).toBe(true);
|
|
56
|
-
// Also verify other core type dirs exist (fingerprint of TYPE_DIRS sweep).
|
|
57
|
-
expect(fs.existsSync(path.join(stashDir, "skills"))).toBe(true);
|
|
58
|
-
expect(fs.existsSync(path.join(stashDir, "memories"))).toBe(true);
|
|
59
|
-
});
|
|
60
|
-
test("re-running on an existing stash is idempotent and keeps lessons/", async () => {
|
|
61
|
-
const stashDir = makeTempDir("akm-init-stash-2-");
|
|
62
|
-
await akmInit({ dir: stashDir });
|
|
63
|
-
// Drop the lessons dir to confirm a re-run rebuilds it.
|
|
64
|
-
fs.rmSync(path.join(stashDir, "lessons"), { recursive: true, force: true });
|
|
65
|
-
expect(fs.existsSync(path.join(stashDir, "lessons"))).toBe(false);
|
|
66
|
-
await akmInit({ dir: stashDir });
|
|
67
|
-
expect(fs.existsSync(path.join(stashDir, "lessons"))).toBe(true);
|
|
68
|
-
});
|
|
69
|
-
});
|
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, test } from "bun:test";
|
|
2
|
-
import { spawnSync } from "node:child_process";
|
|
3
|
-
import { createHash } from "node:crypto";
|
|
4
|
-
import fs from "node:fs";
|
|
5
|
-
import os from "node:os";
|
|
6
|
-
import path from "node:path";
|
|
7
|
-
const PROJECT_ROOT = path.resolve(import.meta.dirname, "..");
|
|
8
|
-
const INSTALL_SCRIPT = path.join(PROJECT_ROOT, "install.sh");
|
|
9
|
-
const BASH_PATH = resolveCommand("bash");
|
|
10
|
-
const CHMOD_PATH = resolveCommand("chmod");
|
|
11
|
-
const tempRoots = [];
|
|
12
|
-
function resolveCommand(name) {
|
|
13
|
-
const result = spawnSync("bash", ["-lc", `command -v ${name}`], { encoding: "utf8" });
|
|
14
|
-
if (result.status !== 0) {
|
|
15
|
-
throw new Error(`Unable to resolve command: ${name}`);
|
|
16
|
-
}
|
|
17
|
-
return result.stdout.trim();
|
|
18
|
-
}
|
|
19
|
-
function writeExecutable(filePath, content) {
|
|
20
|
-
fs.writeFileSync(filePath, content, { mode: 0o755 });
|
|
21
|
-
}
|
|
22
|
-
function addProxy(fakeBin, name) {
|
|
23
|
-
const real = resolveCommand(name);
|
|
24
|
-
writeExecutable(`${fakeBin}/${name}`, `#!${BASH_PATH}\nexec ${real} "$@"\n`);
|
|
25
|
-
}
|
|
26
|
-
function createHarness(options = {}) {
|
|
27
|
-
const root = fs.mkdtempSync(path.join(os.tmpdir(), "akm-install-test-"));
|
|
28
|
-
tempRoots.push(root);
|
|
29
|
-
const fakeBin = path.join(root, "fakebin");
|
|
30
|
-
const installDir = path.join(root, options.installDirName ?? "install-dir");
|
|
31
|
-
const logFile = path.join(root, "requests.log");
|
|
32
|
-
fs.mkdirSync(fakeBin, { recursive: true });
|
|
33
|
-
fs.mkdirSync(installDir, { recursive: true });
|
|
34
|
-
addProxy(fakeBin, "mktemp");
|
|
35
|
-
addProxy(fakeBin, "awk");
|
|
36
|
-
addProxy(fakeBin, "chmod");
|
|
37
|
-
addProxy(fakeBin, "mv");
|
|
38
|
-
addProxy(fakeBin, "rm");
|
|
39
|
-
const checksumTool = options.checksumTool ?? "sha256sum";
|
|
40
|
-
if (checksumTool === "sha256sum") {
|
|
41
|
-
addProxy(fakeBin, "sha256sum");
|
|
42
|
-
}
|
|
43
|
-
if (checksumTool === "shasum") {
|
|
44
|
-
addProxy(fakeBin, "shasum");
|
|
45
|
-
}
|
|
46
|
-
const osName = options.osName ?? "Linux";
|
|
47
|
-
const archName = options.archName ?? "x86_64";
|
|
48
|
-
writeExecutable(path.join(fakeBin, "uname"), `#!${BASH_PATH}
|
|
49
|
-
if [ "\${1:-}" = "-s" ]; then
|
|
50
|
-
printf '%s\n' '${osName}'
|
|
51
|
-
elif [ "\${1:-}" = "-m" ]; then
|
|
52
|
-
printf '%s\n' '${archName}'
|
|
53
|
-
else
|
|
54
|
-
printf '%s\n' '${osName}'
|
|
55
|
-
fi
|
|
56
|
-
`);
|
|
57
|
-
const downloader = options.downloader ?? "curl";
|
|
58
|
-
const binaryName = `akm-${osName === "Darwin" ? "darwin" : osName === "Linux" ? "linux" : "windows"}-${archName === "x86_64" ? "x64" : archName}`;
|
|
59
|
-
const binaryContent = "fake-akm-binary";
|
|
60
|
-
const binaryHash = createHash("sha256").update(binaryContent).digest("hex");
|
|
61
|
-
const checksumMode = options.checksumMode ?? "match";
|
|
62
|
-
const downloadScript = `#!${BASH_PATH}
|
|
63
|
-
set -euo pipefail
|
|
64
|
-
outfile=""
|
|
65
|
-
url=""
|
|
66
|
-
while [ "$#" -gt 0 ]; do
|
|
67
|
-
case "$1" in
|
|
68
|
-
-o)
|
|
69
|
-
outfile="$2"
|
|
70
|
-
shift 2
|
|
71
|
-
;;
|
|
72
|
-
-qO)
|
|
73
|
-
outfile="$2"
|
|
74
|
-
shift 2
|
|
75
|
-
;;
|
|
76
|
-
-fsSL|-q)
|
|
77
|
-
shift
|
|
78
|
-
;;
|
|
79
|
-
*)
|
|
80
|
-
url="$1"
|
|
81
|
-
shift
|
|
82
|
-
;;
|
|
83
|
-
esac
|
|
84
|
-
done
|
|
85
|
-
printf '%s\n' "$url" >> "${logFile}"
|
|
86
|
-
if [[ "$url" == *checksums.txt ]]; then
|
|
87
|
-
case "${checksumMode}" in
|
|
88
|
-
match)
|
|
89
|
-
printf '%s %s\n' '${binaryHash}' '${binaryName}' > "$outfile"
|
|
90
|
-
;;
|
|
91
|
-
mismatch)
|
|
92
|
-
printf '%s %s\n' 'deadbeef' '${binaryName}' > "$outfile"
|
|
93
|
-
;;
|
|
94
|
-
missing)
|
|
95
|
-
printf '%s %s\n' '${binaryHash}' 'other-binary' > "$outfile"
|
|
96
|
-
;;
|
|
97
|
-
esac
|
|
98
|
-
else
|
|
99
|
-
printf '%s' '${binaryContent}' > "$outfile"
|
|
100
|
-
fi
|
|
101
|
-
`;
|
|
102
|
-
if (downloader === "curl") {
|
|
103
|
-
writeExecutable(path.join(fakeBin, "curl"), downloadScript);
|
|
104
|
-
}
|
|
105
|
-
if (downloader === "wget") {
|
|
106
|
-
writeExecutable(path.join(fakeBin, "wget"), downloadScript);
|
|
107
|
-
}
|
|
108
|
-
if (options.useSudo) {
|
|
109
|
-
writeExecutable(path.join(fakeBin, "sudo"), `#!${BASH_PATH}
|
|
110
|
-
set -euo pipefail
|
|
111
|
-
printf 'sudo %s\n' "$*" >> "${logFile}"
|
|
112
|
-
if [ "${options.sudoSucceeds === false ? "0" : "1"}" = "0" ]; then
|
|
113
|
-
exit 127
|
|
114
|
-
fi
|
|
115
|
-
if [ "$1" = "mv" ]; then
|
|
116
|
-
dest="${installDir}"
|
|
117
|
-
${CHMOD_PATH} u+w "$dest"
|
|
118
|
-
fi
|
|
119
|
-
exec "$@"
|
|
120
|
-
`);
|
|
121
|
-
}
|
|
122
|
-
if (downloader === "none") {
|
|
123
|
-
// Intentionally do not create curl/wget so command -v fails.
|
|
124
|
-
}
|
|
125
|
-
if (options.installDirWritable === false) {
|
|
126
|
-
fs.chmodSync(installDir, 0o555);
|
|
127
|
-
}
|
|
128
|
-
return {
|
|
129
|
-
root,
|
|
130
|
-
installDir,
|
|
131
|
-
logFile,
|
|
132
|
-
binaryName,
|
|
133
|
-
run: (args = []) => spawnSync(BASH_PATH, [INSTALL_SCRIPT, ...args], {
|
|
134
|
-
cwd: PROJECT_ROOT,
|
|
135
|
-
encoding: "utf8",
|
|
136
|
-
env: {
|
|
137
|
-
...process.env,
|
|
138
|
-
PATH: downloader === "none" ? buildPathWithoutDownloaders(fakeBin) : fakeBin,
|
|
139
|
-
AKM_INSTALL_DIR: installDir,
|
|
140
|
-
},
|
|
141
|
-
}),
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
function buildPathWithoutDownloaders(fakeBin) {
|
|
145
|
-
const segments = (process.env.PATH ?? "").split(":").filter(Boolean);
|
|
146
|
-
const filtered = segments.filter((segment) => {
|
|
147
|
-
for (const name of ["curl", "wget"]) {
|
|
148
|
-
const candidate = path.join(segment, name);
|
|
149
|
-
if (fs.existsSync(candidate)) {
|
|
150
|
-
return false;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return true;
|
|
154
|
-
});
|
|
155
|
-
return [fakeBin, ...filtered].join(":");
|
|
156
|
-
}
|
|
157
|
-
afterEach(() => {
|
|
158
|
-
while (tempRoots.length > 0) {
|
|
159
|
-
const root = tempRoots.pop();
|
|
160
|
-
if (root) {
|
|
161
|
-
fs.rmSync(root, { recursive: true, force: true });
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
describe("install.sh", () => {
|
|
166
|
-
test("installs the latest linux x64 binary with curl into a custom dir", () => {
|
|
167
|
-
const harness = createHarness();
|
|
168
|
-
const result = harness.run();
|
|
169
|
-
expect(result.status).toBe(0);
|
|
170
|
-
expect(fs.existsSync(path.join(harness.installDir, "akm"))).toBe(true);
|
|
171
|
-
expect(result.stdout).toContain(`akm installed to ${harness.installDir}/akm`);
|
|
172
|
-
const log = fs.readFileSync(harness.logFile, "utf8");
|
|
173
|
-
expect(log).toContain(`/releases/latest/download/${harness.binaryName}`);
|
|
174
|
-
expect(log).toContain("/releases/latest/download/checksums.txt");
|
|
175
|
-
});
|
|
176
|
-
test("uses wget fallback and pinned tags when curl is unavailable", () => {
|
|
177
|
-
const harness = createHarness({ downloader: "wget" });
|
|
178
|
-
const result = harness.run(["v1.2.3"]);
|
|
179
|
-
expect(result.status).toBe(0);
|
|
180
|
-
const log = fs.readFileSync(harness.logFile, "utf8");
|
|
181
|
-
expect(log).toContain(`/releases/download/v1.2.3/${harness.binaryName}`);
|
|
182
|
-
expect(log).toContain("/releases/download/v1.2.3/checksums.txt");
|
|
183
|
-
});
|
|
184
|
-
test("fails clearly when checksum entry is missing", () => {
|
|
185
|
-
const harness = createHarness({ checksumMode: "missing" });
|
|
186
|
-
const result = harness.run();
|
|
187
|
-
expect(result.status).not.toBe(0);
|
|
188
|
-
expect(result.stderr).toContain(`checksum not found for ${harness.binaryName}`);
|
|
189
|
-
});
|
|
190
|
-
test("fails clearly on checksum mismatch", () => {
|
|
191
|
-
const harness = createHarness({ checksumMode: "mismatch" });
|
|
192
|
-
const result = harness.run();
|
|
193
|
-
expect(result.status).not.toBe(0);
|
|
194
|
-
expect(result.stderr).toContain(`checksum verification failed for ${harness.binaryName}`);
|
|
195
|
-
});
|
|
196
|
-
test("fails when no downloader is available", () => {
|
|
197
|
-
const harness = createHarness({ downloader: "none" });
|
|
198
|
-
const result = harness.run();
|
|
199
|
-
expect(result.status).not.toBe(0);
|
|
200
|
-
expect(result.stdout + result.stderr).toContain("curl or wget is required");
|
|
201
|
-
});
|
|
202
|
-
test("uses sudo mv when install dir is not writable", () => {
|
|
203
|
-
const harness = createHarness({ installDirWritable: false, useSudo: true });
|
|
204
|
-
const result = harness.run();
|
|
205
|
-
expect(result.status).toBe(0);
|
|
206
|
-
const log = fs.readFileSync(harness.logFile, "utf8");
|
|
207
|
-
expect(log).toContain("sudo mv");
|
|
208
|
-
expect(fs.existsSync(path.join(harness.installDir, "akm"))).toBe(true);
|
|
209
|
-
});
|
|
210
|
-
test("falls back to shasum when sha256sum is unavailable", () => {
|
|
211
|
-
const harness = createHarness({ checksumTool: "shasum" });
|
|
212
|
-
const result = harness.run();
|
|
213
|
-
expect(result.status).toBe(0);
|
|
214
|
-
expect(fs.existsSync(path.join(harness.installDir, "akm"))).toBe(true);
|
|
215
|
-
});
|
|
216
|
-
test("fails when no checksum tool is available", () => {
|
|
217
|
-
const harness = createHarness({ checksumTool: "none" });
|
|
218
|
-
const result = harness.run();
|
|
219
|
-
expect(result.status).not.toBe(0);
|
|
220
|
-
expect(result.stdout + result.stderr).toContain("sha256sum or shasum is required");
|
|
221
|
-
});
|
|
222
|
-
test("fails clearly on unsupported architecture", () => {
|
|
223
|
-
const harness = createHarness({ archName: "riscv64" });
|
|
224
|
-
const result = harness.run();
|
|
225
|
-
expect(result.status).not.toBe(0);
|
|
226
|
-
expect(result.stderr).toContain("Unsupported architecture");
|
|
227
|
-
});
|
|
228
|
-
test("installs successfully when install dir contains spaces", () => {
|
|
229
|
-
const harness = createHarness({ installDirName: "install dir with spaces" });
|
|
230
|
-
const result = harness.run();
|
|
231
|
-
expect(result.status).toBe(0);
|
|
232
|
-
expect(fs.existsSync(path.join(harness.installDir, "akm"))).toBe(true);
|
|
233
|
-
});
|
|
234
|
-
test("fails clearly when sudo is required but unavailable", () => {
|
|
235
|
-
const harness = createHarness({ installDirWritable: false, useSudo: true, sudoSucceeds: false });
|
|
236
|
-
const result = harness.run();
|
|
237
|
-
expect(result.status).not.toBe(0);
|
|
238
|
-
expect(fs.existsSync(path.join(harness.installDir, "akm"))).toBe(false);
|
|
239
|
-
});
|
|
240
|
-
test("prints the Windows install.ps1 guidance on MINGW", () => {
|
|
241
|
-
const harness = createHarness({ osName: "MINGW64_NT" });
|
|
242
|
-
const result = harness.run();
|
|
243
|
-
expect(result.status).toBe(1);
|
|
244
|
-
expect(result.stderr).toContain("install.ps1");
|
|
245
|
-
});
|
|
246
|
-
});
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Opt-in real-profile integration tests for `akm reflect` and `akm propose` (#226).
|
|
3
|
-
*
|
|
4
|
-
* Skipped by default in CI. Enable by exporting `AKM_REAL_AGENT_TESTS=1`
|
|
5
|
-
* (and a credential for the chosen profile, e.g. `OPENCODE_API_KEY` or
|
|
6
|
-
* `ANTHROPIC_API_KEY`). Each test spawns the actual agent CLI through the
|
|
7
|
-
* documented profile and checks that a proposal lands in the queue.
|
|
8
|
-
*
|
|
9
|
-
* The prompts here are intentionally cheap — single short asset, no long
|
|
10
|
-
* context — to keep cost minimal when developers run them locally.
|
|
11
|
-
*/
|
|
12
|
-
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
13
|
-
import fs from "node:fs";
|
|
14
|
-
import os from "node:os";
|
|
15
|
-
import path from "node:path";
|
|
16
|
-
import { akmPropose } from "../../src/commands/propose";
|
|
17
|
-
import { akmReflect } from "../../src/commands/reflect";
|
|
18
|
-
import { listProposals } from "../../src/core/proposals";
|
|
19
|
-
import { getBuiltinAgentProfile } from "../../src/integrations/agent/profiles";
|
|
20
|
-
const REAL_AGENT_TESTS = process.env.AKM_REAL_AGENT_TESTS === "1" || process.env.AKM_REAL_AGENT_TESTS === "true";
|
|
21
|
-
const tempDirs = [];
|
|
22
|
-
function makeTempDir(prefix) {
|
|
23
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
|
|
24
|
-
tempDirs.push(dir);
|
|
25
|
-
return dir;
|
|
26
|
-
}
|
|
27
|
-
function makeStashDir() {
|
|
28
|
-
const stash = makeTempDir("akm-real-agent-stash-");
|
|
29
|
-
for (const dir of ["lessons", "skills"]) {
|
|
30
|
-
fs.mkdirSync(path.join(stash, dir), { recursive: true });
|
|
31
|
-
}
|
|
32
|
-
return stash;
|
|
33
|
-
}
|
|
34
|
-
describe.skipIf(!REAL_AGENT_TESTS)("real-profile integration (opt-in via AKM_REAL_AGENT_TESTS)", () => {
|
|
35
|
-
let priorXdgCacheHome;
|
|
36
|
-
let priorXdgConfigHome;
|
|
37
|
-
beforeAll(() => {
|
|
38
|
-
priorXdgCacheHome = process.env.XDG_CACHE_HOME;
|
|
39
|
-
priorXdgConfigHome = process.env.XDG_CONFIG_HOME;
|
|
40
|
-
process.env.XDG_CACHE_HOME = makeTempDir("akm-real-agent-cache-");
|
|
41
|
-
process.env.XDG_CONFIG_HOME = makeTempDir("akm-real-agent-config-");
|
|
42
|
-
});
|
|
43
|
-
afterAll(() => {
|
|
44
|
-
if (priorXdgCacheHome === undefined)
|
|
45
|
-
delete process.env.XDG_CACHE_HOME;
|
|
46
|
-
else
|
|
47
|
-
process.env.XDG_CACHE_HOME = priorXdgCacheHome;
|
|
48
|
-
if (priorXdgConfigHome === undefined)
|
|
49
|
-
delete process.env.XDG_CONFIG_HOME;
|
|
50
|
-
else
|
|
51
|
-
process.env.XDG_CONFIG_HOME = priorXdgConfigHome;
|
|
52
|
-
for (const dir of tempDirs.splice(0)) {
|
|
53
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
test("opencode profile produces a queued proposal via akm propose", async () => {
|
|
57
|
-
const profile = getBuiltinAgentProfile("opencode");
|
|
58
|
-
expect(profile).toBeDefined();
|
|
59
|
-
if (!profile)
|
|
60
|
-
return;
|
|
61
|
-
const stash = makeStashDir();
|
|
62
|
-
const result = await akmPropose({
|
|
63
|
-
type: "skill",
|
|
64
|
-
name: "real-profile-hello",
|
|
65
|
-
task: "Author a one-line skill that says hello.",
|
|
66
|
-
stashDir: stash,
|
|
67
|
-
agentProfile: { ...profile, stdio: "captured" },
|
|
68
|
-
timeoutMs: 60_000,
|
|
69
|
-
});
|
|
70
|
-
expect(result.ok).toBe(true);
|
|
71
|
-
if (!result.ok)
|
|
72
|
-
throw new Error(`propose failed: ${result.reason}: ${result.error}`);
|
|
73
|
-
const proposals = listProposals(stash);
|
|
74
|
-
expect(proposals.length).toBeGreaterThanOrEqual(1);
|
|
75
|
-
});
|
|
76
|
-
test("claude profile produces a queued proposal via akm reflect", async () => {
|
|
77
|
-
const profile = getBuiltinAgentProfile("claude");
|
|
78
|
-
expect(profile).toBeDefined();
|
|
79
|
-
if (!profile)
|
|
80
|
-
return;
|
|
81
|
-
const stash = makeStashDir();
|
|
82
|
-
const result = await akmReflect({
|
|
83
|
-
ref: "lesson:real-profile-tip",
|
|
84
|
-
stashDir: stash,
|
|
85
|
-
agentProfile: { ...profile, stdio: "captured" },
|
|
86
|
-
timeoutMs: 60_000,
|
|
87
|
-
});
|
|
88
|
-
expect(result.ok).toBe(true);
|
|
89
|
-
if (!result.ok)
|
|
90
|
-
throw new Error(`reflect failed: ${result.reason}: ${result.error}`);
|
|
91
|
-
const proposals = listProposals(stash);
|
|
92
|
-
expect(proposals.length).toBeGreaterThanOrEqual(1);
|
|
93
|
-
});
|
|
94
|
-
});
|