akm-cli 0.9.0-beta.6 → 0.9.0-rc.0
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 +663 -0
- package/README.md +12 -4
- package/dist/akm +38 -0
- package/dist/akm-migrate-storage +38 -0
- package/dist/assets/help/help-improve.md +9 -6
- package/dist/assets/hints/cli-hints-full.md +6 -5
- package/dist/assets/profiles/default.json +9 -4
- package/dist/assets/profiles/frequent.json +1 -1
- package/dist/assets/profiles/memory-focus.json +1 -1
- package/dist/assets/profiles/proactive-maintenance.json +25 -0
- package/dist/assets/profiles/quick.json +1 -1
- package/dist/assets/profiles/recombine-only.json +21 -0
- package/dist/assets/profiles/reflect-distill.json +30 -0
- package/dist/assets/profiles/synthesize.json +15 -0
- package/dist/assets/profiles/thorough.json +1 -1
- package/dist/assets/prompts/consolidate-system.md +23 -0
- package/dist/assets/prompts/contradiction-judge.md +33 -0
- package/dist/assets/prompts/distill-knowledge-system.md +22 -0
- package/dist/assets/prompts/distill-lesson-system.md +36 -0
- package/dist/assets/prompts/extract-session.md +11 -3
- package/dist/assets/prompts/graph-extract-system.md +1 -0
- package/dist/assets/prompts/graph-extract-user-prompt.md +1 -1
- package/dist/assets/prompts/memory-infer-system.md +1 -0
- package/dist/assets/prompts/memory-infer-user.md +5 -0
- package/dist/assets/prompts/metadata-enhance-system.md +1 -0
- package/dist/assets/prompts/procedural-system.md +44 -0
- package/dist/assets/prompts/recombine-system.md +40 -0
- package/dist/assets/prompts/staleness-detect-system.md +6 -0
- package/dist/assets/prompts/validate-summary-judge.md +1 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +38 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +38 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +39 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +40 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +43 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +38 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +43 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +40 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +43 -0
- package/dist/assets/templates/html/health.html +281 -111
- package/dist/assets/wiki/ingest-workflow-template.md +45 -16
- package/dist/assets/wiki/schema-template.md +4 -4
- package/dist/cli/clack.js +56 -0
- package/dist/cli/config-migrate.js +7 -1
- package/dist/cli/confirm.js +1 -1
- package/dist/cli/parse-args.js +46 -1
- package/dist/cli/shared.js +28 -0
- package/dist/cli.js +25 -14
- package/dist/commands/agent/agent-dispatch.js +3 -2
- package/dist/commands/agent/agent-support.js +0 -7
- package/dist/commands/agent/contribute-cli.js +26 -7
- package/dist/commands/config-cli.js +26 -13
- package/dist/commands/env/child-env.js +47 -0
- package/dist/commands/env/env-cli.js +220 -227
- package/dist/commands/env/env.js +14 -67
- package/dist/commands/env/secret-cli.js +140 -138
- package/dist/commands/feedback-cli.js +153 -147
- package/dist/commands/graph/graph-cli.js +5 -13
- package/dist/commands/graph/graph.js +76 -72
- package/dist/commands/health/advisories.js +151 -0
- package/dist/commands/health/checks.js +103 -16
- package/dist/commands/health/html-report.js +447 -81
- package/dist/commands/health/improve-metrics.js +771 -0
- package/dist/commands/health/llm-usage.js +65 -0
- package/dist/commands/health/md-report.js +103 -0
- package/dist/commands/health/metrics.js +278 -0
- package/dist/commands/health/stash-exposure.js +46 -0
- package/dist/commands/health/surfaces.js +216 -0
- package/dist/commands/health/task-runs.js +135 -0
- package/dist/commands/health/types.js +26 -0
- package/dist/commands/health/windows.js +195 -0
- package/dist/commands/health.js +91 -1083
- package/dist/commands/improve/anti-collapse.js +170 -0
- package/dist/commands/improve/calibration.js +161 -0
- package/dist/commands/improve/collapse-detector.js +421 -0
- package/dist/commands/improve/consolidate/chunking.js +141 -0
- package/dist/commands/improve/consolidate/eligibility.js +64 -0
- package/dist/commands/improve/consolidate/merge.js +145 -0
- package/dist/commands/improve/consolidate/sanitize.js +231 -0
- package/dist/commands/{lint.js → improve/consolidate/types.js} +1 -1
- package/dist/commands/improve/consolidate.js +1313 -1278
- package/dist/commands/improve/dedup.js +482 -0
- package/dist/commands/improve/distill/content-repair.js +202 -0
- package/dist/commands/improve/distill/promote-memory.js +229 -0
- package/dist/commands/improve/distill/quality-gate.js +236 -0
- package/dist/commands/improve/distill-guards.js +127 -0
- package/dist/commands/improve/distill-promotion-policy.js +826 -167
- package/dist/commands/improve/distill.js +243 -599
- package/dist/commands/improve/eligibility.js +434 -0
- package/dist/commands/improve/encoding-salience.js +205 -0
- package/dist/commands/improve/extract-cli.js +179 -59
- package/dist/commands/improve/extract-prompt.js +55 -4
- package/dist/commands/improve/extract-watch.js +140 -0
- package/dist/commands/improve/extract.js +409 -43
- package/dist/commands/improve/feedback-valence.js +54 -0
- package/dist/commands/improve/hot-probation.js +45 -0
- package/dist/commands/improve/improve-auto-accept.js +160 -7
- package/dist/commands/improve/improve-cli.js +115 -73
- package/dist/commands/improve/improve-profiles.js +32 -8
- package/dist/commands/improve/improve-result-file.js +15 -25
- package/dist/commands/improve/improve-session.js +58 -0
- package/dist/commands/improve/improve.js +510 -2537
- package/dist/commands/improve/locks.js +154 -0
- package/dist/commands/improve/loop-stages.js +1100 -0
- package/dist/commands/improve/memory/memory-belief.js +14 -15
- package/dist/commands/improve/memory/memory-contradiction-detect.js +83 -60
- package/dist/commands/improve/memory/memory-improve.js +27 -27
- package/dist/commands/improve/outcome-loop.js +270 -0
- package/dist/commands/improve/preparation.js +2002 -0
- package/dist/commands/improve/proactive-maintenance.js +115 -0
- package/dist/commands/improve/procedural.js +398 -0
- package/dist/commands/improve/recombine.js +818 -0
- package/dist/commands/improve/reflect-noise.js +0 -0
- package/dist/commands/improve/reflect.js +212 -45
- package/dist/commands/improve/salience.js +455 -0
- package/dist/commands/improve/schema-similarity-gate.js +168 -0
- package/dist/commands/improve/shared.js +51 -0
- package/dist/commands/improve/triage.js +93 -0
- package/dist/commands/lint/agent-linter.js +19 -24
- package/dist/commands/lint/base-linter.js +173 -60
- package/dist/commands/lint/command-linter.js +19 -24
- package/dist/commands/lint/env-key-rules.js +38 -1
- package/dist/commands/lint/fact-linter.js +39 -0
- package/dist/commands/lint/index.js +31 -13
- package/dist/commands/lint/memory-linter.js +1 -1
- package/dist/commands/lint/registry.js +7 -2
- package/dist/commands/lint/task-linter.js +3 -3
- package/dist/commands/lint/workflow-linter.js +26 -1
- package/dist/commands/observability-cli.js +4 -4
- package/dist/commands/proposal/drain-policies.js +13 -4
- package/dist/commands/proposal/drain.js +45 -51
- package/dist/commands/proposal/legacy-import.js +115 -0
- package/dist/commands/proposal/proposal-cli.js +24 -34
- package/dist/commands/proposal/proposal.js +7 -1
- package/dist/commands/proposal/propose.js +8 -3
- package/dist/commands/proposal/repository.js +829 -0
- package/dist/commands/proposal/validators/proposal-quality-validators.js +9 -8
- package/dist/commands/proposal/validators/proposals.js +93 -882
- package/dist/commands/read/curate.js +419 -103
- package/dist/commands/read/knowledge.js +10 -3
- package/dist/commands/read/remember-cli.js +133 -138
- package/dist/commands/read/search-cli.js +15 -8
- package/dist/commands/read/search.js +22 -11
- package/dist/commands/read/show.js +106 -14
- package/dist/commands/registry-cli.js +76 -87
- package/dist/commands/remember.js +11 -12
- package/dist/commands/sources/add-cli.js +91 -95
- package/dist/commands/sources/history.js +1 -1
- package/dist/commands/sources/init.js +66 -18
- package/dist/commands/sources/installed-stashes.js +11 -3
- package/dist/commands/sources/schema-repair.js +44 -46
- package/dist/commands/sources/self-update.js +2 -2
- package/dist/commands/sources/source-add.js +7 -3
- package/dist/commands/sources/sources-cli.js +3 -3
- package/dist/commands/sources/stash-cli.js +29 -41
- package/dist/commands/sources/stash-skeleton.js +57 -8
- package/dist/commands/tasks/default-tasks.js +15 -2
- package/dist/commands/tasks/tasks-cli.js +20 -29
- package/dist/commands/tasks/tasks.js +39 -11
- package/dist/commands/wiki-cli.js +23 -38
- package/dist/commands/workflow-cli.js +15 -1
- package/dist/core/asset/asset-registry.js +3 -1
- package/dist/core/asset/asset-spec.js +21 -4
- package/dist/core/asset/frontmatter.js +188 -167
- package/dist/core/asset/markdown.js +8 -0
- package/dist/core/authoring-rules.js +92 -0
- package/dist/core/common.js +4 -23
- package/dist/core/concurrent.js +10 -1
- package/dist/core/config/config-io.js +10 -1
- package/dist/core/config/config-migration.js +18 -40
- package/dist/core/config/config-schema.js +389 -58
- package/dist/core/config/config-types.js +3 -3
- package/dist/core/config/config.js +67 -22
- package/dist/core/deep-merge.js +38 -0
- package/dist/core/errors.js +1 -0
- package/dist/core/eval/rank-metrics.js +113 -0
- package/dist/core/events.js +4 -7
- package/dist/core/improve-types.js +47 -8
- package/dist/core/logs-db.js +14 -75
- package/dist/core/parse.js +36 -16
- package/dist/core/paths.js +21 -18
- package/dist/core/standards/resolve-standards-context.js +87 -0
- package/dist/core/standards/resolve-stash-standards.js +99 -0
- package/dist/core/standards/resolve-type-conventions.js +66 -0
- package/dist/core/state/migrations.js +770 -0
- package/dist/core/state-db.js +142 -1091
- package/dist/core/structured.js +69 -0
- package/dist/core/time.js +53 -0
- package/dist/core/warn.js +21 -0
- package/dist/core/write-source.js +37 -0
- package/dist/indexer/db/db.js +356 -780
- package/dist/indexer/db/entry-mapper.js +41 -0
- package/dist/indexer/db/graph-db.js +129 -86
- package/dist/indexer/db/llm-cache.js +2 -2
- package/dist/indexer/db/schema.js +516 -0
- package/dist/indexer/ensure-index.js +103 -24
- package/dist/indexer/feedback/utility-policy.js +75 -0
- package/dist/indexer/graph/graph-boost.js +51 -41
- package/dist/indexer/graph/graph-extraction.js +207 -4
- package/dist/indexer/index-writer-lock.js +106 -0
- package/dist/indexer/index-written-assets.js +105 -0
- package/dist/indexer/indexer.js +291 -310
- package/dist/indexer/passes/dir-staleness.js +114 -0
- package/dist/indexer/passes/memory-inference.js +13 -5
- package/dist/indexer/passes/metadata.js +20 -0
- package/dist/indexer/read-preflight.js +23 -0
- package/dist/indexer/search/db-search.js +89 -13
- package/dist/indexer/search/fts-query.js +51 -0
- package/dist/indexer/search/ranking-contributors.js +95 -9
- package/dist/indexer/search/ranking.js +79 -3
- package/dist/indexer/search/search-fields.js +6 -0
- package/dist/indexer/search/search-source.js +32 -21
- package/dist/indexer/search/semantic-status.js +4 -0
- package/dist/indexer/walk/matchers.js +9 -0
- package/dist/indexer/walk/walker.js +21 -13
- package/dist/integrations/agent/builders.js +39 -13
- package/dist/integrations/agent/config.js +20 -59
- package/dist/integrations/agent/detect.js +9 -0
- package/dist/integrations/agent/index.js +3 -19
- package/dist/integrations/agent/model-aliases.js +7 -2
- package/dist/integrations/agent/profiles.js +7 -1
- package/dist/integrations/agent/prompts.js +75 -9
- package/dist/integrations/agent/runner-dispatch.js +59 -0
- package/dist/integrations/agent/runner.js +13 -9
- package/dist/integrations/agent/spawn.js +69 -67
- package/dist/integrations/harnesses/claude/agent-builder.js +1 -1
- package/dist/integrations/harnesses/claude/index.js +2 -0
- package/dist/integrations/harnesses/claude/session-log.js +11 -1
- package/dist/integrations/harnesses/index.js +2 -3
- package/dist/integrations/harnesses/opencode/agent-builder.js +1 -1
- package/dist/integrations/harnesses/opencode/index.js +2 -0
- package/dist/integrations/harnesses/opencode/session-log.js +173 -3
- package/dist/integrations/harnesses/opencode-sdk/index.js +2 -2
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +98 -17
- package/dist/integrations/harnesses/types.js +1 -0
- package/dist/integrations/session-logs/index.js +16 -0
- package/dist/llm/call-ai.js +2 -2
- package/dist/llm/client.js +57 -15
- package/dist/llm/embedder.js +67 -4
- package/dist/llm/embedders/cache.js +3 -1
- package/dist/llm/embedders/deterministic.js +66 -0
- package/dist/llm/embedders/local.js +73 -3
- package/dist/llm/feature-gate.js +16 -15
- package/dist/llm/graph-extract.js +67 -44
- package/dist/llm/memory-infer-impl.js +138 -0
- package/dist/llm/memory-infer.js +1 -127
- package/dist/llm/metadata-enhance.js +44 -31
- package/dist/llm/structured-call.js +49 -0
- package/dist/migrate-storage-node.mjs +8 -0
- package/dist/output/context.js +5 -5
- package/dist/output/renderers.js +85 -14
- package/dist/output/shapes/curate.js +14 -2
- package/dist/output/shapes/helpers.js +0 -3
- package/dist/output/shapes/passthrough.js +2 -1
- package/dist/output/text/helpers.js +29 -1
- package/dist/output/text/workflow.js +1 -0
- package/dist/registry/providers/skills-sh.js +21 -147
- package/dist/registry/providers/static-index.js +15 -157
- package/dist/registry/resolve.js +27 -9
- package/dist/runtime.js +25 -1
- package/dist/scripts/migrate-storage.js +2718 -2354
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +891 -597
- package/dist/setup/detect.js +9 -0
- package/dist/setup/legacy-config.js +106 -0
- package/dist/setup/prompt.js +57 -0
- package/dist/setup/providers.js +14 -0
- package/dist/setup/registry-stash-loader.js +12 -0
- package/dist/setup/semantic-assets.js +124 -0
- package/dist/setup/setup.js +52 -1614
- package/dist/setup/steps/connection.js +734 -0
- package/dist/setup/steps/output.js +31 -0
- package/dist/setup/steps/platforms.js +124 -0
- package/dist/setup/steps/semantic.js +27 -0
- package/dist/setup/steps/sources.js +222 -0
- package/dist/setup/steps/stashdir.js +42 -0
- package/dist/setup/steps/tasks.js +152 -0
- package/dist/sources/include.js +6 -2
- package/dist/sources/providers/filesystem.js +0 -1
- package/dist/sources/providers/git-install.js +210 -0
- package/dist/sources/providers/git-provider.js +234 -0
- package/dist/sources/providers/git-stash.js +248 -0
- package/dist/sources/providers/git.js +10 -661
- package/dist/sources/providers/npm.js +2 -6
- package/dist/sources/providers/provider-utils.js +13 -7
- package/dist/sources/providers/sync-from-ref.js +9 -1
- package/dist/sources/providers/tar-utils.js +16 -8
- package/dist/sources/providers/website.js +9 -5
- package/dist/sources/website-ingest.js +187 -29
- package/dist/sources/wiki-fetchers/registry.js +53 -0
- package/dist/sources/wiki-fetchers/youtube.js +239 -0
- package/dist/storage/database.js +45 -10
- package/dist/storage/managed-db.js +82 -0
- package/dist/storage/repositories/canaries-repository.js +107 -0
- package/dist/storage/repositories/consolidation-repository.js +38 -0
- package/dist/storage/repositories/embeddings-repository.js +72 -0
- package/dist/storage/repositories/events-repository.js +187 -0
- package/dist/storage/repositories/extract-sessions-repository.js +96 -0
- package/dist/storage/repositories/improve-runs-repository.js +146 -0
- package/dist/storage/repositories/index-db.js +14 -8
- package/dist/storage/repositories/proposals-repository.js +220 -0
- package/dist/storage/repositories/recombine-repository.js +213 -0
- package/dist/storage/repositories/registry-cache.js +93 -0
- package/dist/storage/repositories/registry-index-cache-repository.js +46 -0
- package/dist/storage/repositories/task-history-repository.js +93 -0
- package/dist/storage/sqlite-pragmas.js +146 -0
- package/dist/tasks/backends/cron.js +1 -1
- package/dist/tasks/backends/index.js +9 -0
- package/dist/tasks/backends/launchd.js +1 -1
- package/dist/tasks/backends/schtasks.js +1 -1
- package/dist/tasks/{resolveAkmBin.js → resolve-akm-bin.js} +2 -2
- package/dist/tasks/runner.js +15 -13
- package/dist/text-import-hook.mjs +0 -0
- package/dist/wiki/wiki.js +52 -11
- package/dist/workflows/cli.js +1 -0
- package/dist/workflows/db.js +3 -4
- package/dist/workflows/runtime/runs.js +43 -118
- package/dist/workflows/runtime/workflow-asset-loader.js +125 -0
- package/dist/workflows/validate-summary.js +2 -7
- package/docs/README.md +69 -18
- package/docs/data-and-telemetry.md +5 -4
- package/docs/migration/release-notes/0.7.0.md +1 -1
- package/docs/migration/release-notes/0.9.0.md +39 -0
- package/package.json +10 -10
- package/dist/assets/tasks/core/update-stashes.yml +0 -4
- package/dist/commands/db-cli.js +0 -23
- package/dist/indexer/db/db-backup.js +0 -376
- package/dist/indexer/passes/staleness-detect.js +0 -488
|
@@ -18,23 +18,28 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import fs from "node:fs";
|
|
20
20
|
import path from "node:path";
|
|
21
|
+
import { findCittyTopLevelCommandIndex } from "../../cli/parse-args.js";
|
|
21
22
|
import { parseAssetRef } from "../../core/asset/asset-ref.js";
|
|
22
23
|
import { parseFrontmatter } from "../../core/asset/frontmatter.js";
|
|
23
24
|
import { META_DIR, parseMetaRef, resolveMetaFilePath } from "../../core/asset/stash-meta.js";
|
|
24
25
|
import { asNonEmptyString } from "../../core/common.js";
|
|
25
|
-
import { loadConfig } from "../../core/config/config.js";
|
|
26
|
+
import { getIndexPassConfig, loadConfig } from "../../core/config/config.js";
|
|
26
27
|
import { NotFoundError, rethrowIfTestIsolationError, UsageError } from "../../core/errors.js";
|
|
27
28
|
import { appendEvent, readEvents } from "../../core/events.js";
|
|
28
|
-
import { findEntryIdByRef } from "../../indexer/db/db.js";
|
|
29
|
-
import {
|
|
29
|
+
import { closeDatabase, computeBodyHash, findEntryIdByRef, openExistingDatabase } from "../../indexer/db/db.js";
|
|
30
|
+
import { hasGraphData } from "../../indexer/db/graph-db.js";
|
|
30
31
|
import { listRelatedPathsForFile } from "../../indexer/graph/graph-boost.js";
|
|
32
|
+
import { extractGraphForSingleFile } from "../../indexer/graph/graph-extraction.js";
|
|
31
33
|
import { lookup } from "../../indexer/indexer.js";
|
|
34
|
+
import { ensurePrimaryIndexForRead, resolveReadSources } from "../../indexer/read-preflight.js";
|
|
32
35
|
import { buildEditHint, findSourceForPath, isEditable, resolveSourceEntries } from "../../indexer/search/search-source.js";
|
|
33
36
|
import { insertUsageEvent } from "../../indexer/usage/usage-events.js";
|
|
34
37
|
import { buildFileContext, buildRenderContext, getRenderer, runMatchers } from "../../indexer/walk/file-context.js";
|
|
35
38
|
import { resolveAssetPath } from "../../indexer/walk/path-resolver.js";
|
|
39
|
+
import { resolveIndexPassLLM } from "../../llm/index-passes.js";
|
|
36
40
|
import { resolveSourcesForOrigin } from "../../registry/origin-resolve.js";
|
|
37
|
-
import {
|
|
41
|
+
import { resolveStorageLocations } from "../../storage/locations.js";
|
|
42
|
+
import { TELEMETRY_BUSY_TIMEOUT_MS, withIndexDb } from "../../storage/repositories/index-db.js";
|
|
38
43
|
// Eagerly import source providers to trigger self-registration.
|
|
39
44
|
import "../../sources/providers/index.js";
|
|
40
45
|
import { getCurrentWorkflowScopeKey } from "../../workflows/authoring/scope-key.js";
|
|
@@ -142,10 +147,8 @@ export async function akmShowUnified(input) {
|
|
|
142
147
|
}
|
|
143
148
|
}
|
|
144
149
|
// Auto-index when stale so the index is current before lookup.
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
await ensureIndex(allSources[0].path);
|
|
148
|
-
}
|
|
150
|
+
const { primarySource } = resolveReadSources();
|
|
151
|
+
await ensurePrimaryIndexForRead(primarySource);
|
|
149
152
|
// Try local filesystem (FTS5 index lookup)
|
|
150
153
|
const result = await showLocal(input);
|
|
151
154
|
// Scope filter narrows resolution: if --scope was supplied, the asset's
|
|
@@ -296,7 +299,7 @@ function logShowEvent(ref, eventSource = "user") {
|
|
|
296
299
|
entry_id: findEntryIdByRef(db, ref),
|
|
297
300
|
source: eventSource,
|
|
298
301
|
});
|
|
299
|
-
});
|
|
302
|
+
}, { busyTimeoutMs: TELEMETRY_BUSY_TIMEOUT_MS });
|
|
300
303
|
}
|
|
301
304
|
catch (err) {
|
|
302
305
|
rethrowIfTestIsolationError(err);
|
|
@@ -360,6 +363,21 @@ export async function showLocal(input) {
|
|
|
360
363
|
}
|
|
361
364
|
const renderCtx = buildRenderContext(fileCtx, match, allSourceDirs, source?.registryId);
|
|
362
365
|
const response = renderer.buildShowResponse(renderCtx);
|
|
366
|
+
// 07 P1-D: provenance-aware toolPolicy CEILING. An agent's self-declared
|
|
367
|
+
// `tools` frontmatter is honoured ONLY for the operator's own PRIMARY stash —
|
|
368
|
+
// the assets they authored. Every other source is content pulled from
|
|
369
|
+
// elsewhere and must not name its own tool grant: registry-installed packs, a
|
|
370
|
+
// configured secondary source, and even a git source the operator marked
|
|
371
|
+
// `--writable` to contribute edits upstream (writability is "can I push", not
|
|
372
|
+
// "do I trust this content to grant itself tools"). Drop the policy so dispatch
|
|
373
|
+
// falls back to the parent/default grant. Keys off primary-stash identity —
|
|
374
|
+
// `allSources[0]` is always the primary (search-source.ts) — not a
|
|
375
|
+
// name-derived registryId or the orthogonal `writable` bit. `source` undefined
|
|
376
|
+
// (unresolved path) also fails closed.
|
|
377
|
+
const isPrimaryStash = source !== undefined && source.path === allSources[0]?.path;
|
|
378
|
+
if (response.toolPolicy !== undefined && !isPrimaryStash) {
|
|
379
|
+
delete response.toolPolicy;
|
|
380
|
+
}
|
|
363
381
|
const editable = isEditable(assetPath, config);
|
|
364
382
|
const fullResponse = {
|
|
365
383
|
...response,
|
|
@@ -383,6 +401,15 @@ export async function showLocal(input) {
|
|
|
383
401
|
if (activeRun) {
|
|
384
402
|
fullResponse.activeRun = activeRun;
|
|
385
403
|
}
|
|
404
|
+
// #624-P3: opt-in inline graph extraction. Default OFF — when the flag is
|
|
405
|
+
// unset this whole block is skipped (no hasGraphData check, no LLM call), so
|
|
406
|
+
// behavior is byte-identical to today. When ON, it extracts graph data for an
|
|
407
|
+
// ungraphed asset, but ONLY when a model is configured (model-available
|
|
408
|
+
// guard) and ALWAYS bounded by a 30s timeout so `show` can never hang. Any
|
|
409
|
+
// timeout/model-unavailable/error path returns the response unchanged.
|
|
410
|
+
if (getIndexPassConfig(config.index, "graph")?.lazyGraphExtraction === true) {
|
|
411
|
+
await maybeExtractGraphInline(config, sourceStashDir, assetPath);
|
|
412
|
+
}
|
|
386
413
|
if (input.detail === "brief") {
|
|
387
414
|
return buildBriefResponse(fullResponse, assetPath);
|
|
388
415
|
}
|
|
@@ -391,6 +418,58 @@ export async function showLocal(input) {
|
|
|
391
418
|
}
|
|
392
419
|
return fullResponse;
|
|
393
420
|
}
|
|
421
|
+
/**
|
|
422
|
+
* #624-P3 — opt-in inline graph extraction for `akm show`. Best-effort and
|
|
423
|
+
* timeout-bounded: never throws, never hangs, never mutates the response.
|
|
424
|
+
*
|
|
425
|
+
* Preconditions (caller already checked the flag): a model must be configured
|
|
426
|
+
* (model-available guard via {@link resolveIndexPassLLM}) and the asset must be
|
|
427
|
+
* ungraphed ({@link hasGraphData}). Extraction races a 30s timeout so `show`
|
|
428
|
+
* cannot block on a slow provider; any timeout/error/missing-model path is
|
|
429
|
+
* swallowed and `show` returns its already-assembled response unchanged.
|
|
430
|
+
*/
|
|
431
|
+
async function maybeExtractGraphInline(config, sourceStashDir, assetPath) {
|
|
432
|
+
try {
|
|
433
|
+
// Model-available guard — no provider configured ⇒ silent skip, no LLM call.
|
|
434
|
+
if (!resolveIndexPassLLM("graph", config))
|
|
435
|
+
return;
|
|
436
|
+
let alreadyGraphed = false;
|
|
437
|
+
let bodyHash;
|
|
438
|
+
try {
|
|
439
|
+
const raw = fs.readFileSync(assetPath, "utf8");
|
|
440
|
+
bodyHash = computeBodyHash(parseFrontmatter(raw).content.trim());
|
|
441
|
+
}
|
|
442
|
+
catch {
|
|
443
|
+
return; // file gone/unreadable ⇒ nothing to extract
|
|
444
|
+
}
|
|
445
|
+
withIndexDb((db) => {
|
|
446
|
+
alreadyGraphed = hasGraphData(db, sourceStashDir, assetPath);
|
|
447
|
+
}, { busyTimeoutMs: TELEMETRY_BUSY_TIMEOUT_MS });
|
|
448
|
+
if (alreadyGraphed)
|
|
449
|
+
return;
|
|
450
|
+
// Open the db for the async extraction ourselves: `withIndexDb` is
|
|
451
|
+
// synchronous and would close the connection the instant the async fn
|
|
452
|
+
// returns its Promise (before extraction completes). Close it explicitly
|
|
453
|
+
// after the race settles instead.
|
|
454
|
+
const db = openExistingDatabase(resolveStorageLocations().indexDb);
|
|
455
|
+
let timer;
|
|
456
|
+
const timeout = new Promise((resolve) => {
|
|
457
|
+
timer = setTimeout(resolve, 30_000);
|
|
458
|
+
});
|
|
459
|
+
try {
|
|
460
|
+
await Promise.race([extractGraphForSingleFile(db, sourceStashDir, assetPath, bodyHash, { config }), timeout]);
|
|
461
|
+
}
|
|
462
|
+
finally {
|
|
463
|
+
if (timer)
|
|
464
|
+
clearTimeout(timer);
|
|
465
|
+
closeDatabase(db);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
catch (err) {
|
|
469
|
+
rethrowIfTestIsolationError(err);
|
|
470
|
+
// Any other failure: silently return the unchanged show response.
|
|
471
|
+
}
|
|
472
|
+
}
|
|
394
473
|
/**
|
|
395
474
|
* Minimal `show`: ref → indexer lookup → file contents. Used by callers that
|
|
396
475
|
* just need the raw file (e.g. clone, write-source) and don't want the full
|
|
@@ -458,6 +537,14 @@ function buildSummaryResponse(full, assetPath) {
|
|
|
458
537
|
}
|
|
459
538
|
// ── argv normalisation ───────────────────────────────────────────────────────
|
|
460
539
|
const SHOW_VIEW_MODES = new Set(["toc", "frontmatter", "full", "section", "lines"]);
|
|
540
|
+
const SHOW_ARGV_TOP_LEVEL_ARGS = {
|
|
541
|
+
format: { type: "string" },
|
|
542
|
+
output: { type: "string" },
|
|
543
|
+
detail: { type: "string" },
|
|
544
|
+
shape: { type: "string" },
|
|
545
|
+
quiet: { type: "boolean", alias: "q" },
|
|
546
|
+
verbose: { type: "boolean" },
|
|
547
|
+
};
|
|
461
548
|
/**
|
|
462
549
|
* Normalize argv so positional view-mode arguments after the asset ref
|
|
463
550
|
* are rewritten into internal flags that citty can parse.
|
|
@@ -471,15 +558,20 @@ const SHOW_VIEW_MODES = new Set(["toc", "frontmatter", "full", "section", "lines
|
|
|
471
558
|
* Returns a new array; the input is never modified.
|
|
472
559
|
*/
|
|
473
560
|
export function normalizeShowArgv(argv) {
|
|
474
|
-
|
|
475
|
-
|
|
561
|
+
const rawArgs = argv.slice(2);
|
|
562
|
+
const commandIndex = findCittyTopLevelCommandIndex(rawArgs, SHOW_ARGV_TOP_LEVEL_ARGS);
|
|
563
|
+
if (commandIndex < 0 || rawArgs[commandIndex] !== "show")
|
|
476
564
|
return argv;
|
|
477
|
-
|
|
565
|
+
const commandArgs = rawArgs.slice(commandIndex + 1);
|
|
566
|
+
if (commandArgs.includes("--view") ||
|
|
567
|
+
commandArgs.includes("--heading") ||
|
|
568
|
+
commandArgs.includes("--start") ||
|
|
569
|
+
commandArgs.includes("--end")) {
|
|
478
570
|
throw new UsageError('Legacy show flags are no longer supported. Use positional syntax like `akm show knowledge:guide toc` or `akm show knowledge:guide section "Auth"`.');
|
|
479
571
|
}
|
|
480
572
|
// Separate global flags from positional/show-specific args
|
|
481
|
-
const prefix = argv.slice(0,
|
|
482
|
-
const rest =
|
|
573
|
+
const prefix = [...argv.slice(0, 2), ...rawArgs.slice(0, commandIndex + 1)];
|
|
574
|
+
const rest = commandArgs;
|
|
483
575
|
const globalFlags = [];
|
|
484
576
|
const showArgs = [];
|
|
485
577
|
for (let i = 0; i < rest.length; i++) {
|
|
@@ -3,27 +3,24 @@
|
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import { parsePositiveIntFlag } from "../cli/parse-args.js";
|
|
6
|
-
import {
|
|
6
|
+
import { defineJsonCommand, output } from "../cli/shared.js";
|
|
7
7
|
import { DEFAULT_CONFIG, loadUserConfig, saveConfig } from "../core/config/config.js";
|
|
8
8
|
import { UsageError } from "../core/errors.js";
|
|
9
9
|
import { warn } from "../core/warn.js";
|
|
10
|
-
import { getHyphenatedArg, getHyphenatedBoolean } from "../output/context.js";
|
|
11
10
|
import { buildRegistryIndex, writeRegistryIndex } from "../registry/build-index.js";
|
|
12
11
|
import { searchRegistry } from "./read/registry-search.js";
|
|
13
12
|
export const registryCommand = defineCommand({
|
|
14
13
|
meta: { name: "registry", description: "Manage stash registries" },
|
|
15
14
|
subCommands: {
|
|
16
|
-
list:
|
|
15
|
+
list: defineJsonCommand({
|
|
17
16
|
meta: { name: "list", description: "List configured registries" },
|
|
18
|
-
run() {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
output("registry-list", { registries });
|
|
23
|
-
});
|
|
17
|
+
async run() {
|
|
18
|
+
const config = loadUserConfig();
|
|
19
|
+
const registries = config.registries ?? DEFAULT_CONFIG.registries;
|
|
20
|
+
output("registry-list", { registries });
|
|
24
21
|
},
|
|
25
22
|
}),
|
|
26
|
-
add:
|
|
23
|
+
add: defineJsonCommand({
|
|
27
24
|
meta: { name: "add", description: "Add a registry by URL" },
|
|
28
25
|
args: {
|
|
29
26
|
url: { type: "positional", description: "Registry index URL", required: true },
|
|
@@ -36,75 +33,71 @@ export const registryCommand = defineCommand({
|
|
|
36
33
|
default: false,
|
|
37
34
|
},
|
|
38
35
|
},
|
|
39
|
-
run({ args }) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
"Use https:// or pass --allow-insecure if you have explicitly accepted the risk.");
|
|
49
|
-
}
|
|
50
|
-
warn("Warning: registry URL uses plain HTTP (not HTTPS). --allow-insecure was set; an on-path attacker could substitute a malicious index.");
|
|
36
|
+
async run({ args }) {
|
|
37
|
+
if (!args.url.startsWith("http")) {
|
|
38
|
+
throw new UsageError("Registry URL must start with http:// or https://");
|
|
39
|
+
}
|
|
40
|
+
if (args.url.startsWith("http://")) {
|
|
41
|
+
const allowInsecure = args["allow-insecure"];
|
|
42
|
+
if (!allowInsecure) {
|
|
43
|
+
throw new UsageError("Registry URL uses plain HTTP (not HTTPS). An on-path attacker could substitute a malicious index. " +
|
|
44
|
+
"Use https:// or pass --allow-insecure if you have explicitly accepted the risk.");
|
|
51
45
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
46
|
+
warn("Warning: registry URL uses plain HTTP (not HTTPS). --allow-insecure was set; an on-path attacker could substitute a malicious index.");
|
|
47
|
+
}
|
|
48
|
+
const config = loadUserConfig();
|
|
49
|
+
const registries = [...(config.registries ?? [])];
|
|
50
|
+
// Deduplicate by URL
|
|
51
|
+
if (registries.some((r) => r.url === args.url)) {
|
|
52
|
+
output("registry-add", { registries, added: false, message: "Registry URL already configured" });
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const entry = { url: args.url };
|
|
56
|
+
if (args.name)
|
|
57
|
+
entry.name = args.name;
|
|
58
|
+
if (args.provider)
|
|
59
|
+
entry.provider = args.provider;
|
|
60
|
+
if (args.options) {
|
|
61
|
+
try {
|
|
62
|
+
entry.options = JSON.parse(args.options);
|
|
58
63
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
entry.name = args.name;
|
|
62
|
-
if (args.provider)
|
|
63
|
-
entry.provider = args.provider;
|
|
64
|
-
if (args.options) {
|
|
65
|
-
try {
|
|
66
|
-
entry.options = JSON.parse(args.options);
|
|
67
|
-
}
|
|
68
|
-
catch {
|
|
69
|
-
throw new UsageError("--options must be valid JSON");
|
|
70
|
-
}
|
|
64
|
+
catch {
|
|
65
|
+
throw new UsageError("--options must be valid JSON");
|
|
71
66
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
});
|
|
67
|
+
}
|
|
68
|
+
registries.push(entry);
|
|
69
|
+
saveConfig({ ...config, registries });
|
|
70
|
+
output("registry-add", { registries, added: true });
|
|
76
71
|
},
|
|
77
72
|
}),
|
|
78
|
-
remove:
|
|
73
|
+
remove: defineJsonCommand({
|
|
79
74
|
meta: { name: "remove", description: "Remove a registry by URL or name" },
|
|
80
75
|
args: {
|
|
81
76
|
target: { type: "positional", description: "Registry URL or name to remove", required: true },
|
|
82
77
|
yes: { type: "boolean", alias: "y", description: "Skip confirmation prompt", default: false },
|
|
83
78
|
},
|
|
84
|
-
run({ args }) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
yes: args.yes === true,
|
|
96
|
-
});
|
|
97
|
-
if (!confirmed) {
|
|
98
|
-
process.stderr.write("Aborted.\n");
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
const removed = registries.splice(idx, 1)[0];
|
|
102
|
-
saveConfig({ ...config, registries });
|
|
103
|
-
output("registry-remove", { registries, removed: true, entry: removed });
|
|
79
|
+
async run({ args }) {
|
|
80
|
+
const config = loadUserConfig();
|
|
81
|
+
const registries = [...(config.registries ?? [])];
|
|
82
|
+
const idx = registries.findIndex((r) => r.url === args.target || r.name === args.target);
|
|
83
|
+
if (idx === -1) {
|
|
84
|
+
output("registry-remove", { registries, removed: false, message: "No matching registry found" });
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const { confirmDestructive } = await import("../cli/confirm.js");
|
|
88
|
+
const confirmed = await confirmDestructive(`Remove registry "${args.target}"? This cannot be undone.`, {
|
|
89
|
+
yes: args.yes === true,
|
|
104
90
|
});
|
|
91
|
+
if (!confirmed) {
|
|
92
|
+
process.stderr.write("Aborted.\n");
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const removed = registries.splice(idx, 1)[0];
|
|
96
|
+
saveConfig({ ...config, registries });
|
|
97
|
+
output("registry-remove", { registries, removed: true, entry: removed });
|
|
105
98
|
},
|
|
106
99
|
}),
|
|
107
|
-
search:
|
|
100
|
+
search: defineJsonCommand({
|
|
108
101
|
meta: { name: "search", description: "Search enabled registries for stashes" },
|
|
109
102
|
args: {
|
|
110
103
|
query: { type: "positional", description: "Search query", required: true },
|
|
@@ -112,14 +105,12 @@ export const registryCommand = defineCommand({
|
|
|
112
105
|
assets: { type: "boolean", description: "Include asset-level search results", default: false },
|
|
113
106
|
},
|
|
114
107
|
async run({ args }) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
output("registry-search", result);
|
|
119
|
-
});
|
|
108
|
+
const limitRaw = parsePositiveIntFlag(args.limit ?? undefined);
|
|
109
|
+
const result = await searchRegistry(args.query, { limit: limitRaw, includeAssets: args.assets });
|
|
110
|
+
output("registry-search", result);
|
|
120
111
|
},
|
|
121
112
|
}),
|
|
122
|
-
"build-index":
|
|
113
|
+
"build-index": defineJsonCommand({
|
|
123
114
|
meta: { name: "build-index", description: "Build a v2 registry index from discovery and manual entries" },
|
|
124
115
|
args: {
|
|
125
116
|
out: { type: "string", description: "Output path for the generated index" },
|
|
@@ -128,21 +119,19 @@ export const registryCommand = defineCommand({
|
|
|
128
119
|
"github-api": { type: "string", description: "Override GitHub API base URL" },
|
|
129
120
|
},
|
|
130
121
|
async run({ args }) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
manualEntriesPath: result.paths.manualEntriesPath,
|
|
145
|
-
});
|
|
122
|
+
const result = await buildRegistryIndex({
|
|
123
|
+
manualEntriesPath: args.manual,
|
|
124
|
+
npmRegistryBase: args["npm-registry"],
|
|
125
|
+
githubApiBase: args["github-api"],
|
|
126
|
+
});
|
|
127
|
+
const outPath = writeRegistryIndex(result.index, args.out);
|
|
128
|
+
output("registry-build-index", {
|
|
129
|
+
outPath,
|
|
130
|
+
version: result.index.version,
|
|
131
|
+
updatedAt: result.index.updatedAt,
|
|
132
|
+
totalKits: result.counts.total,
|
|
133
|
+
counts: result.counts,
|
|
134
|
+
manualEntriesPath: result.paths.manualEntriesPath,
|
|
146
135
|
});
|
|
147
136
|
},
|
|
148
137
|
}),
|
|
@@ -12,25 +12,24 @@ import { serializeFrontmatter } from "../core/asset/asset-serialize.js";
|
|
|
12
12
|
import { toErrorMessage, tryReadStdinText } from "../core/common.js";
|
|
13
13
|
import { getDefaultLlmConfig, loadConfig } from "../core/config/config.js";
|
|
14
14
|
import { UsageError } from "../core/errors.js";
|
|
15
|
+
import { DURATION_UNITS, parseDuration as parseDurationSpec } from "../core/time.js";
|
|
15
16
|
import { warn } from "../core/warn.js";
|
|
16
17
|
import { SCOPE_KEYS } from "../indexer/passes/metadata.js";
|
|
17
18
|
import { parseFlagValue } from "../output/context.js";
|
|
18
19
|
/**
|
|
19
20
|
* Parse a shorthand duration string to a number of milliseconds.
|
|
20
|
-
* Supports: `30d` (days), `12h` (hours),
|
|
21
|
+
* Supports the CLI-wide canonical grammar: `30d` (days), `12h` (hours),
|
|
22
|
+
* `5m` (minutes), `3M` (months, approximated as 30d).
|
|
21
23
|
*/
|
|
22
24
|
export function parseDuration(s) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return n * 60 * 60 * 1000;
|
|
32
|
-
// 'm' = months, approximated as 30 days
|
|
33
|
-
return n * 30 * 24 * 60 * 60 * 1000;
|
|
25
|
+
// Canonical CLI unit grammar: `m` = minutes, `M` = months. Not lower-cased,
|
|
26
|
+
// so case distinguishes the two (`5m` = 5 minutes, `5M` = 5 months). See
|
|
27
|
+
// core/time.ts DURATION_UNITS.
|
|
28
|
+
const ms = parseDurationSpec(s.trim(), DURATION_UNITS);
|
|
29
|
+
if (ms === null) {
|
|
30
|
+
throw new UsageError(`Invalid --expires format "${s}". Use shorthand like 30d, 12h, 5m, or 3M.`, "INVALID_FLAG_VALUE");
|
|
31
|
+
}
|
|
32
|
+
return ms;
|
|
34
33
|
}
|
|
35
34
|
/**
|
|
36
35
|
* Build a YAML frontmatter block from memory metadata.
|