@aiwg/cli 2026.10.4 → 2026.10.6
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 +3 -1
- package/dist/src/artifacts/browser-export.js +1 -0
- package/dist/src/artifacts/citation-parser.js +8 -1
- package/dist/src/artifacts/cli.js +72 -9
- 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/graph-query.js +18 -8
- package/dist/src/artifacts/index-adapters.js +339 -0
- package/dist/src/artifacts/index-builder.js +146 -16
- package/dist/src/artifacts/index-files.js +15 -4
- package/dist/src/artifacts/index-preparation.js +91 -26
- package/dist/src/artifacts/index-reader.js +44 -0
- package/dist/src/artifacts/index-refresh.js +130 -56
- package/dist/src/artifacts/index-status.js +20 -5
- package/dist/src/artifacts/index-worker.mjs +9 -7
- 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/cli/handlers/decision.js +19 -1
- 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/local-executor.js +5 -3
- 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 +40 -6
- package/dist/src/cli/handlers/setup.js +428 -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 +279 -93
- package/dist/src/cli/handlers/workspace.js +3 -1
- package/dist/src/cli/prompt-utils.js +8 -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/native-sandbox-warnings.js +25 -0
- package/dist/src/contributors/validation.js +6 -5
- package/dist/src/decision/admission.js +7 -3
- package/dist/src/decision/benchmark.js +469 -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 +18 -15
- package/dist/src/decision/qualification/load-staged.js +539 -0
- package/dist/src/decision/qualification/load.js +109 -33
- package/dist/src/decision/qualification/runner.js +5 -2
- 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 +233 -0
- package/dist/src/discovery/plan-apply.js +571 -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/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-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/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/mcp/cli.mjs +5 -6
- package/dist/src/mcp/config-file.mjs +6 -2
- package/dist/src/mcp/config-layers.mjs +23 -7
- 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 +17 -4
- 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/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/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 +7 -0
- package/dist/src/models/worker-installation.mjs +169 -37
- package/dist/src/models/wrapper-route.js +1 -1
- package/dist/src/output-modes/registry.js +8 -7
- package/dist/src/plugin/metadata-validator.js +1 -1
- 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 +114 -15
- package/dist/src/sessions/adapters/claude.js +19 -18
- package/dist/src/sessions/adapters/codex.js +33 -19
- 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/batch-contracts.js +1 -1
- package/dist/src/sessions/batch-import.js +202 -2
- package/dist/src/sessions/candidates.js +7 -6
- package/dist/src/sessions/contracts.js +73 -54
- package/dist/src/sessions/coverage-preflight.js +26 -1
- package/dist/src/sessions/output-registration.js +11 -10
- package/dist/src/sessions/policy.js +18 -7
- package/dist/src/sessions/refresh.js +2 -3
- package/dist/src/sessions/repository.js +4 -2
- package/dist/src/sessions/workspace-discovery.js +92 -26
- package/dist/src/smiths/context-pipeline/aiwg-md.js +18 -1
- package/dist/src/smiths/context-pipeline/claude-hook.js +42 -6
- package/dist/src/smiths/context-pipeline/parallelism-section.js +72 -5
- package/dist/src/smiths/context-pipeline/workspace-context.js +106 -10
- package/dist/src/update/checker.d.mts +4 -0
- package/dist/src/update/checker.mjs +14 -0
- 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 +19 -13
- package/tools/agents/providers/claude.mjs +1 -1
- package/tools/agents/providers/codex.mjs +50 -56
- package/tools/agents/providers/copilot.mjs +8 -2
- 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 +7 -13
- package/tools/agents/providers/muse-hooks.mjs +21 -14
- package/tools/agents/providers/muse.mjs +7 -2
- package/tools/agents/providers/omp.mjs +28 -4
- 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 +263 -71
- package/tools/agents/providers/windsurf.mjs +7 -0
- 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/muse-adapter.mjs +12 -2
- 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 +7 -4
- package/tools/ralph-external/session-launcher.mjs +280 -32
- package/tools/skills/deploy-skills-codex.mjs +11 -7
- package/vscode-extension/schemas/aiwg.config.v1.json +11 -1
|
@@ -20,6 +20,7 @@ import path from 'node:path';
|
|
|
20
20
|
import { readFileSync } from 'node:fs';
|
|
21
21
|
import { fileURLToPath } from 'node:url';
|
|
22
22
|
import { GRAPH_CONFIGS, OPERATIONAL_DISCOVERY_TYPES, OPERATIONAL_SHOW_TYPES, isOperationalShowType, loadUserGraphConfigs, loadGlobalGraphConfigs, orderedGraphEntries, } from './types.js';
|
|
23
|
+
import { resolveIndexWorkers } from './index-preparation.js';
|
|
23
24
|
import { SUPPORTED_VIEWS } from './corpus-views/renderers.js';
|
|
24
25
|
import { parseResourceSelector, readVerifiedRegularFile, } from '../resources/web-release.js';
|
|
25
26
|
import { findPackageRoot } from '../cli/find-package-root.js';
|
|
@@ -328,10 +329,12 @@ export function printIndexUsage() {
|
|
|
328
329
|
console.log(' build [--force] [--verbose] [--all] [--scope <dir>] [--graph <name>]');
|
|
329
330
|
console.log(' refresh [--full] [--workspace <path>]... [--root <dir>]...');
|
|
330
331
|
console.log(' [--only graphs|sessions|caches|runtime|models|issues] [--dry-run] [--json] [--lock-wait-ms <n>]');
|
|
332
|
+
console.log(' --only also accepts a registered index name (for example project) or all.');
|
|
331
333
|
console.log(' [--max-record-bytes <n>] [--max-source-bytes <n>]');
|
|
332
334
|
console.log(' Session import defaults: 67108864 bytes per record, 1073741824 bytes (1 GiB) per source; source 0 is unlimited.');
|
|
333
335
|
console.log(' --exclude <id-or-glob> (repeatable): skip session IDs or absolute path globs; adds to sessions.import.exclude and AIWG_SESSIONS_IMPORT_EXCLUDE (comma-separated).');
|
|
334
336
|
console.log(' Import limits: CLI flag > AIWG_SESSIONS_IMPORT_MAX_RECORD_BYTES / AIWG_SESSIONS_IMPORT_MAX_SOURCE_BYTES > workspace config > default.');
|
|
337
|
+
console.log(' build/refresh --index-workers <n>: preparation processes (0 = serial); flag > AIWG_INDEX_WORKERS > automatic CPU/memory limits.');
|
|
335
338
|
console.log(' sync [--backend fortemi-core] [--graph <name> | --all] [--repo <name>]');
|
|
336
339
|
console.log(' [--privacy private|sanitized|public] [--generated-at <iso>] [--json]');
|
|
337
340
|
console.log(' --graph <name> Target a specific graph (framework, project, codebase, source, user, or user-defined)');
|
|
@@ -503,6 +506,7 @@ async function handleBuild(args) {
|
|
|
503
506
|
console.log('Usage: aiwg index build [options]');
|
|
504
507
|
console.log('');
|
|
505
508
|
console.log('Options:');
|
|
509
|
+
console.log(' --index-workers <n> Preparation processes (0 = serial); overrides AIWG_INDEX_WORKERS');
|
|
506
510
|
console.log(' --force Full rebuild (ignore checksums, re-index everything)');
|
|
507
511
|
console.log(' --verbose Show detailed progress during indexing');
|
|
508
512
|
console.log(' --all Build all known graphs (including user-defined)');
|
|
@@ -530,6 +534,15 @@ async function handleBuild(args) {
|
|
|
530
534
|
console.log(' aiwg index sync --all');
|
|
531
535
|
return;
|
|
532
536
|
}
|
|
537
|
+
let workers;
|
|
538
|
+
try {
|
|
539
|
+
workers = resolveIndexWorkers(parseFlagValue(args, '--index-workers', 'Error: --index-workers requires a value'));
|
|
540
|
+
}
|
|
541
|
+
catch (error) {
|
|
542
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
543
|
+
process.exitCode = 1;
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
533
546
|
// Dynamic import to keep the CLI router lightweight
|
|
534
547
|
const { buildIndex } = await import('./index-builder.js');
|
|
535
548
|
const cwd = process.cwd();
|
|
@@ -554,7 +567,7 @@ async function handleBuild(args) {
|
|
|
554
567
|
// --graph X: build the JSON graph if X is one; otherwise X may be a
|
|
555
568
|
// research-corpus markdown view, rendered below.
|
|
556
569
|
if (graph in GRAPH_CONFIGS) {
|
|
557
|
-
await buildIndex(cwd, { force, verbose, scope, includeIgnored, graph, explicit: true });
|
|
570
|
+
await buildIndex(cwd, { force, verbose, scope, includeIgnored, workers, graph, explicit: true });
|
|
558
571
|
jsonBuilt = true;
|
|
559
572
|
builtGraphs.add(graph);
|
|
560
573
|
}
|
|
@@ -562,7 +575,7 @@ async function handleBuild(args) {
|
|
|
562
575
|
else if (all) {
|
|
563
576
|
// Build all known graphs — user asked for everything, but don't hard-error on missing dirs
|
|
564
577
|
for (const [name] of orderedGraphEntries(Object.entries(GRAPH_CONFIGS))) {
|
|
565
|
-
await buildIndex(cwd, { force, verbose, includeIgnored, graph: name, explicit: false });
|
|
578
|
+
await buildIndex(cwd, { force, verbose, includeIgnored, workers, graph: name, explicit: false });
|
|
566
579
|
builtGraphs.add(name);
|
|
567
580
|
}
|
|
568
581
|
jsonBuilt = true;
|
|
@@ -571,7 +584,7 @@ async function handleBuild(args) {
|
|
|
571
584
|
// Default: build graphs with defaultBuild=true; skip gracefully if their dirs don't exist
|
|
572
585
|
for (const [name, config] of orderedGraphEntries(Object.entries(GRAPH_CONFIGS))) {
|
|
573
586
|
if (config.defaultBuild) {
|
|
574
|
-
await buildIndex(cwd, { force, verbose, includeIgnored, scope: name === Object.keys(GRAPH_CONFIGS)[0] ? scope : undefined, graph: name, explicit: false });
|
|
587
|
+
await buildIndex(cwd, { force, verbose, includeIgnored, workers, scope: name === Object.keys(GRAPH_CONFIGS)[0] ? scope : undefined, graph: name, explicit: false });
|
|
575
588
|
builtGraphs.add(name);
|
|
576
589
|
}
|
|
577
590
|
}
|
|
@@ -1073,6 +1086,21 @@ async function handleExport(args) {
|
|
|
1073
1086
|
process.exit(1);
|
|
1074
1087
|
}
|
|
1075
1088
|
}
|
|
1089
|
+
function warnSyncTextQuality(manifest) {
|
|
1090
|
+
const quality = manifest.text_quality;
|
|
1091
|
+
if (!quality?.degenerate)
|
|
1092
|
+
return;
|
|
1093
|
+
const config = GRAPH_CONFIGS[manifest.graph];
|
|
1094
|
+
const source = config
|
|
1095
|
+
? ` Source: ${config.scanDirs.join(', ')} (nodeStrategy: ${config.nodeStrategy ?? 'default'}).`
|
|
1096
|
+
: '';
|
|
1097
|
+
if (manifest.item_count === 0) {
|
|
1098
|
+
console.warn(`Warning: graph '${manifest.graph}' contains no indexed items; this graph cannot return results.${source}`);
|
|
1099
|
+
return;
|
|
1100
|
+
}
|
|
1101
|
+
const percent = Math.round(quality.short_text_count / manifest.item_count * 100);
|
|
1102
|
+
console.warn(`Warning: graph '${manifest.graph}': ${quality.short_text_count}/${manifest.item_count} items (${percent}%) have <${quality.short_text_threshold_chars} chars of indexed text; ${quality.filename_title_count} have a filename as title. This graph may return poor results. Check source content and extracted text sidecars.${source}`);
|
|
1103
|
+
}
|
|
1076
1104
|
/**
|
|
1077
1105
|
* Handle 'index sync' command
|
|
1078
1106
|
*/
|
|
@@ -1142,6 +1170,7 @@ async function handleSync(args) {
|
|
|
1142
1170
|
console.log(`Fortemi Core sync: ${manifests.length} graph(s) succeeded, ${failures.length} failed`);
|
|
1143
1171
|
for (const manifest of manifests) {
|
|
1144
1172
|
console.log(` ${manifest.graph}: ${manifest.status}, ${manifest.item_count} item(s) → ${manifest.export_path}`);
|
|
1173
|
+
warnSyncTextQuality(manifest);
|
|
1145
1174
|
}
|
|
1146
1175
|
for (const failure of failures) {
|
|
1147
1176
|
console.error(` ${failure.graph}: failed — ${failure.error}`);
|
|
@@ -1157,6 +1186,7 @@ async function handleSync(args) {
|
|
|
1157
1186
|
return;
|
|
1158
1187
|
}
|
|
1159
1188
|
console.log(`Fortemi Core ${manifest.status}: ${manifest.item_count} item(s) → ${manifest.export_path}`);
|
|
1189
|
+
warnSyncTextQuality(manifest);
|
|
1160
1190
|
}
|
|
1161
1191
|
catch (err) {
|
|
1162
1192
|
console.error('Error: ' + (err instanceof Error ? err.message : String(err)));
|
|
@@ -1288,7 +1318,7 @@ async function handleStats(args) {
|
|
|
1288
1318
|
*/
|
|
1289
1319
|
async function handleStatus(args) {
|
|
1290
1320
|
if (args.includes('--help') || args.includes('-h')) {
|
|
1291
|
-
console.log('Usage: aiwg index status [--json]');
|
|
1321
|
+
console.log('Usage: aiwg index status [--only <name|all>] [--json]');
|
|
1292
1322
|
console.log(' aiwg index list [--json] (alias)');
|
|
1293
1323
|
console.log('');
|
|
1294
1324
|
console.log('Enumerate every registered index graph (built-in + module + operator)');
|
|
@@ -1302,7 +1332,10 @@ async function handleStatus(args) {
|
|
|
1302
1332
|
return;
|
|
1303
1333
|
}
|
|
1304
1334
|
const { showIndexStatus } = await import('./index-status.js');
|
|
1305
|
-
|
|
1335
|
+
const onlyAt = args.indexOf('--only');
|
|
1336
|
+
if (onlyAt >= 0 && (!args[onlyAt + 1] || args[onlyAt + 1].startsWith('--')))
|
|
1337
|
+
throw new Error('--only requires an index name');
|
|
1338
|
+
await showIndexStatus(process.cwd(), { json: args.includes('--json'), only: onlyAt >= 0 ? args[onlyAt + 1] : undefined });
|
|
1306
1339
|
}
|
|
1307
1340
|
/**
|
|
1308
1341
|
* Handle 'index neighbors' command
|
|
@@ -1510,7 +1543,7 @@ async function handleDiscover(args) {
|
|
|
1510
1543
|
});
|
|
1511
1544
|
}
|
|
1512
1545
|
/**
|
|
1513
|
-
* Handle 'index show' command —
|
|
1546
|
+
* Handle 'index show' command — show the metadata card of a specific
|
|
1514
1547
|
* artifact by type and name.
|
|
1515
1548
|
*
|
|
1516
1549
|
* Shape (#1218):
|
|
@@ -1519,9 +1552,31 @@ async function handleDiscover(args) {
|
|
|
1519
1552
|
* Type is positional (not a flag) so the verb reads as
|
|
1520
1553
|
* "show <kind> <name>". `<type>` is one of the operational show types.
|
|
1521
1554
|
*
|
|
1522
|
-
* Companion to `discover`: where discover ranks candidates, show
|
|
1523
|
-
*
|
|
1555
|
+
* Companion to `discover`: where discover ranks candidates, show returns
|
|
1556
|
+
* a metadata card with section/body drill-ins so consumers don't need to navigate the filesystem.
|
|
1524
1557
|
*/
|
|
1558
|
+
const SHOW_FLAGS = new Set(['--json', '--first', '--bound-rule-bodies', '--graph', '--backend', '--resource-source',
|
|
1559
|
+
'--aiwg-version', '--offline', '--body', '--section', '--rules', '--with-rule-bodies', '--resources', '--resource',
|
|
1560
|
+
'--help']);
|
|
1561
|
+
// Section headings can themselves start with `--` (e.g. "--max-iterations (default: 10)"), and the card
|
|
1562
|
+
// tells agents to pass them verbatim. Only a missing value or another show flag counts as "no value".
|
|
1563
|
+
function showFlagValue(flags, index) {
|
|
1564
|
+
const value = flags[index + 1];
|
|
1565
|
+
if (!value || SHOW_FLAGS.has(value.split('=')[0]))
|
|
1566
|
+
throw new Error(`${flags[index]} requires a value`);
|
|
1567
|
+
return value;
|
|
1568
|
+
}
|
|
1569
|
+
/** Values for a repeatable value flag, accepting both `--flag value` and `--flag=value`. */
|
|
1570
|
+
function showFlagValues(flags, name) {
|
|
1571
|
+
const values = [];
|
|
1572
|
+
for (let i = 0; i < flags.length; i++) {
|
|
1573
|
+
if (flags[i] === name)
|
|
1574
|
+
values.push(showFlagValue(flags, i));
|
|
1575
|
+
else if (flags[i].startsWith(`${name}=`))
|
|
1576
|
+
values.push(flags[i].slice(name.length + 1));
|
|
1577
|
+
}
|
|
1578
|
+
return values;
|
|
1579
|
+
}
|
|
1525
1580
|
async function handleShow(args) {
|
|
1526
1581
|
const { showArtifact, showMetadata } = await import('./query-engine.js');
|
|
1527
1582
|
const cwd = process.cwd();
|
|
@@ -1555,9 +1610,11 @@ async function handleShow(args) {
|
|
|
1555
1610
|
' aiwg show command discover',
|
|
1556
1611
|
' aiwg show skill intake-wizard --resource-source web --aiwg-version stable',
|
|
1557
1612
|
'',
|
|
1613
|
+
'Default: metadata card. --body restores full output; --section <heading> is repeatable.',
|
|
1614
|
+
'--rules [--with-rule-bodies] | --resources | --resource <path>',
|
|
1558
1615
|
'Bound rules: summaries and show pointers are appended for bound skills, agents, and flows.',
|
|
1559
1616
|
'Fetch and follow every required_rule_checks entry before starting governed work; summaries do not replace full rules.',
|
|
1560
|
-
'Use --
|
|
1617
|
+
'Use --rules --with-rule-bodies to include their full text (legacy alias: --bound-rule-bodies).',
|
|
1561
1618
|
'',
|
|
1562
1619
|
'Tip: use `aiwg discover "<phrase>" --json` first to find the stable id.',
|
|
1563
1620
|
].join('\n');
|
|
@@ -1623,6 +1680,12 @@ async function handleShow(args) {
|
|
|
1623
1680
|
const params = {
|
|
1624
1681
|
name,
|
|
1625
1682
|
boundRuleBodies: flags.includes('--bound-rule-bodies'),
|
|
1683
|
+
body: flags.includes('--body'),
|
|
1684
|
+
sections: showFlagValues(flags, '--section'),
|
|
1685
|
+
rules: flags.includes('--rules'),
|
|
1686
|
+
withRuleBodies: flags.includes('--with-rule-bodies'),
|
|
1687
|
+
resources: flags.includes('--resources'),
|
|
1688
|
+
resource: showFlagValues(flags, '--resource')[0],
|
|
1626
1689
|
typeFilter: type ? [type] : undefined,
|
|
1627
1690
|
json,
|
|
1628
1691
|
first,
|
|
@@ -244,6 +244,8 @@ function entryFromRecord(record) {
|
|
|
244
244
|
const indexedScript = indexedFrontmatter.aiwg_script;
|
|
245
245
|
return {
|
|
246
246
|
path: record.source.path,
|
|
247
|
+
...(indexedFrontmatter.aiwg_memory_record && typeof indexedFrontmatter.aiwg_memory_record === 'object'
|
|
248
|
+
? { memoryRecord: indexedFrontmatter.aiwg_memory_record } : {}),
|
|
247
249
|
type: artifactTypeFromRecord(record),
|
|
248
250
|
kind: typeof indexedFrontmatter.aiwg_kind === "string"
|
|
249
251
|
? indexedFrontmatter.aiwg_kind
|
|
@@ -5,9 +5,9 @@ import { fileURLToPath } from "node:url";
|
|
|
5
5
|
import { parse as parseYaml } from "yaml";
|
|
6
6
|
import { GRAPH_CONFIGS, getProjectIndexRoot, loadGlobalGraphConfigs } from "./types.js";
|
|
7
7
|
import { buildAiwgFortemiIndexExport, } from "./browser-export.js";
|
|
8
|
-
import { loadGraphIndexFile } from "./index-reader.js";
|
|
8
|
+
import { loadGraphIndexFile, publishIndexFiles } from "./index-reader.js";
|
|
9
9
|
import { getFrameworkIndexBaseDir } from './framework-index-paths.js';
|
|
10
|
-
function
|
|
10
|
+
export function getFortemiCoreIndexDir(cwd, graph) {
|
|
11
11
|
loadGlobalGraphConfigs();
|
|
12
12
|
if (graph === 'framework')
|
|
13
13
|
return path.join(getFrameworkIndexBaseDir(cwd), 'fortemi-core', graph);
|
|
@@ -180,14 +180,15 @@ function writeExport(file, exported, maxChars) {
|
|
|
180
180
|
}
|
|
181
181
|
export function syncFortemiCoreIndex(cwd, options = {}) {
|
|
182
182
|
const graph = options.graph ?? "project";
|
|
183
|
-
const dir =
|
|
183
|
+
const dir = getFortemiCoreIndexDir(cwd, graph);
|
|
184
184
|
const exportPath = path.join(dir, "aiwg-fortemi-index-v2.json");
|
|
185
185
|
const manifestPath = path.join(dir, "manifest.json");
|
|
186
186
|
const maxChars = options.maxChunkChars ?? 64 * 1024;
|
|
187
187
|
if (!Number.isSafeInteger(maxChars) || maxChars < 64)
|
|
188
188
|
throw new Error("maxChunkChars must be an integer of at least 64");
|
|
189
189
|
fs.mkdirSync(dir, { recursive: true });
|
|
190
|
-
const
|
|
190
|
+
const staging = fs.mkdtempSync(path.join(dir, ".sync-"));
|
|
191
|
+
const temporaryPath = path.join(staging, `.export-${randomUUID()}.tmp`);
|
|
191
192
|
const previous = readManifest(manifestPath);
|
|
192
193
|
const sourceBuiltAt = sourceIndexBuiltAt(cwd, graph);
|
|
193
194
|
const buildExport = (generatedAt) => {
|
|
@@ -200,10 +201,25 @@ export function syncFortemiCoreIndex(cwd, options = {}) {
|
|
|
200
201
|
});
|
|
201
202
|
const checksum = writeExport(temporaryPath, exported, maxChars);
|
|
202
203
|
const recordsWithConcepts = exported.items.filter((item) => (item.skos_concepts?.length ?? 0) > 0).length;
|
|
204
|
+
const shortTextThreshold = 200;
|
|
205
|
+
let shortTextCount = 0;
|
|
206
|
+
let filenameTitleCount = 0;
|
|
207
|
+
for (const item of exported.items) {
|
|
208
|
+
if (item.text.trim().length < shortTextThreshold)
|
|
209
|
+
shortTextCount++;
|
|
210
|
+
if (item.title.trim() === path.posix.basename(item.source.path))
|
|
211
|
+
filenameTitleCount++;
|
|
212
|
+
}
|
|
203
213
|
return {
|
|
204
214
|
generatedAt,
|
|
205
215
|
checksum,
|
|
206
216
|
itemCount: exported.items.length,
|
|
217
|
+
textQuality: {
|
|
218
|
+
short_text_threshold_chars: shortTextThreshold,
|
|
219
|
+
short_text_count: shortTextCount,
|
|
220
|
+
filename_title_count: filenameTitleCount,
|
|
221
|
+
degenerate: exported.items.length === 0 || shortTextCount / exported.items.length >= 0.8,
|
|
222
|
+
},
|
|
207
223
|
skosCoverage: {
|
|
208
224
|
records_with_concepts: recordsWithConcepts,
|
|
209
225
|
total_records: exported.items.length,
|
|
@@ -228,7 +244,7 @@ export function syncFortemiCoreIndex(cwd, options = {}) {
|
|
|
228
244
|
}
|
|
229
245
|
}
|
|
230
246
|
}
|
|
231
|
-
fs.renameSync(temporaryPath, exportPath);
|
|
247
|
+
fs.renameSync(temporaryPath, path.join(staging, path.basename(exportPath)));
|
|
232
248
|
const manifest = {
|
|
233
249
|
schema_version: "aiwg.fortemi.core-sync.v1",
|
|
234
250
|
backend: "fortemi-core",
|
|
@@ -238,19 +254,21 @@ export function syncFortemiCoreIndex(cwd, options = {}) {
|
|
|
238
254
|
export_schema_version: "aiwg.fortemi.index.export.v2",
|
|
239
255
|
export_checksum: built.checksum,
|
|
240
256
|
item_count: built.itemCount,
|
|
257
|
+
text_quality: built.textQuality,
|
|
241
258
|
skos_coverage: built.skosCoverage,
|
|
242
259
|
status,
|
|
243
260
|
source_index_built_at: sourceBuiltAt,
|
|
244
261
|
};
|
|
245
|
-
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
|
|
262
|
+
fs.writeFileSync(path.join(staging, path.basename(manifestPath)), JSON.stringify(manifest, null, 2) + "\n", "utf-8");
|
|
263
|
+
publishIndexFiles(staging, dir);
|
|
246
264
|
return manifest;
|
|
247
265
|
}
|
|
248
266
|
finally {
|
|
249
|
-
fs.rmSync(
|
|
267
|
+
fs.rmSync(staging, { recursive: true, force: true });
|
|
250
268
|
}
|
|
251
269
|
}
|
|
252
270
|
export function getFortemiCoreSyncStatus(cwd, graph = "project") {
|
|
253
|
-
const dir =
|
|
271
|
+
const dir = getFortemiCoreIndexDir(cwd, graph);
|
|
254
272
|
const manifestPath = path.join(dir, "manifest.json");
|
|
255
273
|
const exportPath = path.join(dir, "aiwg-fortemi-index-v2.json");
|
|
256
274
|
const { manifest, reason: manifestReadReason } = readManifestResult(manifestPath);
|
|
@@ -9,8 +9,17 @@
|
|
|
9
9
|
* @tests @test/unit/artifacts/graph-query.test.ts
|
|
10
10
|
*/
|
|
11
11
|
import { normalizeEdges } from './types.js';
|
|
12
|
-
import { buildFortemiCoreDependencyGraph } from './fortemi-core-query-adapter.js';
|
|
12
|
+
import { buildFortemiCoreDependencyGraph, loadFortemiCoreMetadataEntries } from './fortemi-core-query-adapter.js';
|
|
13
13
|
import { closeGraphBackend, openGraphBackend } from './backend-runtime.js';
|
|
14
|
+
import { loadGraphIndexFile } from './index-reader.js';
|
|
15
|
+
import { isOrdinaryMemoryEntry } from './query-engine.js';
|
|
16
|
+
function graphMemoryMetadata(cwd, graph, backend) {
|
|
17
|
+
const local = loadGraphIndexFile(cwd, 'metadata.json', graph)?.entries ?? {};
|
|
18
|
+
if (backend === 'fortemi-core') {
|
|
19
|
+
return { ...Object.fromEntries(loadFortemiCoreMetadataEntries(cwd, graph).entries.map(entry => [entry.path, entry])), ...local };
|
|
20
|
+
}
|
|
21
|
+
return local;
|
|
22
|
+
}
|
|
14
23
|
/**
|
|
15
24
|
* Get neighbors of a node in a dependency graph.
|
|
16
25
|
*
|
|
@@ -20,15 +29,15 @@ import { closeGraphBackend, openGraphBackend } from './backend-runtime.js';
|
|
|
20
29
|
* @param edgeType - Optional filter by edge type
|
|
21
30
|
* @returns Array of neighbor paths
|
|
22
31
|
*/
|
|
23
|
-
export function getNeighbors(graph, node, direction = 'both', edgeType) {
|
|
32
|
+
export function getNeighbors(graph, node, direction = 'both', edgeType, metadata = {}) {
|
|
24
33
|
const entry = graph[node];
|
|
25
|
-
if (!entry)
|
|
34
|
+
if (!entry || (metadata[node] && !isOrdinaryMemoryEntry(metadata[node])))
|
|
26
35
|
return [];
|
|
27
36
|
const results = new Set();
|
|
28
37
|
if (direction === 'in' || direction === 'both') {
|
|
29
38
|
const edges = normalizeEdges(entry.upstream);
|
|
30
39
|
for (const edge of edges) {
|
|
31
|
-
if (!edgeType || edge.type === edgeType) {
|
|
40
|
+
if ((!edgeType || edge.type === edgeType) && (!metadata[edge.path] || isOrdinaryMemoryEntry(metadata[edge.path]))) {
|
|
32
41
|
results.add(edge.path);
|
|
33
42
|
}
|
|
34
43
|
}
|
|
@@ -36,7 +45,7 @@ export function getNeighbors(graph, node, direction = 'both', edgeType) {
|
|
|
36
45
|
if (direction === 'out' || direction === 'both') {
|
|
37
46
|
const edges = normalizeEdges(entry.downstream);
|
|
38
47
|
for (const edge of edges) {
|
|
39
|
-
if (!edgeType || edge.type === edgeType) {
|
|
48
|
+
if ((!edgeType || edge.type === edgeType) && (!metadata[edge.path] || isOrdinaryMemoryEntry(metadata[edge.path]))) {
|
|
40
49
|
results.add(edge.path);
|
|
41
50
|
}
|
|
42
51
|
}
|
|
@@ -134,7 +143,7 @@ export async function showNeighbors(cwd, options) {
|
|
|
134
143
|
}
|
|
135
144
|
process.exit(1);
|
|
136
145
|
}
|
|
137
|
-
const neighbors = getNeighbors(graph, resolved, direction, edgeType);
|
|
146
|
+
const neighbors = getNeighbors(graph, resolved, direction, edgeType, graphMemoryMetadata(cwd, graphType, backend));
|
|
138
147
|
if (json) {
|
|
139
148
|
console.log(JSON.stringify({
|
|
140
149
|
graph: graphType,
|
|
@@ -208,8 +217,9 @@ export async function executeSetQuery(cwd, options) {
|
|
|
208
217
|
console.error(`Error: Node '${nodeB}' not found in graph '${graphType}'.`);
|
|
209
218
|
process.exit(1);
|
|
210
219
|
}
|
|
211
|
-
const
|
|
212
|
-
const
|
|
220
|
+
const metadata = graphMemoryMetadata(cwd, graphType, backend);
|
|
221
|
+
const neighborsA = getNeighbors(graph, resolvedA, direction, edgeType, metadata);
|
|
222
|
+
const neighborsB = getNeighbors(graph, resolvedB, direction, edgeType, metadata);
|
|
213
223
|
let result;
|
|
214
224
|
switch (op) {
|
|
215
225
|
case 'intersection':
|