@aiwg/cli 2026.10.5 → 2026.10.7
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/agentic/code/addons/composition-engine/lib/runtime.mjs +1401 -0
- package/agentic/code/addons/composition-engine/lib/validator.mjs +513 -0
- package/agentic/code/addons/composition-engine/schemas/flow-graph.schema.json +372 -0
- package/agentic/code/providers/model-capabilities.v1.json +74 -50
- package/bin/aiwg.mjs +7 -3
- package/dist/src/a2a/agent-card.js +11 -0
- package/dist/src/api/index.d.ts +1 -0
- package/dist/src/api/index.js +1 -0
- package/dist/src/artifacts/browser-export.js +1 -0
- package/dist/src/artifacts/citation-parser.js +8 -1
- package/dist/src/artifacts/cli.js +57 -6
- package/dist/src/artifacts/fortemi-core-query-adapter.js +2 -0
- package/dist/src/artifacts/fortemi-core-sync.js +26 -8
- package/dist/src/artifacts/fortemi-shard-contract/2.2.0/contract.json +103 -0
- package/dist/src/artifacts/fortemi-shard-contract/2.2.0/full-v1-embedding-config.schema.json +212 -0
- package/dist/src/artifacts/fortemi-shard-contract/2.2.0/full-v1-embedding-set.schema.json +240 -0
- package/dist/src/artifacts/fortemi-shard-contract/2.2.0/full-v1-manifest.schema.json +451 -0
- package/dist/src/artifacts/fortemi-shard-export.js +284 -0
- package/dist/src/artifacts/graph-query.js +18 -8
- package/dist/src/artifacts/index-adapters.js +339 -0
- package/dist/src/artifacts/index-builder.js +143 -14
- package/dist/src/artifacts/index-files.js +15 -4
- package/dist/src/artifacts/index-preparation.js +2 -0
- package/dist/src/artifacts/index-reader.js +44 -0
- package/dist/src/artifacts/index-refresh.js +114 -55
- package/dist/src/artifacts/index-status.js +20 -5
- package/dist/src/artifacts/memory-maintenance.js +503 -0
- package/dist/src/artifacts/prebuilt-relations.js +3 -1
- package/dist/src/artifacts/query-engine.js +263 -108
- package/dist/src/artifacts/relations-builder.js +2 -2
- package/dist/src/artifacts/source-graph.js +2 -2
- package/dist/src/artifacts/types.js +9 -1
- package/dist/src/auth/client.js +5 -1
- package/dist/src/auth/credential-store.js +5 -1
- package/dist/src/auth/sensitive-input.js +151 -0
- package/dist/src/channel/manager.mjs +3 -0
- package/dist/src/cli/handlers/agentcard.js +47 -25
- package/dist/src/cli/handlers/auth.js +22 -2
- package/dist/src/cli/handlers/decision.js +22 -3
- package/dist/src/cli/handlers/effect.js +4 -84
- package/dist/src/cli/handlers/guided-setup.js +470 -0
- package/dist/src/cli/handlers/help.js +2 -2
- package/dist/src/cli/handlers/housekeeper.js +1110 -0
- package/dist/src/cli/handlers/index.js +4 -2
- package/dist/src/cli/handlers/init.js +41 -6
- package/dist/src/cli/handlers/install.js +6 -0
- package/dist/src/cli/handlers/local-executor.js +5 -3
- package/dist/src/cli/handlers/marketplace.js +15 -4
- package/dist/src/cli/handlers/mc.js +509 -53
- package/dist/src/cli/handlers/models.js +32 -2
- package/dist/src/cli/handlers/ralph-launcher.js +76 -4
- package/dist/src/cli/handlers/rules.js +1 -1
- package/dist/src/cli/handlers/script-runner.js +73 -2
- package/dist/src/cli/handlers/serve.js +5 -3
- package/dist/src/cli/handlers/sessions.js +1 -0
- package/dist/src/cli/handlers/setup.js +432 -1
- package/dist/src/cli/handlers/skill-lint.js +1 -1
- package/dist/src/cli/handlers/subcommands.js +118 -8
- package/dist/src/cli/handlers/use.js +335 -107
- package/dist/src/cli/handlers/workspace.js +3 -1
- package/dist/src/cli/prompt-utils.js +81 -0
- package/dist/src/cli/router.js +16 -1
- package/dist/src/config/aiwg-config.js +42 -0
- package/dist/src/config/cli.js +7 -3
- package/dist/src/config/decision-config.js +14 -1
- package/dist/src/config/gitignore.js +4 -0
- package/dist/src/config/native-sandbox-warnings.js +25 -0
- package/dist/src/config/workspace.js +2 -1
- package/dist/src/contributors/validation.js +6 -5
- package/dist/src/decision/adapters/jev.js +20 -31
- package/dist/src/decision/admission.js +7 -3
- package/dist/src/decision/ask.js +6 -1
- package/dist/src/decision/benchmark.js +482 -0
- package/dist/src/decision/ledger.js +22 -3
- package/dist/src/decision/pricing.js +147 -0
- package/dist/src/decision/qualification/gate-evidence.js +23 -18
- package/dist/src/decision/qualification/load-staged.js +576 -0
- package/dist/src/decision/qualification/load.js +109 -33
- package/dist/src/decision/qualification/runner.js +12 -5
- package/dist/src/decision/review/service.js +6 -4
- package/dist/src/decision/review/validate.js +23 -2
- package/dist/src/decision/savings.js +8 -3
- package/dist/src/discovery/index.js +492 -0
- package/dist/src/discovery/interview.js +238 -0
- package/dist/src/discovery/plan-apply.js +567 -0
- package/dist/src/discovery/plan-store.js +171 -0
- package/dist/src/discovery/plan-types.js +2 -0
- package/dist/src/discovery/plan-validation.js +139 -0
- package/dist/src/discovery/types.js +2 -0
- package/dist/src/effects/host.js +91 -0
- package/dist/src/extensions/commands/definitions.js +49 -9
- package/dist/src/extensions/manifest.js +71 -44
- package/dist/src/extensions/project-local-discovery.js +1 -1
- package/dist/src/extensions/project-local-gitignore.js +2 -0
- package/dist/src/extensions/project-quickref.js +18 -17
- package/dist/src/extensions/validation.js +32 -29
- package/dist/src/housekeeper/daemon-config.js +148 -0
- package/dist/src/housekeeper/ipc.js +84 -0
- package/dist/src/housekeeper/lifecycle.js +148 -0
- package/dist/src/housekeeper/platform.js +35 -0
- package/dist/src/housekeeper/status.js +70 -0
- package/dist/src/housekeeper/units.js +114 -0
- package/dist/src/issues/cli.js +16 -5
- package/dist/src/issues/live.js +44 -12
- package/dist/src/jobs/flow.js +22 -21
- package/dist/src/lint/rule-activation.js +20 -5
- package/dist/src/lint/runner.js +1 -1
- package/dist/src/marketplace/exchange.js +18 -6
- package/dist/src/marketplace/provenance.js +3 -2
- package/dist/src/mcp/adapters/codex-runtime.js +46 -76
- package/dist/src/mcp/cli.mjs +22 -96
- package/dist/src/mcp/config-file.mjs +6 -2
- package/dist/src/mcp/config-layers.mjs +23 -7
- package/dist/src/mcp/grok-build-config.mjs +2 -1
- package/dist/src/mcp/muse-native-config.mjs +2 -1
- package/dist/src/mcp/profiles.js +18 -31
- package/dist/src/mcp/profiles.mjs +18 -32
- package/dist/src/mcp/registry.js +7 -27
- package/dist/src/mcp/registry.mjs +7 -28
- package/dist/src/mcp/server.mjs +34 -1
- package/dist/src/mcp/tools/agentic-sandbox.mjs +8 -7
- package/dist/src/mcp/tools/command-run.mjs +3 -2
- package/dist/src/mcp/tools/decision.mjs +49 -48
- package/dist/src/mcp/tools/discovery.mjs +46 -21
- package/dist/src/mcp/tools/orchestration.mjs +22 -22
- package/dist/src/mcp/tools/subsystems.mjs +9 -8
- package/dist/src/mcp/tools/worker-invoke.mjs +30 -6
- package/dist/src/mcp/tools/writer-profiles.mjs +1 -1
- package/dist/src/memory/audit.js +719 -0
- package/dist/src/memory/canonical-context.js +392 -13
- package/dist/src/memory/canonical-maintenance.js +95 -0
- package/dist/src/memory/cli-result.js +22 -0
- package/dist/src/memory/cli.js +176 -0
- package/dist/src/memory/context-pack.js +57 -6
- package/dist/src/memory/cost.js +512 -0
- package/dist/src/memory/firewall-classification.d.mts +7 -0
- package/dist/src/memory/firewall-classification.mjs +32 -0
- package/dist/src/memory/index.js +8 -0
- package/dist/src/memory/line-maintenance.js +68 -0
- package/dist/src/memory/maintenance-cli.js +286 -0
- package/dist/src/memory/maintenance-contract.js +136 -0
- package/dist/src/memory/maintenance-index.js +18 -0
- package/dist/src/memory/maintenance-owner.js +2 -0
- package/dist/src/memory/maintenance-record.js +138 -0
- package/dist/src/memory/maintenance.js +254 -0
- package/dist/src/memory/project-registry.js +2 -1
- package/dist/src/memory/provider-memory-adapter.js +154 -0
- package/dist/src/memory/recommend-cli.js +83 -0
- package/dist/src/memory/recommend.js +269 -0
- package/dist/src/memory/scheduled.js +81 -0
- package/dist/src/memory/taxonomy.js +44 -0
- package/dist/src/mission-protocol/codecs.js +19 -9
- package/dist/src/mission-protocol/worker-status.js +91 -1
- package/dist/src/models/config-loader.js +11 -1
- package/dist/src/models/model-capabilities.v1.json +74 -50
- package/dist/src/models/provider-policy.js +125 -62
- package/dist/src/models/resolver.js +45 -8
- package/dist/src/models/worker-installation.d.mts +8 -1
- package/dist/src/models/worker-installation.mjs +231 -38
- package/dist/src/models/wrapper-route.js +1 -1
- package/dist/src/output-modes/registry.js +8 -7
- package/dist/src/packages/adapters/git.js +99 -23
- package/dist/src/packages/adapters/gitea.js +8 -27
- package/dist/src/packages/adapters/github.js +7 -25
- package/dist/src/packages/registry.js +4 -4
- package/dist/src/plugin/metadata-validator.js +1 -1
- package/dist/src/process/cli-command.d.mts +5 -0
- package/dist/src/process/cli-command.mjs +42 -0
- package/dist/src/providers/deploy-version.d.mts +1 -0
- package/dist/src/providers/deploy-version.mjs +17 -0
- package/dist/src/providers/provider-definitions.js +19 -16
- package/dist/src/providers/skill-ownership.d.mts +11 -2
- package/dist/src/providers/skill-ownership.mjs +35 -17
- package/dist/src/rules/activation.d.mts +11 -2
- package/dist/src/rules/activation.mjs +82 -6
- package/dist/src/rules/inventory.js +1 -1
- package/dist/src/rules/rule-frontmatter.schema.json +2 -0
- package/dist/src/schema/zod-validation.d.mts +6 -0
- package/dist/src/schema/zod-validation.mjs +50 -0
- package/dist/src/serve/executor-registry.js +297 -20
- package/dist/src/serve/executor-token.d.mts +1 -0
- package/dist/src/serve/executor-token.mjs +8 -0
- package/dist/src/serve/shared-host-scheduler.js +1102 -31
- package/dist/src/serve/worker-invocation.js +124 -15
- package/dist/src/sessions/adapters/claude.js +19 -18
- package/dist/src/sessions/adapters/codex.js +10 -9
- package/dist/src/sessions/adapters/copilot.js +14 -13
- package/dist/src/sessions/adapters/cursor.js +19 -18
- package/dist/src/sessions/adapters/deepseek-harness.js +9 -8
- package/dist/src/sessions/adapters/factory.js +11 -10
- package/dist/src/sessions/adapters/generic.js +32 -23
- package/dist/src/sessions/adapters/grokbot.js +35 -35
- package/dist/src/sessions/adapters/hermes.js +20 -19
- package/dist/src/sessions/adapters/muse.js +50 -49
- package/dist/src/sessions/adapters/omp.js +5 -4
- package/dist/src/sessions/adapters/openclaw.js +30 -29
- package/dist/src/sessions/adapters/opencode.js +26 -26
- package/dist/src/sessions/adapters/openhuman.js +24 -23
- package/dist/src/sessions/adapters/pi.js +5 -4
- package/dist/src/sessions/adapters/windsurf.js +8 -8
- package/dist/src/sessions/analytics.js +10 -9
- package/dist/src/sessions/candidates.js +7 -6
- package/dist/src/sessions/contracts.js +63 -53
- package/dist/src/sessions/output-registration.js +11 -10
- package/dist/src/sessions/workspace-discovery.js +3 -4
- package/dist/src/smiths/context-pipeline/aiwg-md.js +18 -1
- package/dist/src/smiths/context-pipeline/claude-hook.js +46 -10
- package/dist/src/smiths/context-pipeline/context-file-safety.js +330 -9
- package/dist/src/smiths/context-pipeline/finalization.js +3 -2
- package/dist/src/smiths/context-pipeline/generator.js +7 -19
- package/dist/src/smiths/context-pipeline/legacy-inject.js +3 -10
- package/dist/src/smiths/context-pipeline/managed-hook.js +5 -5
- package/dist/src/smiths/context-pipeline/parallelism-section.js +72 -5
- package/dist/src/smiths/context-pipeline/workspace-context.js +110 -22
- package/dist/src/tracker/project-inputs.js +2 -0
- package/dist/src/update/checker.d.mts +4 -0
- package/dist/src/update/checker.mjs +14 -0
- package/dist/src/update/notifier.mjs +2 -4
- package/dist/src/writing/exemplar-selection.js +6 -6
- package/dist/src/writing/voice-evaluation.js +24 -23
- package/dist/src/writing/writer-migration.js +14 -13
- package/dist/src/writing/writer-profile.js +19 -18
- package/dist/src/writing/writing-brief.js +18 -17
- package/dist/src/writing/writing-receipt.js +47 -46
- package/package.json +5 -2
- package/schemas/decision/DecisionReview.schema.json +78 -1
- package/schemas/mission-v1.schema.json +3 -0
- package/tools/agents/deploy-agents.mjs +67 -39
- package/tools/agents/providers/antigravity.mjs +6 -1
- package/tools/agents/providers/base.mjs +24 -14
- package/tools/agents/providers/claude.mjs +6 -3
- package/tools/agents/providers/codex.mjs +54 -57
- package/tools/agents/providers/context-write.mjs +28 -0
- package/tools/agents/providers/copilot.mjs +13 -4
- package/tools/agents/providers/cursor.mjs +1 -1
- package/tools/agents/providers/deepseek-harness.mjs +1 -1
- package/tools/agents/providers/factory.mjs +7 -1
- package/tools/agents/providers/grok-build.mjs +18 -2
- package/tools/agents/providers/grokbot.mjs +1 -1
- package/tools/agents/providers/hermes.mjs +12 -15
- package/tools/agents/providers/muse-hooks.mjs +21 -14
- package/tools/agents/providers/muse.mjs +7 -2
- package/tools/agents/providers/omp.mjs +31 -5
- package/tools/agents/providers/opencode.mjs +14 -5
- package/tools/agents/providers/openhuman.mjs +1 -1
- package/tools/agents/providers/pi.mjs +1 -1
- package/tools/agents/providers/provider-prepare-coordinator.mjs +29 -9
- package/tools/agents/providers/rule-delivery.mjs +289 -80
- package/tools/agents/providers/warp.mjs +4 -1
- package/tools/agents/providers/windsurf.mjs +13 -3
- package/tools/cli/workspace-status.mjs +5 -0
- package/tools/commands/deploy-prompts-codex.mjs +11 -8
- package/tools/ralph-external/lib/codex-adapter.mjs +6 -2
- package/tools/ralph-external/lib/consecutive-failure-circuit-breaker.mjs +26 -0
- package/tools/ralph-external/lib/launcher-recovery-evidence.mjs +7 -1
- package/tools/ralph-external/lib/muse-adapter.mjs +12 -2
- package/tools/ralph-external/lib/recovery-probe.mjs +14 -4
- package/tools/ralph-external/lib/worker-health.mjs +1 -1
- package/tools/ralph-external/lib/worker-isolation.mjs +65 -9
- package/tools/ralph-external/process-monitor.mjs +49 -8
- package/tools/ralph-external/session-launcher.mjs +405 -35
- package/tools/skills/deploy-skills-codex.mjs +11 -7
- package/vscode-extension/schemas/aiwg.config.v1.json +11 -1
|
@@ -87,9 +87,14 @@ export async function collectGraphIndexFiles(cwd, graph, options = {}) {
|
|
|
87
87
|
throw new Error(`Unknown graph: ${graph}`);
|
|
88
88
|
}
|
|
89
89
|
const artifactRoot = resolveProjectAiwgDir(cwd);
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
const artifactRoots = [path.join(cwd, DEFAULT_PROJECT_AIWG_DIR), artifactRoot];
|
|
91
|
+
// Aggregate owner state contains history, tombstones and transaction payloads.
|
|
92
|
+
// It is not an ordinary artifact: only each owner's public projection is a
|
|
93
|
+
// retrieval surface, never the backing store or maintenance receipts.
|
|
94
|
+
const privateDirs = ['context/compound-memory', 'memory/transactions', 'memory/maintenance'];
|
|
95
|
+
const privateFiles = ['memory/line-memory.meta.json', 'memory/line-memory.config.json', 'memory/line-memory.lock'];
|
|
96
|
+
const excludedDirs = artifactRoots.flatMap(root => [...INDEX_SCRATCH_DIRS, ...privateDirs].map(name => path.resolve(root, name)));
|
|
97
|
+
const excludedPaths = new Set([...excludedDirs, ...artifactRoots.flatMap(root => privateFiles.map(name => path.resolve(root, name)))]);
|
|
93
98
|
// A directory's ancestors are shared by thousands of sibling artifacts.
|
|
94
99
|
// Cache only within this scan so the next build still notices new symlinks.
|
|
95
100
|
const safePaths = new Map();
|
|
@@ -109,7 +114,7 @@ export async function collectGraphIndexFiles(cwd, graph, options = {}) {
|
|
|
109
114
|
}
|
|
110
115
|
const inputPath = file;
|
|
111
116
|
file = path.resolve(file);
|
|
112
|
-
if (excludedDirs.some(dir => process.platform === 'win32'
|
|
117
|
+
if (excludedPaths.has(file) || excludedDirs.some(dir => process.platform === 'win32'
|
|
113
118
|
? pathContains(dir, file) : file === dir || file.startsWith(dir + path.sep)))
|
|
114
119
|
return false;
|
|
115
120
|
if (knownStat && !knownStat.isSymbolicLink() && safePaths.get(path.dirname(file)) === true) {
|
|
@@ -190,6 +195,10 @@ export async function collectGraphIndexFiles(cwd, graph, options = {}) {
|
|
|
190
195
|
}
|
|
191
196
|
}
|
|
192
197
|
let sources = [...files];
|
|
198
|
+
const candidates = [...sources].sort();
|
|
199
|
+
if (options.selection?.files && JSON.stringify(candidates) === JSON.stringify(options.selection.candidates)) {
|
|
200
|
+
return [...options.selection.files];
|
|
201
|
+
}
|
|
193
202
|
if (!options.includeIgnored) {
|
|
194
203
|
// Many projects ignore the whole artifact root (`.aiwg/`). Honoring that
|
|
195
204
|
// would empty the index, so ignore rules apply only beneath a scan root
|
|
@@ -225,6 +234,8 @@ export async function collectGraphIndexFiles(cwd, graph, options = {}) {
|
|
|
225
234
|
if (!selected.has(file))
|
|
226
235
|
options.fileStats.delete(file);
|
|
227
236
|
}
|
|
237
|
+
if (options.selection)
|
|
238
|
+
Object.assign(options.selection, { candidates, files: [...sources] });
|
|
228
239
|
return sources;
|
|
229
240
|
}
|
|
230
241
|
//# sourceMappingURL=index-files.js.map
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import { fork } from 'node:child_process';
|
|
4
4
|
import { signalChild } from '../process/signal-child.mjs';
|
|
5
|
+
import { helperEnvironment, DEPLOYMENT_HELPER_ENV_ALLOWLIST } from '../process/cli-command.mjs';
|
|
5
6
|
const MIB = 1024 ** 2;
|
|
6
7
|
const WORKER_HEAP_MB = 256;
|
|
7
8
|
// Leave room for V8's young generation, executable code, IPC and native allocations.
|
|
@@ -68,6 +69,7 @@ export async function runIndexPreparation(jobs, serial, moduleUrl, requested, on
|
|
|
68
69
|
// Node during allocation before its isolate-limit error is delivered.
|
|
69
70
|
// A child heap fatal/SIGABRT is instead an ordinary, recoverable exit.
|
|
70
71
|
const worker = fork(new URL('./index-worker.mjs', import.meta.url), [moduleUrl], {
|
|
72
|
+
env: helperEnvironment(process.env, DEPLOYMENT_HELPER_ENV_ALLOWLIST),
|
|
71
73
|
execArgv: [`--max-old-space-size=${WORKER_HEAP_MB}`, '--max-semi-space-size=16'],
|
|
72
74
|
stdio: ['ignore', 'ignore', 'pipe', 'ipc'], serialization: 'advanced',
|
|
73
75
|
});
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import fs from 'fs';
|
|
12
12
|
import path from 'path';
|
|
13
13
|
import { getGraphIndexDir, getProjectIndexRoot } from './types.js';
|
|
14
|
+
import { loadManifest, writeManifest } from './checksum-manifest.js';
|
|
14
15
|
/**
|
|
15
16
|
* Load a JSON file from the index directory
|
|
16
17
|
*
|
|
@@ -109,4 +110,47 @@ export function loadGraphIndexFile(cwd, filename, graph) {
|
|
|
109
110
|
return null;
|
|
110
111
|
}
|
|
111
112
|
}
|
|
113
|
+
/** Publish a prepared snapshot with the existing atomic file writes under the owner lock. */
|
|
114
|
+
export function publishIndexFiles(staging, directory) {
|
|
115
|
+
const files = fs.readdirSync(staging).filter(file => fs.statSync(path.join(staging, file)).isFile())
|
|
116
|
+
.sort((a, b) => Number(a === 'metadata.json') - Number(b === 'metadata.json'));
|
|
117
|
+
const backups = path.join(staging, '.previous');
|
|
118
|
+
fs.mkdirSync(backups);
|
|
119
|
+
for (const file of files) {
|
|
120
|
+
const target = path.join(directory, file);
|
|
121
|
+
if (fs.existsSync(target))
|
|
122
|
+
fs.copyFileSync(target, path.join(backups, file));
|
|
123
|
+
}
|
|
124
|
+
const published = [];
|
|
125
|
+
try {
|
|
126
|
+
for (const file of files) {
|
|
127
|
+
fs.renameSync(path.join(staging, file), path.join(directory, file));
|
|
128
|
+
published.push(file);
|
|
129
|
+
}
|
|
130
|
+
// Receipts bind to final inode signatures, after the atomic renames.
|
|
131
|
+
if (files.includes('checksum-manifest.json')) {
|
|
132
|
+
const manifest = loadManifest(directory);
|
|
133
|
+
const signature = (file) => {
|
|
134
|
+
const stat = fs.statSync(path.join(directory, file), { bigint: true });
|
|
135
|
+
return [stat.dev, stat.ino, stat.size, stat.mtimeNs, stat.ctimeNs].join(':');
|
|
136
|
+
};
|
|
137
|
+
if (manifest.receipt) {
|
|
138
|
+
manifest.receipt.metadataSignature = signature('metadata.json');
|
|
139
|
+
if (manifest.receipt.relations)
|
|
140
|
+
manifest.receipt.relations.signature = signature('relations.json');
|
|
141
|
+
writeManifest(directory, manifest);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
for (const file of published.reverse()) {
|
|
147
|
+
const backup = path.join(backups, file);
|
|
148
|
+
if (fs.existsSync(backup))
|
|
149
|
+
fs.renameSync(backup, path.join(directory, file));
|
|
150
|
+
else
|
|
151
|
+
fs.rmSync(path.join(directory, file), { force: true });
|
|
152
|
+
}
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
112
156
|
//# sourceMappingURL=index-reader.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import * as fs from 'node:fs';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
@@ -7,13 +7,14 @@ import { findPackageRoot } from '../cli/find-package-root.js';
|
|
|
7
7
|
import { projectAiwgPath, projectControlPath } from '../config/project-artifacts.js';
|
|
8
8
|
import { getUserStateDir } from '../config/user-state.js';
|
|
9
9
|
import { resolveIndexWorkers } from './index-preparation.js';
|
|
10
|
-
import {
|
|
10
|
+
import { resolveFrameworkIndexRoot } from './framework-index-paths.js';
|
|
11
11
|
import { collectIndexStatus } from './index-status.js';
|
|
12
|
+
import { graphIndexDigest, indexAdapterRegistry, selectIndexAdapters, indexFreshnessSnapshot, indexAdapterDigest, recordIndexVerification } from './index-adapters.js';
|
|
12
13
|
import { getFortemiCoreSyncStatus, syncFortemiCoreIndex } from './fortemi-core-sync.js';
|
|
13
14
|
import { acquireDirectoryLock, DirectoryLockContentionError } from './prebuilt-build-lock.js';
|
|
14
15
|
import { resolveImportExclusions } from '../sessions/import-exclusions.js';
|
|
15
16
|
import { resolveImportLimits } from '../sessions/import-limits.js';
|
|
16
|
-
import {
|
|
17
|
+
import { GRAPH_CONFIGS, getGraphIndexDir, graphBuildOrder, loadWorkspaceGraphs, resolveGraphScanDir, } from './types.js';
|
|
17
18
|
function readJson(file, tolerateMalformed = true) {
|
|
18
19
|
try {
|
|
19
20
|
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
@@ -29,14 +30,6 @@ function writeJson(file, value) {
|
|
|
29
30
|
fs.writeFileSync(temporary, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600 });
|
|
30
31
|
fs.renameSync(temporary, file);
|
|
31
32
|
}
|
|
32
|
-
/** The registry is process-global; reload it per workspace to avoid cross-project leakage. */
|
|
33
|
-
function loadWorkspaceGraphs(workspace) {
|
|
34
|
-
for (const name of Object.keys(GRAPH_CONFIGS))
|
|
35
|
-
delete GRAPH_CONFIGS[name];
|
|
36
|
-
Object.assign(GRAPH_CONFIGS, structuredClone(BUILTIN_GRAPH_CONFIGS));
|
|
37
|
-
loadUserGraphConfigs(workspace);
|
|
38
|
-
loadGlobalGraphConfigs();
|
|
39
|
-
}
|
|
40
33
|
function workspacePaths(options) {
|
|
41
34
|
const cwd = options.cwd ?? process.cwd();
|
|
42
35
|
const found = new Map();
|
|
@@ -124,33 +117,38 @@ function planWorkspaceRefresh(options, workspaces) {
|
|
|
124
117
|
loadWorkspaceGraphs(workspace);
|
|
125
118
|
const graphs = collectIndexStatus(workspace).graphs
|
|
126
119
|
.sort((a, b) => graphBuildOrder(a.name, GRAPH_CONFIGS[a.name]) - graphBuildOrder(b.name, GRAPH_CONFIGS[b.name]) || a.name.localeCompare(b.name));
|
|
127
|
-
|
|
120
|
+
const adapters = indexAdapterRegistry(workspace);
|
|
121
|
+
const selected = selectIndexAdapters(adapters, options.only);
|
|
122
|
+
const includes = (name) => selected.some(adapter => adapter.name === name);
|
|
123
|
+
if (!options.only || options.only === 'all' || options.only === 'graphs' || selected.some(adapter => adapter.group === 'graphs')) {
|
|
128
124
|
for (const graph of graphs) {
|
|
129
|
-
if (
|
|
125
|
+
if (selected.some(adapter => adapter.group === 'graphs' && adapter.graph === graph.name)
|
|
126
|
+
&& (graph.built || graph.defaultBuild || graph.origin === 'registered'
|
|
127
|
+
|| (options.only && options.only !== 'all' && options.only !== 'graphs'))) {
|
|
130
128
|
jobs.push({ kind: 'graph', workspace, graph: graph.name, status: 'planned', wallMs: 0 });
|
|
131
129
|
}
|
|
132
130
|
}
|
|
133
131
|
}
|
|
134
|
-
if (!options.only || options.only === 'caches') {
|
|
132
|
+
if (!options.only || options.only === 'all' || options.only === 'caches' || options.only?.startsWith('caches:')) {
|
|
135
133
|
for (const graph of graphs) {
|
|
136
134
|
// Refresh only local, opted-in caches; never create a new cache from a packaged prebuilt.
|
|
137
|
-
if (fs.existsSync(getFortemiCoreSyncStatus(workspace, graph.name).location)) {
|
|
135
|
+
if (includes(`caches:${graph.name}`) && fs.existsSync(getFortemiCoreSyncStatus(workspace, graph.name).location)) {
|
|
138
136
|
jobs.push({ kind: 'cache', workspace, graph: graph.name, status: 'planned', wallMs: 0 });
|
|
139
137
|
}
|
|
140
138
|
}
|
|
141
139
|
}
|
|
142
|
-
if ((
|
|
140
|
+
if (includes('sessions') && fs.existsSync(path.join(workspace, '.aiwg/sessions/catalog.sqlite'))) {
|
|
143
141
|
jobs.push({ kind: 'sessions', workspace, status: 'planned', wallMs: 0, noManifest: 0 });
|
|
144
142
|
}
|
|
145
143
|
for (const kind of ['runtime', 'issues']) {
|
|
146
|
-
if (
|
|
144
|
+
if (!includes(kind))
|
|
147
145
|
continue;
|
|
148
146
|
if (kind === 'issues' && !fs.existsSync(projectAiwgPath(workspace, 'issues')))
|
|
149
147
|
continue;
|
|
150
148
|
jobs.push({ kind, workspace, status: 'planned', wallMs: 0 });
|
|
151
149
|
}
|
|
152
150
|
}
|
|
153
|
-
if (!options.only || options.only === 'models') {
|
|
151
|
+
if (!options.only || options.only === 'all' || options.only === 'models') {
|
|
154
152
|
jobs.push({ kind: 'models', scope: 'host', status: 'planned', wallMs: 0 });
|
|
155
153
|
}
|
|
156
154
|
return jobs;
|
|
@@ -177,23 +175,6 @@ export async function refreshResourceGate(workspace, live) {
|
|
|
177
175
|
const result = preflight.evaluateDispatchGate(live ?? preflight.readLiveHostResources({ paths: [workspace] }), thresholds);
|
|
178
176
|
return { ok: result.ok, reason: result.failures.map((failure) => failure.reason).join('; ') || undefined };
|
|
179
177
|
}
|
|
180
|
-
async function graphFingerprint(workspace, graph) {
|
|
181
|
-
const files = await collectGraphIndexFiles(workspace, graph);
|
|
182
|
-
// Source import resolution also depends on the compiler/package configuration.
|
|
183
|
-
if (graph === 'source') {
|
|
184
|
-
for (const file of ['tsconfig.json', 'package.json']) {
|
|
185
|
-
if (fs.existsSync(path.join(workspace, file)))
|
|
186
|
-
files.push(path.join(workspace, file));
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
const stats = [...new Set(files)].sort().map(file => {
|
|
190
|
-
const stat = fs.statSync(file);
|
|
191
|
-
return [file, stat.mtimeMs, stat.ctimeMs, stat.size];
|
|
192
|
-
});
|
|
193
|
-
return createHash('sha256').update(JSON.stringify([
|
|
194
|
-
INDEX_VERSION, INDEX_EXTRACTOR_VERSION, GRAPH_CONFIGS[graph], resolveGraphBackendType(graph), stats,
|
|
195
|
-
])).digest('hex');
|
|
196
|
-
}
|
|
197
178
|
async function refreshWorkspaceRuntime(workspace, full, runtime) {
|
|
198
179
|
const directory = projectAiwgPath(workspace, 'smiths', 'toolsmith');
|
|
199
180
|
const output = path.join(directory, 'runtime.json');
|
|
@@ -237,34 +218,54 @@ async function refreshWorkspaceRuntime(workspace, full, runtime) {
|
|
|
237
218
|
async function executeJob(job, options, aliases, runtime) {
|
|
238
219
|
const workspace = job.workspace ?? process.env.HOME ?? homedir();
|
|
239
220
|
if (job.kind === 'graph') {
|
|
221
|
+
const graphStart = Date.now();
|
|
240
222
|
const graph = job.graph;
|
|
241
223
|
const config = GRAPH_CONFIGS[graph];
|
|
242
|
-
|
|
224
|
+
const sourceWorkspace = graph === 'framework' ? resolveFrameworkIndexRoot(workspace) : workspace;
|
|
225
|
+
if (!config.scanDirs.some(dir => fs.existsSync(resolveGraphScanDir(sourceWorkspace, dir)))) {
|
|
243
226
|
job.status = 'skipped';
|
|
244
227
|
job.reason = 'scan directories missing';
|
|
245
228
|
return;
|
|
246
229
|
}
|
|
247
230
|
const directory = getGraphIndexDir(workspace, graph);
|
|
248
231
|
const markerPath = path.join(directory, 'refresh-state.json');
|
|
232
|
+
const fingerprint = await graphIndexDigest(sourceWorkspace, graph);
|
|
249
233
|
const marker = readJson(markerPath);
|
|
250
234
|
const metadata = readJson(path.join(directory, 'metadata.json'));
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
235
|
+
const adapter = indexAdapterRegistry(workspace).find(item => item.name === graph);
|
|
236
|
+
if (!options.full && marker?.fingerprint === fingerprint && marker.builtAt === metadata?.builtAt
|
|
237
|
+
&& indexFreshnessSnapshot(adapter, workspace).pendingWork === 0) {
|
|
238
|
+
const release = await acquireDirectoryLock(`${directory}.build.lock`, {
|
|
239
|
+
timeoutMs: options.lockWaitMs ?? 0, reclaimDeadOwner: true,
|
|
240
|
+
});
|
|
241
|
+
try {
|
|
242
|
+
const current = await graphIndexDigest(sourceWorkspace, graph);
|
|
243
|
+
if (current === fingerprint && indexFreshnessSnapshot(adapter, workspace).pendingWork === 0) {
|
|
244
|
+
recordIndexVerification(adapter, workspace, { before: fingerprint, after: current, wallMs: Date.now() - graphStart });
|
|
245
|
+
job.status = 'skipped';
|
|
246
|
+
job.reason = 'unchanged';
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
finally {
|
|
251
|
+
await release();
|
|
252
|
+
}
|
|
260
253
|
}
|
|
254
|
+
const beforeOutput = outputStamp(path.join(directory, 'metadata.json'));
|
|
261
255
|
const { buildIndex } = await import('./index-builder.js');
|
|
262
|
-
await buildIndex(
|
|
256
|
+
await buildIndex(sourceWorkspace, { graph, force: Boolean(options.full), explicit: false, quiet: true, workers: options.workers, lockWaitMs: options.lockWaitMs ?? 0,
|
|
263
257
|
onDiagnostic: message => (job.diagnostics ??= []).push(message) });
|
|
264
258
|
const built = readJson(path.join(directory, 'metadata.json'));
|
|
265
259
|
if (!built)
|
|
266
260
|
throw new Error(`graph did not produce metadata: ${graph}`);
|
|
267
|
-
|
|
261
|
+
const verification = readJson(path.join(directory, 'freshness.json'));
|
|
262
|
+
if (!options.full && beforeOutput && beforeOutput === outputStamp(path.join(directory, 'metadata.json'))) {
|
|
263
|
+
job.status = 'skipped';
|
|
264
|
+
job.reason = 'unchanged';
|
|
265
|
+
}
|
|
266
|
+
if (!verification?.pendingWork && verification?.lastVerifiedDigest === fingerprint) {
|
|
267
|
+
writeJson(markerPath, { fingerprint, builtAt: built.builtAt });
|
|
268
|
+
}
|
|
268
269
|
}
|
|
269
270
|
else if (job.kind === 'cache') {
|
|
270
271
|
const status = getFortemiCoreSyncStatus(workspace, job.graph);
|
|
@@ -333,7 +334,8 @@ async function executeJob(job, options, aliases, runtime) {
|
|
|
333
334
|
}
|
|
334
335
|
}
|
|
335
336
|
}
|
|
336
|
-
job.status
|
|
337
|
+
if (job.status !== 'skipped')
|
|
338
|
+
job.status = 'ok';
|
|
337
339
|
}
|
|
338
340
|
function outputStamp(file) {
|
|
339
341
|
try {
|
|
@@ -385,6 +387,17 @@ export async function refreshIndexes(options = {}, dependencies = {}) {
|
|
|
385
387
|
.reduce((total, receipt) => total + (receipt.totals.excluded ?? 0), 0), 0),
|
|
386
388
|
wallMs: Date.now() - start,
|
|
387
389
|
};
|
|
390
|
+
report.indices = [];
|
|
391
|
+
for (const workspace of workspaces.keys()) {
|
|
392
|
+
loadWorkspaceGraphs(workspace);
|
|
393
|
+
for (const adapter of selectIndexAdapters(indexAdapterRegistry(workspace), options.only)) {
|
|
394
|
+
report.indices.push({ ...indexFreshnessSnapshot(adapter, workspace), workspace });
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
if (!jobs.length && options.only && report.indices.length && report.indices.every(index => index.status === 'unsupported')) {
|
|
398
|
+
report.status = 'deferred';
|
|
399
|
+
report.reason = 'unsupported';
|
|
400
|
+
}
|
|
388
401
|
return report;
|
|
389
402
|
};
|
|
390
403
|
if (options.dryRun)
|
|
@@ -435,6 +448,8 @@ export async function refreshIndexes(options = {}, dependencies = {}) {
|
|
|
435
448
|
continue;
|
|
436
449
|
}
|
|
437
450
|
const jobStart = Date.now();
|
|
451
|
+
let adapter;
|
|
452
|
+
let beforeDigest;
|
|
438
453
|
try {
|
|
439
454
|
const gateWorkspace = job.workspace ?? workspaces.keys().next().value ?? options.cwd ?? process.cwd();
|
|
440
455
|
const gate = await (dependencies.gate ?? refreshResourceGate)(gateWorkspace);
|
|
@@ -447,6 +462,15 @@ export async function refreshIndexes(options = {}, dependencies = {}) {
|
|
|
447
462
|
}
|
|
448
463
|
if (job.workspace)
|
|
449
464
|
loadWorkspaceGraphs(job.workspace);
|
|
465
|
+
const workspace = job.workspace ?? options.cwd ?? process.cwd();
|
|
466
|
+
adapter = indexAdapterRegistry(workspace).find(item => item.name === (job.kind === 'graph' ? job.graph
|
|
467
|
+
: job.kind === 'cache' ? `caches:${job.graph}` : job.kind));
|
|
468
|
+
if (adapter?.supported && job.kind !== 'graph') {
|
|
469
|
+
try {
|
|
470
|
+
beforeDigest = await indexAdapterDigest(adapter, workspace);
|
|
471
|
+
}
|
|
472
|
+
catch { /* Owner reports unavailable dependencies. */ }
|
|
473
|
+
}
|
|
450
474
|
if (job.kind === 'cache' && jobs.some(other => other.kind === 'graph'
|
|
451
475
|
&& other.workspace === job.workspace && other.graph === job.graph && other.status === 'error')) {
|
|
452
476
|
job.status = 'skipped';
|
|
@@ -471,13 +495,52 @@ export async function refreshIndexes(options = {}, dependencies = {}) {
|
|
|
471
495
|
await executeJob(job, options, aliases, discoverRuntime);
|
|
472
496
|
}
|
|
473
497
|
catch (error) {
|
|
474
|
-
|
|
475
|
-
|
|
498
|
+
if (error instanceof DirectoryLockContentionError) {
|
|
499
|
+
job.status = 'deferred';
|
|
500
|
+
job.reason = 'lock-held';
|
|
501
|
+
report.status = 'deferred';
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
job.status = 'error';
|
|
505
|
+
job.error = error instanceof Error ? error.message : String(error);
|
|
506
|
+
}
|
|
476
507
|
}
|
|
477
508
|
finally {
|
|
478
509
|
job.wallMs = Date.now() - jobStart;
|
|
510
|
+
if (adapter) {
|
|
511
|
+
const workspace = job.workspace ?? options.cwd ?? process.cwd();
|
|
512
|
+
if (adapter.supported && job.kind !== 'graph' && job.status !== 'deferred') {
|
|
513
|
+
try {
|
|
514
|
+
let after;
|
|
515
|
+
let probeError;
|
|
516
|
+
try {
|
|
517
|
+
after = await indexAdapterDigest(adapter, workspace);
|
|
518
|
+
}
|
|
519
|
+
catch (error) {
|
|
520
|
+
probeError = String(error);
|
|
521
|
+
}
|
|
522
|
+
if (job.kind === 'runtime' && job.status === 'ok')
|
|
523
|
+
beforeDigest = after;
|
|
524
|
+
const partial = job.reason && job.reason !== 'unchanged';
|
|
525
|
+
job.freshness = recordIndexVerification(adapter, workspace, { before: beforeDigest, after,
|
|
526
|
+
error: job.error ?? probeError, pendingWork: partial ? 1 : 0, wallMs: job.wallMs });
|
|
527
|
+
}
|
|
528
|
+
catch (error) {
|
|
529
|
+
job.freshness = { ...indexFreshnessSnapshot(adapter, workspace), status: 'degraded',
|
|
530
|
+
pendingWork: 1, lastError: String(error) };
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
else
|
|
534
|
+
job.freshness = indexFreshnessSnapshot(adapter, workspace);
|
|
535
|
+
if (job.freshness.pendingWork && !job.error && job.status !== 'deferred' && job.kind === 'graph'
|
|
536
|
+
&& job.reason !== 'scan directories missing') {
|
|
537
|
+
job.status = 'deferred';
|
|
538
|
+
job.reason = 'inputs changed during build';
|
|
539
|
+
report.status = 'deferred';
|
|
540
|
+
}
|
|
541
|
+
}
|
|
479
542
|
}
|
|
480
|
-
if (job.status !== 'error' && job.reason !== 'graph failed'
|
|
543
|
+
if (job.status !== 'error' && job.status !== 'deferred' && job.reason !== 'graph failed'
|
|
481
544
|
&& job.reason !== 'no authorized discovery manifest')
|
|
482
545
|
checkpoint.completed.push(key);
|
|
483
546
|
writeJson(checkpointPath, checkpoint);
|
|
@@ -534,10 +597,6 @@ export async function runIndexRefresh(args, cwd = process.cwd(), signal) {
|
|
|
534
597
|
else if (flag === '--exclude')
|
|
535
598
|
(options.exclude ??= []).push(value);
|
|
536
599
|
else if (flag === '--only') {
|
|
537
|
-
if (value !== 'graphs' && value !== 'sessions' && value !== 'caches'
|
|
538
|
-
&& value !== 'runtime' && value !== 'models' && value !== 'issues') {
|
|
539
|
-
throw new Error('--only must be graphs, sessions, caches, runtime, models, or issues');
|
|
540
|
-
}
|
|
541
600
|
options.only = value;
|
|
542
601
|
}
|
|
543
602
|
else {
|
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import * as fs from 'node:fs';
|
|
20
20
|
import * as path from 'node:path';
|
|
21
|
-
import { GRAPH_CONFIGS, BUILTIN_GRAPH_CONFIGS, getGraphIndexDir, getProjectIndexRoot,
|
|
21
|
+
import { GRAPH_CONFIGS, BUILTIN_GRAPH_CONFIGS, getGraphIndexDir, getProjectIndexRoot, loadWorkspaceGraphs, resolveGraphBackendType, } from './types.js';
|
|
22
22
|
import { getFortemiCoreSyncStatus, } from './fortemi-core-sync.js';
|
|
23
|
+
import { indexAdapterRegistry, indexFreshnessSnapshot, selectIndexAdapters } from './index-adapters.js';
|
|
23
24
|
function readBuiltMeta(indexDir) {
|
|
24
25
|
try {
|
|
25
26
|
const metaPath = path.join(indexDir, 'metadata.json');
|
|
@@ -42,12 +43,11 @@ function readBuiltMeta(indexDir) {
|
|
|
42
43
|
*
|
|
43
44
|
* @param nowMs - injectable clock for deterministic tests (defaults to Date.now()).
|
|
44
45
|
*/
|
|
45
|
-
export function collectIndexStatus(cwd, nowMs) {
|
|
46
|
+
export function collectIndexStatus(cwd, nowMs, only) {
|
|
46
47
|
// Populate the registry from module + operator config, collecting warnings
|
|
47
48
|
// instead of letting malformed defs vanish (#1624).
|
|
48
49
|
const warnings = [];
|
|
49
|
-
|
|
50
|
-
loadGlobalGraphConfigs(warnings);
|
|
50
|
+
loadWorkspaceGraphs(cwd, warnings);
|
|
51
51
|
const now = nowMs ?? Date.now();
|
|
52
52
|
const graphs = [];
|
|
53
53
|
for (const [name, config] of Object.entries(GRAPH_CONFIGS)) {
|
|
@@ -99,6 +99,10 @@ export function collectIndexStatus(cwd, nowMs) {
|
|
|
99
99
|
const built = graphs.filter((g) => g.built).length;
|
|
100
100
|
return {
|
|
101
101
|
graphs,
|
|
102
|
+
indices: selectIndexAdapters(indexAdapterRegistry(cwd), only).map(adapter => ({
|
|
103
|
+
...indexFreshnessSnapshot(adapter, cwd, now), identity: adapter.identity, backend: adapter.backend,
|
|
104
|
+
operation: adapter.operation, roots: adapter.roots(cwd), exclusions: adapter.exclusions, outputPaths: adapter.outputPaths,
|
|
105
|
+
})),
|
|
102
106
|
orphanIndexDirs,
|
|
103
107
|
warnings,
|
|
104
108
|
fortemiCore: getFortemiCoreSyncStatus(cwd),
|
|
@@ -111,9 +115,17 @@ export function collectIndexStatus(cwd, nowMs) {
|
|
|
111
115
|
},
|
|
112
116
|
};
|
|
113
117
|
}
|
|
118
|
+
/** Probe inputs through their owners; the legacy synchronous reader stays available. */
|
|
119
|
+
export async function probeIndexStatus(cwd, only, nowMs = Date.now()) {
|
|
120
|
+
const report = collectIndexStatus(cwd, nowMs, only);
|
|
121
|
+
const adapters = new Map(indexAdapterRegistry(cwd).map(adapter => [adapter.name, adapter]));
|
|
122
|
+
report.indices = await Promise.all(report.indices.map(async (index) => ({ ...index,
|
|
123
|
+
...await adapters.get(index.name).probe(cwd, nowMs) })));
|
|
124
|
+
return report;
|
|
125
|
+
}
|
|
114
126
|
/** Render `aiwg index status` (human table or JSON). */
|
|
115
127
|
export async function showIndexStatus(cwd, opts = {}) {
|
|
116
|
-
const report =
|
|
128
|
+
const report = await probeIndexStatus(cwd, opts.only);
|
|
117
129
|
if (opts.json) {
|
|
118
130
|
console.log(JSON.stringify(report, null, 2));
|
|
119
131
|
return;
|
|
@@ -182,6 +194,9 @@ export async function showIndexStatus(cwd, opts = {}) {
|
|
|
182
194
|
console.log(`⚠ ${missing} registered durable index(es) are not built. Run \`aiwg index build --all\`.`);
|
|
183
195
|
}
|
|
184
196
|
console.log('');
|
|
197
|
+
for (const index of report.indices) {
|
|
198
|
+
console.log(` ${index.name}: ${index.status} (target ${index.policy.targetStaleAfterMs}ms, pending ${index.pendingWork})${index.lastError ? `: ${index.lastError}` : ''}`);
|
|
199
|
+
}
|
|
185
200
|
console.log(`${report.summary.total} graph(s): ${report.summary.built} built, ${missing} missing, ` +
|
|
186
201
|
`${report.summary.orphans} orphan(s), ${report.summary.warnings} warning(s).`);
|
|
187
202
|
}
|