@aiwg/cli 2026.10.3 → 2026.10.5
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/README.md +2 -2
- package/agentic/code/providers/model-capabilities.v1.json +96 -4
- package/bin/aiwg.mjs +50 -27
- package/dist/src/agents/grounding/knowledge-base.js +54 -6
- package/dist/src/artifacts/browser-export.js +6 -0
- package/dist/src/artifacts/checksum-manifest.js +1 -0
- package/dist/src/artifacts/citation-parser.js +173 -92
- package/dist/src/artifacts/citation-table-schema.js +59 -0
- package/dist/src/artifacts/cli.js +69 -18
- package/dist/src/artifacts/corpus-tools/snapshot.js +1 -1
- package/dist/src/artifacts/corpus-tools/vision-extract.js +2 -0
- package/dist/src/artifacts/corpus-views/ref-parser.js +3 -1
- package/dist/src/artifacts/corpus-views/renderers.js +3 -3
- package/dist/src/artifacts/discovery-eval.js +6 -4
- package/dist/src/artifacts/fortemi-core-query-adapter.js +36 -3
- package/dist/src/artifacts/fortemi-core-sync.js +166 -40
- package/dist/src/artifacts/framework-capabilities.js +171 -0
- package/dist/src/artifacts/framework-index-paths.js +73 -0
- package/dist/src/artifacts/framework-source-digest.js +75 -0
- package/dist/src/artifacts/index-builder.js +286 -131
- package/dist/src/artifacts/index-files.js +132 -18
- package/dist/src/artifacts/index-preparation.js +130 -0
- package/dist/src/artifacts/index-refresh.js +591 -0
- package/dist/src/artifacts/index-worker.mjs +11 -0
- package/dist/src/artifacts/prebuilt-build-lock.js +47 -4
- package/dist/src/artifacts/prebuilt-deployment.js +46 -0
- package/dist/src/artifacts/prebuilt-relations.js +80 -0
- package/dist/src/artifacts/query-engine.js +410 -88
- package/dist/src/artifacts/relations-builder.js +168 -0
- package/dist/src/artifacts/relations.js +148 -0
- package/dist/src/artifacts/stats.js +5 -2
- package/dist/src/artifacts/types.js +30 -10
- package/dist/src/artifacts/watcher.js +1 -1
- package/dist/src/auth/credential-store.js +2 -1
- package/dist/src/catalog/cli.d.mts +5 -0
- package/dist/src/channel/manager.d.mts +20 -0
- package/dist/src/channel/manager.mjs +19 -2
- package/dist/src/cli/command-log.js +2 -3
- package/dist/src/cli/handlers/artifacts.js +3 -0
- package/dist/src/cli/handlers/auth.js +3 -0
- package/dist/src/cli/handlers/decision.js +19 -12
- package/dist/src/cli/handlers/diagnose.js +4 -3
- package/dist/src/cli/handlers/effect.js +4 -2
- package/dist/src/cli/handlers/evidence.js +3 -0
- package/dist/src/cli/handlers/help.js +1 -0
- package/dist/src/cli/handlers/index.js +3 -1
- package/dist/src/cli/handlers/init.js +4 -1
- package/dist/src/cli/handlers/lint.js +5 -0
- package/dist/src/cli/handlers/models.js +104 -8
- package/dist/src/cli/handlers/ralph-launcher.js +2 -0
- package/dist/src/cli/handlers/refresh.js +12 -0
- package/dist/src/cli/handlers/resource-versions.js +3 -0
- package/dist/src/cli/handlers/rules.js +195 -0
- package/dist/src/cli/handlers/run.js +4 -0
- package/dist/src/cli/handlers/runtime-info.js +1 -2
- package/dist/src/cli/handlers/script-runner.js +3 -2
- package/dist/src/cli/handlers/session.js +19 -9
- package/dist/src/cli/handlers/sessions.js +137 -43
- package/dist/src/cli/handlers/setup-manifest.js +39 -44
- package/dist/src/cli/handlers/setup.js +41 -0
- package/dist/src/cli/handlers/steward.js +11 -0
- package/dist/src/cli/handlers/subcommands.js +57 -2
- package/dist/src/cli/handlers/uhp.js +3 -0
- package/dist/src/cli/handlers/use.js +294 -55
- package/dist/src/cli/handlers/utilities.js +26 -10
- package/dist/src/cli/handlers/version.js +8 -0
- package/dist/src/cli/router.js +15 -1
- package/dist/src/cli/services/deployment-verification.js +19 -9
- package/dist/src/cli/services/provider-prepare-coordinator.js +24 -0
- package/dist/src/cli/skill-usage.js +2 -3
- package/dist/src/config/aiwg-config.js +87 -37
- package/dist/src/config/cli.js +111 -5
- package/dist/src/config/decision-config.js +106 -0
- package/dist/src/config/dispatch-thresholds-runtime.d.mts +8 -0
- package/dist/src/config/gitignore.js +50 -0
- package/dist/src/config/index-graph-overrides.js +36 -0
- package/dist/src/config/project-artifacts-health.d.mts +37 -0
- package/dist/src/config/project-artifacts-runtime.d.mts +16 -0
- package/dist/src/config/user-config-dir.d.mts +9 -0
- package/dist/src/config/user-config.js +2 -1
- package/dist/src/config/user-registry.js +23 -15
- package/dist/src/config/user-state.js +7 -0
- package/dist/src/decision/ask.js +203 -43
- package/dist/src/decision/context-live-qualification.js +2 -2
- package/dist/src/decision/driver.js +13 -8
- package/dist/src/decision/ensemble/aggregate.js +23 -10
- package/dist/src/decision/ensemble-study/multifact-study.js +6 -2
- package/dist/src/decision/entry.js +2 -15
- package/dist/src/decision/graph-live-qualification.js +1 -1
- package/dist/src/decision/graph-run.js +9 -0
- package/dist/src/decision/heldout/collector.js +5 -13
- package/dist/src/decision/heldout/contract.js +30 -7
- package/dist/src/decision/jev-credentials.js +15 -1
- package/dist/src/decision/ledger.js +131 -28
- package/dist/src/decision/offload-activation.js +137 -0
- package/dist/src/decision/offload.js +550 -0
- package/dist/src/decision/qualification/load.js +4 -6
- package/dist/src/decision/savings.js +28 -0
- package/dist/src/effects/types.js +5 -1
- package/dist/src/effects/verifiers/git.js +2 -1
- package/dist/src/effects/verifiers/tracker.js +26 -14
- package/dist/src/extensions/commands/definitions.js +19 -0
- package/dist/src/extensions/project-local-remove.js +36 -1
- package/dist/src/gates/providers/loader.js +61 -17
- package/dist/src/installation/manager-command.d.mts +18 -0
- package/dist/src/installation/manager-command.mjs +14 -2
- package/dist/src/installation/manager.d.mts +49 -0
- package/dist/src/installation/manager.mjs +78 -3
- package/dist/src/issues/cli.js +4 -4
- package/dist/src/issues/local.js +24 -5
- package/dist/src/jobs/runner.js +1 -1
- package/dist/src/lint/cli.js +27 -1
- package/dist/src/lint/loader.js +2 -1
- package/dist/src/lint/reporters.js +25 -1
- package/dist/src/lint/rule-activation.js +43 -0
- package/dist/src/lint/runner.js +137 -62
- package/dist/src/mcp/adapters/codex-runtime.js +7 -1
- package/dist/src/mcp/claude-install.d.mts +4 -0
- package/dist/src/mcp/claude-install.mjs +41 -0
- package/dist/src/mcp/cli.d.mts +1 -0
- package/dist/src/mcp/cli.mjs +36 -11
- package/dist/src/mcp/config-file.d.mts +28 -0
- package/dist/src/mcp/config-layers.d.mts +36 -0
- package/dist/src/mcp/credentials.d.mts +51 -0
- package/dist/src/mcp/grok-build-config.d.mts +6 -0
- package/dist/src/mcp/grok-build-config.mjs +1 -1
- package/dist/src/mcp/helpers.mjs +3 -2
- package/dist/src/mcp/muse-native-config.d.mts +13 -0
- package/dist/src/mcp/muse-native-config.mjs +1 -0
- package/dist/src/mcp/omp-config.d.mts +4 -0
- package/dist/src/mcp/registry.js +3 -93
- package/dist/src/mcp/registry.mjs +3 -87
- package/dist/src/mcp/server-config.d.mts +3 -0
- package/dist/src/mcp/server-config.mjs +89 -0
- package/dist/src/mcp/server.mjs +37 -375
- package/dist/src/mcp/test-simple.mjs +2 -1
- package/dist/src/mcp/toml-editor.d.mts +4 -0
- package/dist/src/mcp/toml-string.d.mts +1 -0
- package/dist/src/mcp/toml-strip-mcp.d.mts +1 -0
- package/dist/src/mcp/tool-filters.d.mts +46 -0
- package/dist/src/mcp/tools/decision.mjs +12 -11
- package/dist/src/mcp/tools/discovery.mjs +62 -55
- package/dist/src/mcp/tools/orchestration.mjs +12 -2
- package/dist/src/mcp/tools/worker-invoke.mjs +1340 -23
- package/dist/src/mcp/tools/worker-shell-control.mjs +52 -21
- package/dist/src/mcp/tools/worker-stdin-runtime.mjs +3 -3
- package/dist/src/mission-protocol/codecs.js +8 -0
- package/dist/src/models/config-loader.js +7 -2
- package/dist/src/models/model-capabilities.v1.json +96 -4
- package/dist/src/models/model-discovery.js +76 -11
- package/dist/src/models/provider-policy.js +101 -7
- package/dist/src/models/qualification-digest.d.mts +2 -0
- package/dist/src/models/resolver.js +12 -10
- package/dist/src/models/worker-direct-readiness.js +65 -44
- package/dist/src/models/worker-dispatch-offer.js +3 -3
- package/dist/src/models/worker-health-readiness.js +16 -3
- package/dist/src/models/worker-installation.d.mts +39 -0
- package/dist/src/models/worker-installation.mjs +135 -28
- package/dist/src/process/bounded-child-process.d.mts +84 -0
- package/dist/src/process/bounded-child-process.mjs +43 -0
- package/dist/src/process/cli-command.d.mts +16 -0
- package/dist/src/process/signal-child.d.mts +6 -0
- package/dist/src/process/signal-child.mjs +7 -0
- package/dist/src/providers/deployed-skill-roots.js +20 -0
- package/dist/src/providers/grok-build-acp.js +3 -2
- package/dist/src/providers/grok-build-headless.js +12 -4
- package/dist/src/providers/grok-build-inspect.js +1 -0
- package/dist/src/providers/omp-agent.d.mts +8 -0
- package/dist/src/providers/omp-diagnostics.d.mts +1 -0
- package/dist/src/providers/omp-paths.d.mts +13 -0
- package/dist/src/providers/skill-ownership.d.mts +9 -0
- package/dist/src/providers/skill-ownership.mjs +88 -0
- package/dist/src/rules/activation.d.mts +21 -0
- package/dist/src/rules/activation.mjs +62 -0
- package/dist/src/rules/inline-budget.d.mts +26 -0
- package/dist/src/rules/inline-budget.mjs +66 -0
- package/dist/src/rules/inventory.js +129 -0
- package/dist/src/rules/pin-state.js +73 -0
- package/dist/src/rules/pins.d.mts +14 -0
- package/dist/src/rules/pins.mjs +112 -0
- package/dist/src/rules/rule-frontmatter.schema.json +197 -0
- package/dist/src/serve/mission-conductor.js +38 -12
- package/dist/src/serve/worker-invocation.js +30 -10
- package/dist/src/serve/worker-stdin-frame.d.mts +10 -0
- package/dist/src/sessions/adapter-registry.js +23 -19
- package/dist/src/sessions/adapters/claude.js +39 -54
- package/dist/src/sessions/adapters/codex.js +95 -67
- package/dist/src/sessions/adapters/copilot.js +4 -4
- package/dist/src/sessions/adapters/cursor.js +40 -57
- package/dist/src/sessions/adapters/deepseek-harness.js +15 -12
- package/dist/src/sessions/adapters/factory.js +31 -27
- package/dist/src/sessions/adapters/generic.js +10 -10
- package/dist/src/sessions/adapters/grok-build.js +11 -11
- package/dist/src/sessions/adapters/grokbot.js +24 -13
- package/dist/src/sessions/adapters/hermes.js +27 -29
- package/dist/src/sessions/adapters/muse-workspace-scan.js +31 -11
- package/dist/src/sessions/adapters/muse.js +150 -93
- package/dist/src/sessions/adapters/omp.js +28 -14
- package/dist/src/sessions/adapters/openclaw.js +89 -79
- package/dist/src/sessions/adapters/opencode.js +27 -24
- package/dist/src/sessions/adapters/openhuman.js +18 -60
- package/dist/src/sessions/adapters/pi.js +29 -14
- package/dist/src/sessions/adapters/warp.js +3 -3
- package/dist/src/sessions/adapters/windsurf.js +19 -48
- package/dist/src/sessions/batch-contracts.js +16 -8
- package/dist/src/sessions/batch-import.js +252 -12
- package/dist/src/sessions/contracts.js +50 -3
- package/dist/src/sessions/coverage-preflight.js +27 -2
- package/dist/src/sessions/export-plan.js +4 -3
- package/dist/src/sessions/import-exclusions.js +72 -0
- package/dist/src/sessions/import-lease.js +34 -18
- package/dist/src/sessions/import-limits.js +37 -0
- package/dist/src/sessions/importer.js +60 -38
- package/dist/src/sessions/lifecycle.js +45 -0
- package/dist/src/sessions/policy.js +145 -26
- package/dist/src/sessions/readers.js +106 -53
- package/dist/src/sessions/refresh.js +105 -0
- package/dist/src/sessions/repository.js +151 -54
- package/dist/src/sessions/workspace-discovery.js +292 -60
- package/dist/src/sessions/workspace-matching.js +107 -0
- package/dist/src/skills/importer.js +1 -0
- package/dist/src/smiths/context-pipeline/aiwg-md.js +11 -0
- package/dist/src/smiths/context-pipeline/claude-hook.js +3 -26
- package/dist/src/smiths/context-pipeline/finalization.js +6 -5
- package/dist/src/smiths/context-pipeline/generator.js +21 -4
- package/dist/src/smiths/context-pipeline/parallelism-section.js +7 -15
- package/dist/src/smiths/mcpsmith/generator.js +1 -1
- package/dist/src/smiths/toolsmith/runtime-discovery.d.mts +10 -0
- package/dist/src/smiths/toolsmith/runtime-discovery.mjs +76 -18
- package/dist/src/storage/backends/fs.js +18 -76
- package/dist/src/storage/backends/obsidian.js +1 -0
- package/dist/src/tracker/forge-http.js +2 -1
- package/dist/src/update/checker.d.mts +2 -0
- package/dist/src/update/service.d.mts +22 -0
- package/dist/src/utils/contained-filesystem.d.mts +37 -0
- package/dist/src/utils/contained-filesystem.mjs +683 -0
- package/dist/src/utils/temporary-directory.js +36 -0
- package/dist/src/writing/example-generator.js +1 -1
- package/package.json +15 -2
- package/schemas/models/model-catalog.v1.schema.json +1 -1
- package/schemas/models/provider-model-capabilities.v1.schema.json +6 -0
- package/tools/_resolve-impl.mjs +13 -15
- package/tools/agents/deploy-agents.mjs +49 -21
- package/tools/agents/providers/base.mjs +104 -134
- package/tools/agents/providers/claude.mjs +8 -24
- package/tools/agents/providers/codex.mjs +18 -11
- package/tools/agents/providers/cursor.mjs +19 -18
- package/tools/agents/providers/grok-build.mjs +3 -1
- package/tools/agents/providers/hermes.mjs +57 -47
- package/tools/agents/providers/openclaw.mjs +9 -4
- package/tools/agents/providers/pi.mjs +5 -0
- package/tools/agents/providers/provider-prepare-channel.mjs +5 -0
- package/tools/agents/providers/provider-prepare-coordinator.mjs +247 -0
- package/tools/agents/providers/provider-prepare-worker.mjs +84 -0
- package/tools/agents/providers/rule-delivery.mjs +1270 -0
- package/tools/agents/providers/warp.mjs +20 -26
- package/tools/cli/decision-offload-report.mjs +40 -0
- package/tools/cli/workspace-status.mjs +862 -0
- package/tools/plugin/package-plugins.mjs +186 -8
- package/tools/plugin/plugin-links.mjs +114 -0
- package/tools/providers/antigravity-transport.mjs +3 -1
- package/tools/providers/deepseek-harness-transport.mjs +6 -4
- package/tools/providers/omp-transport.mjs +4 -2
- package/tools/ralph-external/lib/consecutive-failure-circuit-breaker.mjs +1748 -0
- package/tools/ralph-external/lib/launcher-recovery-evidence.mjs +55 -0
- package/tools/ralph-external/lib/omp-adapter.mjs +1 -1
- package/tools/ralph-external/lib/pi-adapter.mjs +0 -4
- package/tools/ralph-external/lib/provider-adapter.mjs +59 -1
- package/tools/ralph-external/lib/recovery-probe.mjs +72 -0
- package/tools/ralph-external/lib/session-environment.mjs +28 -0
- package/tools/ralph-external/lib/systemd-client.mjs +49 -0
- package/tools/ralph-external/lib/worker-health.mjs +1 -1
- package/tools/ralph-external/lib/worker-isolation.mjs +717 -0
- package/tools/ralph-external/lib/worker-overflow.mjs +50 -0
- package/tools/ralph-external/process-monitor.mjs +1017 -0
- package/tools/ralph-external/session-launcher.mjs +5057 -0
- package/tools/scripts/resource-preflight.mjs +541 -0
- package/tools/skills/deploy-skills-codex.mjs +2 -1
- package/vscode-extension/schemas/aiwg.config.v1.json +1194 -231
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* @tests @test/unit/artifacts/citation-parser.test.ts
|
|
23
23
|
*/
|
|
24
24
|
import { parseFrontmatter } from './index-builder.js';
|
|
25
|
+
import { CITATION_HEADER_ALIASES, CITATION_SECTION_ALIASES } from './citation-table-schema.js';
|
|
25
26
|
/**
|
|
26
27
|
* Match a single node identifier (REF-* or PROF-*) anywhere in a string.
|
|
27
28
|
* Used by `extractRefsFromTable` to pull every ID out of a table cell.
|
|
@@ -33,31 +34,71 @@ const NODE_ID_PATTERN = /(?:REF-\d+[a-z]?|PROF-[POFG]-[a-z0-9-]+)/g;
|
|
|
33
34
|
* frontmatter `ref` values.
|
|
34
35
|
*/
|
|
35
36
|
const NODE_ID_FULL = /^(?:REF-\d+[a-z]?|PROF-[POFG]-[a-z0-9-]+)$/;
|
|
36
|
-
/**
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
];
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
function
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
37
|
+
/** An unnamed resolution cell must contain only one REF, optionally decorated. */
|
|
38
|
+
function standaloneRef(value) {
|
|
39
|
+
let text = value.trim();
|
|
40
|
+
const link = text.match(/^\[([^\]]+)\]\([^\s]+(?:\s+"[^"\n]*")?\)$/);
|
|
41
|
+
if (link)
|
|
42
|
+
text = link[1].trim();
|
|
43
|
+
const code = text.match(/^`([^`]+)`$/);
|
|
44
|
+
if (code)
|
|
45
|
+
text = code[1].trim();
|
|
46
|
+
return /^REF-\d+[a-z]?$/.test(text) ? text : null;
|
|
47
|
+
}
|
|
48
|
+
/** Resolution aliases are shared by every registered bibliographic form. */
|
|
49
|
+
const CITATION_REF_COLUMNS = CITATION_HEADER_ALIASES.ref;
|
|
50
|
+
const HEADER_ROLES = new Map(Object.entries(CITATION_HEADER_ALIASES).flatMap(([role, aliases]) => aliases.map(alias => [alias, role])));
|
|
51
|
+
function normalizeCell(value) {
|
|
52
|
+
return value.toLowerCase().replace(/[`*_]/g, '').replace(/\s+/g, ' ').trim();
|
|
53
|
+
}
|
|
54
|
+
/** Direction belongs to the heading, never to a mention in its section body. */
|
|
55
|
+
function citationDirection(heading) {
|
|
56
|
+
const text = normalizeCell(heading.replace(/[ \t]+#+[ \t]*$/, ''));
|
|
57
|
+
const segment = text.split(/[/—:(]/, 1)[0].trim();
|
|
58
|
+
// Keep the corpus's Incoming/Outgoing descriptions, with a word boundary
|
|
59
|
+
// so unrelated words such as "Incomingish" cannot declare citations.
|
|
60
|
+
if (/^incoming(?:\s|$)/.test(segment))
|
|
61
|
+
return 'incoming';
|
|
62
|
+
if (/^outgoing(?:\s|$)/.test(segment))
|
|
63
|
+
return 'outgoing';
|
|
64
|
+
for (const direction of ['incoming', 'outgoing']) {
|
|
65
|
+
if (CITATION_SECTION_ALIASES[direction].some(alias => text === alias
|
|
66
|
+
|| (text.startsWith(alias) && /^\s*[/—:(]/.test(text.slice(alias.length)))))
|
|
67
|
+
return direction;
|
|
59
68
|
}
|
|
60
|
-
return
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
/** Explicitly non-bibliographic or uncertain declarations must not assert citations. */
|
|
72
|
+
function isNonCitation(value) {
|
|
73
|
+
const text = normalizeCell(value);
|
|
74
|
+
// An explicit disavowal wins even when the description also says "cites".
|
|
75
|
+
if (/\b(?:topical|thematic|non[- ]citations?|methodological cousin|unverified)\b/.test(text)
|
|
76
|
+
|| /\bnot (?:(?:a|an) )?(?:(?:verified|formal|directly) )?(?:citations?|cites?|cited|verified)\b/.test(text)
|
|
77
|
+
|| /\bno (?:formal |verified )?citations?\b/.test(text)
|
|
78
|
+
|| /\b(?:if|unless|provided that|assuming)\s+(?:ref-\d+|prof-[pofg]-|present\b)/.test(text)
|
|
79
|
+
|| /\bconditional (?:on|upon)\b/.test(text)
|
|
80
|
+
|| /^(?:conditional|related)(?:\s+only)?\s*(?:[(:;—-]|$)/.test(text))
|
|
81
|
+
return true;
|
|
82
|
+
// "Cites X in Related Work", "cites-related-version", and citations to a
|
|
83
|
+
// paper named "Conditional Memory" describe real citations, not qualifiers.
|
|
84
|
+
if (/\b(?:cites?|cited|citing)\b/.test(text))
|
|
85
|
+
return false;
|
|
86
|
+
return /\brelated\b/.test(text);
|
|
87
|
+
}
|
|
88
|
+
/** Table/section declarations, rather than incidental mentions in audit prose. */
|
|
89
|
+
function isNonCitationContext(value) {
|
|
90
|
+
// Candidate-specific audit prose does not disavow the surrounding tables.
|
|
91
|
+
// Keep whole-table declarations separate from notes about particular REFs.
|
|
92
|
+
const text = value.replace(/<!--[\s\S]*?-->/g, '').toLowerCase().replace(/[`*_]/g, '').split('\n')
|
|
93
|
+
.filter(line => !/\b(?:search results|external .*?candidates?|historical records)\b/.test(line))
|
|
94
|
+
.filter(line => !/(?:ref-\d+|prof-[pofg]-)/.test(line)
|
|
95
|
+
|| /\b(?:rows|tables?|relationships?|connections?) (?:below|are|only)\b/.test(line))
|
|
96
|
+
.join('\n');
|
|
97
|
+
return /(?:^|\n)\s*(?:related|topical|thematic) works[^\n]*\b(?:do|does) not (?:directly )?cite\b/.test(text)
|
|
98
|
+
|| /\b(?:no (?:formal|verified) citations?|not (?:(?:asserted|verified) )?citation (?:edges?|rows?)|relationship notes|related corpus nodes)\b/.test(text)
|
|
99
|
+
|| /\bno citations\s*(?:[.!;]|$)/.test(text)
|
|
100
|
+
|| /\b(?:topical|thematic|related|conditional|non-citation) (?:relationships?|connections?|only)\b/.test(text)
|
|
101
|
+
|| /(?:^|\n)\s*(?:topical|thematic|related|conditional|non-citation)(?:\s+(?:relationships?|connections?|notes|rows|only))?\s*(?:$|\n)/.test(text);
|
|
61
102
|
}
|
|
62
103
|
/**
|
|
63
104
|
* Test whether a string is a valid sidecar node identifier.
|
|
@@ -73,75 +114,102 @@ export function isNodeId(value) {
|
|
|
73
114
|
* Extract node identifiers from a markdown table column.
|
|
74
115
|
*
|
|
75
116
|
* Scans table rows for a column matching `columnName` (case-insensitive)
|
|
76
|
-
* and extracts node IDs (REF-* or PROF-*)
|
|
117
|
+
* and extracts node IDs (REF-* or PROF-*) only from that cell. Malformed
|
|
118
|
+
* tables/rows and explicit non-citation qualifiers are skipped.
|
|
77
119
|
*
|
|
78
120
|
* @param tableText - Markdown table text (header + separator + rows)
|
|
79
121
|
* @param columnName - Column header to extract from (e.g., "Inducted REF")
|
|
80
122
|
* @returns Array of node identifiers found
|
|
81
123
|
*/
|
|
82
124
|
export function extractRefsFromTable(tableText, columnName) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
currentBlock = [];
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
if (currentBlock.length > 0)
|
|
97
|
-
tableBlocks.push(currentBlock);
|
|
98
|
-
const parseRow = (line) => {
|
|
99
|
-
let row = line.trim();
|
|
100
|
-
if (row.startsWith('|'))
|
|
101
|
-
row = row.slice(1);
|
|
102
|
-
if (row.endsWith('|'))
|
|
103
|
-
row = row.slice(0, -1);
|
|
104
|
-
return row.split('|').map(cell => cell.trim());
|
|
105
|
-
};
|
|
125
|
+
return extractTableRefs(tableText, columnName, false);
|
|
126
|
+
}
|
|
127
|
+
function extractTableRefs(tableText, columnName, bibliographicOnly) {
|
|
128
|
+
const aliases = (typeof columnName === 'string' ? [columnName] : columnName)
|
|
129
|
+
.map(normalizeCell);
|
|
130
|
+
const parseRow = (line) => line.trim().replace(/^\|/, '').replace(/\|$/, '').split(/(?<!\\)\|/)
|
|
131
|
+
.map(cell => cell.replace(/\\\|/g, '|').trim());
|
|
132
|
+
const lines = tableText.split('\n');
|
|
133
|
+
const headings = [];
|
|
134
|
+
let preamble = [];
|
|
106
135
|
const refs = [];
|
|
107
|
-
for (
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
NODE_ID_PATTERN.lastIndex = 0;
|
|
123
|
-
const refMatches = line.match(NODE_ID_PATTERN);
|
|
124
|
-
if (refMatches)
|
|
125
|
-
refs.push(...refMatches);
|
|
126
|
-
}
|
|
136
|
+
for (let i = 0; i < lines.length; i++) {
|
|
137
|
+
const heading = lines[i].match(/^ {0,3}(#{1,6})[ \t]+(.+)/);
|
|
138
|
+
if (heading) {
|
|
139
|
+
// A parent section's declaration also governs its nested tables.
|
|
140
|
+
const parent = headings[headings.length - 1];
|
|
141
|
+
if (parent && parent.level < heading[1].length)
|
|
142
|
+
parent.text += `\n${preamble.join('\n')}`;
|
|
143
|
+
while (headings.length && headings[headings.length - 1].level >= heading[1].length)
|
|
144
|
+
headings.pop();
|
|
145
|
+
headings.push({ level: heading[1].length, text: heading[2] });
|
|
146
|
+
preamble = [];
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (!lines[i].trim().startsWith('|')) {
|
|
150
|
+
preamble.push(lines[i]);
|
|
127
151
|
continue;
|
|
128
152
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
153
|
+
const table = [];
|
|
154
|
+
while (i < lines.length && lines[i].trim().startsWith('|'))
|
|
155
|
+
table.push(lines[i++]);
|
|
156
|
+
i--;
|
|
157
|
+
const context = [...headings.map(h => h.text), ...preamble];
|
|
158
|
+
preamble = [];
|
|
159
|
+
// A trailing note can explicitly disavow the preceding table's citations.
|
|
160
|
+
const following = [];
|
|
161
|
+
for (let j = i + 1; j < lines.length && !/^\s*[#|]/.test(lines[j]); j++)
|
|
162
|
+
following.push(lines[j]);
|
|
163
|
+
if (/^\s*note\b/im.test(following.join('\n')))
|
|
164
|
+
context.push(...following);
|
|
165
|
+
if (isNonCitationContext(context.join('\n')) || table.length < 3)
|
|
166
|
+
continue;
|
|
167
|
+
const headers = parseRow(table[0]).map(normalizeCell);
|
|
168
|
+
if (headers.some(isNonCitation))
|
|
169
|
+
continue;
|
|
170
|
+
const separator = parseRow(table[1]);
|
|
171
|
+
if (separator.length !== headers.length || !separator.every(cell => /^:?-{3,}:?$/.test(cell)))
|
|
172
|
+
continue;
|
|
173
|
+
const roles = headers.map(header => HEADER_ROLES.get(header));
|
|
174
|
+
// Incoming/Outgoing declares the direction; the named resolution header
|
|
175
|
+
// identifies the target when present. Otherwise whole-cell REF IDs
|
|
176
|
+
// resolve rows. Additional metadata and column order do not change
|
|
177
|
+
// those semantics. Multiple resolution columns are ambiguous.
|
|
178
|
+
if (bibliographicOnly && roles.filter(role => role === 'ref').length > 1)
|
|
179
|
+
continue;
|
|
180
|
+
// For graph extraction the headers register exactly one resolution
|
|
181
|
+
// column when present. The generic column helper still honors its explicit alias order.
|
|
182
|
+
const colIndex = bibliographicOnly
|
|
183
|
+
? roles.indexOf('ref')
|
|
184
|
+
: aliases.map(alias => headers.indexOf(alias)).find(index => index !== -1) ?? -1;
|
|
185
|
+
if (colIndex === -1 && !bibliographicOnly)
|
|
186
|
+
continue;
|
|
187
|
+
for (const line of table.slice(2)) {
|
|
188
|
+
const cells = parseRow(line);
|
|
189
|
+
// Extra/missing cells have no unambiguous column semantics. Never guess.
|
|
190
|
+
if (cells.length !== headers.length)
|
|
191
|
+
continue;
|
|
192
|
+
// A resolution explicitly labelled as context/adjacency does not map
|
|
193
|
+
// the printed entry to that node (corpus Formal References variants).
|
|
194
|
+
if (colIndex !== -1
|
|
195
|
+
&& /\b(?:REF-\d+[a-z]?|PROF-[POFG]-[a-z0-9-]+)\s+(?:(?:family )?context|adjacent)\b/i.test(normalizeCell(cells[colIndex])))
|
|
133
196
|
continue;
|
|
134
|
-
//
|
|
135
|
-
//
|
|
136
|
-
|
|
137
|
-
// alias (title/authors/year) remain excluded.
|
|
138
|
-
const value = cells.slice(colIndex).join(' | ');
|
|
139
|
-
if (!value || value === '—' || value === '-' || value === '–')
|
|
197
|
+
// A condition can also qualify the printed title, as in the downstream
|
|
198
|
+
// "Learning is Forgetting (if REF-828 in 6-benchmark suite)" row.
|
|
199
|
+
if (cells.some(cell => /\b(?:if|unless|provided that|assuming)\s+[`*_[\s]*(?:REF-\d+|PROF-[POFG]-)/i.test(cell)))
|
|
140
200
|
continue;
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
201
|
+
const qualifiers = cells.filter((_, index) => (bibliographicOnly && colIndex === -1) || index === colIndex
|
|
202
|
+
|| ['notes', 'evidence', 'context', 'kind', 'relationship', 'status'].includes(roles[index] ?? '')
|
|
203
|
+
|| (!bibliographicOnly && !['#', 'title', 'work', 'authors', 'year', 'doi/url', 'doi', 'url'].includes(headers[index])));
|
|
204
|
+
if (qualifiers.some(isNonCitation))
|
|
205
|
+
continue;
|
|
206
|
+
// Without a named resolution column, only whole-cell REF IDs resolve.
|
|
207
|
+
// Named columns always take precedence over incidental IDs elsewhere.
|
|
208
|
+
const matches = colIndex === -1
|
|
209
|
+
? cells.map(standaloneRef).filter((ref) => ref !== null)
|
|
210
|
+
: cells[colIndex].match(NODE_ID_PATTERN);
|
|
211
|
+
if (matches)
|
|
212
|
+
refs.push(...matches);
|
|
145
213
|
}
|
|
146
214
|
}
|
|
147
215
|
return [...new Set(refs)];
|
|
@@ -149,6 +217,12 @@ export function extractRefsFromTable(tableText, columnName) {
|
|
|
149
217
|
/**
|
|
150
218
|
* Parse a citation sidecar markdown file into structured edges.
|
|
151
219
|
*
|
|
220
|
+
* Tables in recognized directional or reference sections declare citations through a unique
|
|
221
|
+
* registered resolution column, or whole-cell REF IDs when no such column
|
|
222
|
+
* exists, independent of other metadata columns.
|
|
223
|
+
* Topical, related, conditional and explicitly non-citation declarations are
|
|
224
|
+
* skipped; they do not produce citation edges or new relationship types.
|
|
225
|
+
*
|
|
152
226
|
* @param content - Full markdown content of the sidecar file
|
|
153
227
|
* @returns Parse result with ref ID and edge arrays, or null if not a valid sidecar
|
|
154
228
|
*/
|
|
@@ -158,22 +232,29 @@ export function parseCitationSidecar(content) {
|
|
|
158
232
|
const ref = typeof data.ref === 'string' ? data.ref : null;
|
|
159
233
|
if (!ref || !NODE_ID_FULL.test(ref))
|
|
160
234
|
return null;
|
|
161
|
-
//
|
|
162
|
-
const
|
|
235
|
+
// ATX level-two headings allow indentation, tabs and closing hashes.
|
|
236
|
+
const sectionHeading = /^ {0,3}##[ \t]+([^\r\n]+)/m;
|
|
237
|
+
const sections = body.split(/(?=^ {0,3}##[ \t]+)/m).filter(Boolean);
|
|
238
|
+
const preamble = sectionHeading.test(sections[0] ?? '') ? '' : sections[0] ?? '';
|
|
239
|
+
if (isNonCitationContext(preamble.replace(/^#+ .*$/gm, '')))
|
|
240
|
+
return { ref, cites: [], citedBy: [] };
|
|
163
241
|
let cites = [];
|
|
164
242
|
let citedBy = [];
|
|
165
243
|
for (const section of sections) {
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
cites.push(...
|
|
244
|
+
const heading = section.match(sectionHeading);
|
|
245
|
+
const direction = heading ? citationDirection(heading[1]) : null;
|
|
246
|
+
if (direction === 'outgoing') {
|
|
247
|
+
cites.push(...extractTableRefs(section, CITATION_REF_COLUMNS, true));
|
|
170
248
|
}
|
|
171
|
-
else if (
|
|
172
|
-
citedBy.push(...
|
|
173
|
-
citedBy.push(...extractSectionNodeIds(section));
|
|
249
|
+
else if (direction === 'incoming') {
|
|
250
|
+
citedBy.push(...extractTableRefs(section, CITATION_REF_COLUMNS, true));
|
|
174
251
|
}
|
|
175
252
|
}
|
|
176
|
-
return {
|
|
253
|
+
return {
|
|
254
|
+
ref,
|
|
255
|
+
cites: [...new Set(cites)].filter(target => target !== ref),
|
|
256
|
+
citedBy: [...new Set(citedBy)].filter(source => source !== ref),
|
|
257
|
+
};
|
|
177
258
|
}
|
|
178
259
|
/**
|
|
179
260
|
* Convert a CitationParseResult into TypedEdge arrays for the dependency graph.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registered column aliases for citation-sidecar edge extraction.
|
|
3
|
+
*
|
|
4
|
+
* Based on the research-papers corpus table contract
|
|
5
|
+
* (scripts/corpus/citation-sidecar.schema.json, schemaVersion 1). A unique
|
|
6
|
+
* resolution header identifies the target cell in Incoming/Outgoing tables.
|
|
7
|
+
* Without one, a whole-cell REF ID can resolve a row.
|
|
8
|
+
* Other columns supply metadata or explicit qualifiers that disavow citations;
|
|
9
|
+
* they do not need to follow an enumerated table shape.
|
|
10
|
+
*/
|
|
11
|
+
/** Direction names used as whole headings or before /, —, :, or (. */
|
|
12
|
+
export const CITATION_SECTION_ALIASES = {
|
|
13
|
+
incoming: ['cited-by', 'cited by', 'papers that cite this work', 'sources that cite this work', 'works that cite this work'],
|
|
14
|
+
outgoing: [
|
|
15
|
+
'cites', 'references', 'papers this work cites', 'sources this work cites', 'works this work cites',
|
|
16
|
+
'formal / high-value references extracted',
|
|
17
|
+
'formal / high-value references and benchmarks extracted',
|
|
18
|
+
'formal references extracted from the card',
|
|
19
|
+
'formal references extracted from the addendum / parent card',
|
|
20
|
+
'high-value references and benchmarks',
|
|
21
|
+
'foundational external citations',
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
export const CITATION_HEADER_ALIASES = {
|
|
25
|
+
ordinal: ['#', 'bibliography #', 'label', 'row', 'original label', '# (arxiv)'],
|
|
26
|
+
title: [
|
|
27
|
+
'title', 'citing work', 'cited work', 'citation', 'citation (extracted)', 'title / source',
|
|
28
|
+
'title / work', 'title / source bibliographic entry', 'citation as printed (normalized whitespace)',
|
|
29
|
+
'citation as printed or faithfully transcribed', 'cited source / concept',
|
|
30
|
+
'mentioned work / cluster', 'work cited / discussed', 'source', 'artifact', 'title / referent',
|
|
31
|
+
'work / cluster', 'source-reported reference', 'title / source label', 'title / target', 'entry',
|
|
32
|
+
'reference', 'reference (as printed, cvpr 2026 camera-ready)', 'reference (as printed, arxiv v2)',
|
|
33
|
+
],
|
|
34
|
+
authors: [
|
|
35
|
+
'authors', 'authors / publisher', 'organization', 'party', 'authors / project', 'author(s)',
|
|
36
|
+
'authors / attributed entity', 'authors (as printed)', 'author or owner', 'authors / org',
|
|
37
|
+
],
|
|
38
|
+
year: ['year'],
|
|
39
|
+
locator: [
|
|
40
|
+
'doi/url', 'doi / url', 'url', 'identifier', 'venue / doi / url', 'doi/url/venue', 'venue / url',
|
|
41
|
+
'doi/url or venue', 'venue / id', 'venue / identifier', 'identifier / url', 'venue / doi',
|
|
42
|
+
],
|
|
43
|
+
ref: [
|
|
44
|
+
'inducted ref', 'corpus node', 'corpus ref', 'in-corpus ref', 'ref', 'citing ref', 'ref / issue',
|
|
45
|
+
'in-corpus ref / issue', 'corpus id',
|
|
46
|
+
],
|
|
47
|
+
context: ['context', 'where it appears'],
|
|
48
|
+
notes: ['notes', 'note', 'rationale', 'why the guarded matcher missed it'],
|
|
49
|
+
evidence: [
|
|
50
|
+
'source evidence', 'in-text evidence', 'provenance', 'evidence', 'basis', 'verification',
|
|
51
|
+
'confirmed by',
|
|
52
|
+
],
|
|
53
|
+
'their-row': ['their row', '[ref]', 'row in its sidecar'],
|
|
54
|
+
venue: ['venue'],
|
|
55
|
+
kind: ['kind', 'type', 'nature'],
|
|
56
|
+
relationship: ['relationship', 'relation', 'relationship (conceptual, not citation-grounded)'],
|
|
57
|
+
status: ['mapping status', 'status', 'mapping'],
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=citation-table-schema.js.map
|
|
@@ -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';
|
|
@@ -213,6 +214,15 @@ export async function main(args) {
|
|
|
213
214
|
process.exit(0);
|
|
214
215
|
}
|
|
215
216
|
switch (subcommand) {
|
|
217
|
+
case 'refresh': {
|
|
218
|
+
if (subcommandArgs.includes('--help') || subcommandArgs.includes('-h')) {
|
|
219
|
+
printIndexUsage();
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
const { runIndexRefresh } = await import('./index-refresh.js');
|
|
223
|
+
await runIndexRefresh(subcommandArgs);
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
216
226
|
case 'build':
|
|
217
227
|
await handleBuild(subcommandArgs);
|
|
218
228
|
break;
|
|
@@ -288,15 +298,16 @@ export async function main(args) {
|
|
|
288
298
|
break;
|
|
289
299
|
default:
|
|
290
300
|
console.error(`Error: Unknown index subcommand '${subcommand}'`);
|
|
291
|
-
console.log('Available: build, query, discover, show, export, sync, migrate-legacy, deps, stats, status, list, neighbors, set, embed, similar, dedup-report, eval-discovery, watch');
|
|
301
|
+
console.log('Available: build, refresh, query, discover, show, export, sync, migrate-legacy, deps, stats, status, list, neighbors, set, embed, similar, dedup-report, eval-discovery, watch');
|
|
292
302
|
process.exit(1);
|
|
293
303
|
}
|
|
294
304
|
}
|
|
295
|
-
function printIndexUsage() {
|
|
305
|
+
export function printIndexUsage() {
|
|
296
306
|
console.log('Usage: aiwg index <subcommand> [options]');
|
|
297
307
|
console.log('');
|
|
298
308
|
console.log('Available subcommands:');
|
|
299
309
|
console.log(' build Build/rebuild the artifact index');
|
|
310
|
+
console.log(' refresh Safely refresh graphs, caches, sessions, runtime, models, and local issues');
|
|
300
311
|
console.log(' query Search artifacts by keyword, type, phase, tags');
|
|
301
312
|
console.log(' discover Capability search across operational asset types (#1214)');
|
|
302
313
|
console.log(' show Print the full text of a specific operational asset');
|
|
@@ -315,12 +326,23 @@ function printIndexUsage() {
|
|
|
315
326
|
console.log(' watch Start a filesystem watcher for automatic incremental index updates');
|
|
316
327
|
console.log('');
|
|
317
328
|
console.log('Options:');
|
|
329
|
+
console.log(' build [--force] [--verbose] [--all] [--scope <dir>] [--graph <name>]');
|
|
330
|
+
console.log(' refresh [--full] [--workspace <path>]... [--root <dir>]...');
|
|
331
|
+
console.log(' [--only graphs|sessions|caches|runtime|models|issues] [--dry-run] [--json] [--lock-wait-ms <n>]');
|
|
332
|
+
console.log(' [--max-record-bytes <n>] [--max-source-bytes <n>]');
|
|
333
|
+
console.log(' Session import defaults: 67108864 bytes per record, 1073741824 bytes (1 GiB) per source; source 0 is unlimited.');
|
|
334
|
+
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).');
|
|
335
|
+
console.log(' Import limits: CLI flag > AIWG_SESSIONS_IMPORT_MAX_RECORD_BYTES / AIWG_SESSIONS_IMPORT_MAX_SOURCE_BYTES > workspace config > default.');
|
|
336
|
+
console.log(' build/refresh --index-workers <n>: preparation processes (0 = serial); flag > AIWG_INDEX_WORKERS > automatic CPU/memory limits.');
|
|
337
|
+
console.log(' sync [--backend fortemi-core] [--graph <name> | --all] [--repo <name>]');
|
|
338
|
+
console.log(' [--privacy private|sanitized|public] [--generated-at <iso>] [--json]');
|
|
318
339
|
console.log(' --graph <name> Target a specific graph (framework, project, codebase, source, user, or user-defined)');
|
|
319
340
|
console.log(' --all Build all known graphs (including user-defined)');
|
|
320
341
|
console.log('');
|
|
321
342
|
console.log('Examples:');
|
|
322
343
|
console.log(' aiwg index build');
|
|
323
344
|
console.log(' aiwg index build --all');
|
|
345
|
+
console.log(' aiwg index refresh --root ~/dev --json');
|
|
324
346
|
console.log(' aiwg index build --graph codebase --force');
|
|
325
347
|
console.log(' aiwg index discover "create intake"');
|
|
326
348
|
console.log(' aiwg index discover "deploy production" --limit 5 --json');
|
|
@@ -483,10 +505,13 @@ async function handleBuild(args) {
|
|
|
483
505
|
console.log('Usage: aiwg index build [options]');
|
|
484
506
|
console.log('');
|
|
485
507
|
console.log('Options:');
|
|
508
|
+
console.log(' --index-workers <n> Preparation processes (0 = serial); overrides AIWG_INDEX_WORKERS');
|
|
486
509
|
console.log(' --force Full rebuild (ignore checksums, re-index everything)');
|
|
487
510
|
console.log(' --verbose Show detailed progress during indexing');
|
|
488
511
|
console.log(' --all Build all known graphs (including user-defined)');
|
|
489
512
|
console.log(' --scope <dir> Limit scan to a specific subdirectory');
|
|
513
|
+
console.log(' --include-ignored Include gitignored sources (runtime directories stay excluded)');
|
|
514
|
+
console.log(' Source discovery skips symlinks and .aiwg/{working,sessions,scratch,tmp,temp,cache,.index,.cache,.storage-cache}/.');
|
|
490
515
|
console.log(' --graph <name> Build a specific graph only (built-in or user-defined)');
|
|
491
516
|
console.log('');
|
|
492
517
|
console.log('Built-in graph names: project, codebase, source, user, framework');
|
|
@@ -508,6 +533,15 @@ async function handleBuild(args) {
|
|
|
508
533
|
console.log(' aiwg index sync --all');
|
|
509
534
|
return;
|
|
510
535
|
}
|
|
536
|
+
let workers;
|
|
537
|
+
try {
|
|
538
|
+
workers = resolveIndexWorkers(parseFlagValue(args, '--index-workers', 'Error: --index-workers requires a value'));
|
|
539
|
+
}
|
|
540
|
+
catch (error) {
|
|
541
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
542
|
+
process.exitCode = 1;
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
511
545
|
// Dynamic import to keep the CLI router lightweight
|
|
512
546
|
const { buildIndex } = await import('./index-builder.js');
|
|
513
547
|
const cwd = process.cwd();
|
|
@@ -516,6 +550,7 @@ async function handleBuild(args) {
|
|
|
516
550
|
const force = args.includes('--force');
|
|
517
551
|
const verbose = args.includes('--verbose');
|
|
518
552
|
const all = args.includes('--all');
|
|
553
|
+
const includeIgnored = args.includes('--include-ignored');
|
|
519
554
|
const graph = parseGraphFlag(args);
|
|
520
555
|
let scope;
|
|
521
556
|
const scopeIdx = args.indexOf('--scope');
|
|
@@ -531,7 +566,7 @@ async function handleBuild(args) {
|
|
|
531
566
|
// --graph X: build the JSON graph if X is one; otherwise X may be a
|
|
532
567
|
// research-corpus markdown view, rendered below.
|
|
533
568
|
if (graph in GRAPH_CONFIGS) {
|
|
534
|
-
await buildIndex(cwd, { force, verbose, scope, graph, explicit: true });
|
|
569
|
+
await buildIndex(cwd, { force, verbose, scope, includeIgnored, workers, graph, explicit: true });
|
|
535
570
|
jsonBuilt = true;
|
|
536
571
|
builtGraphs.add(graph);
|
|
537
572
|
}
|
|
@@ -539,7 +574,7 @@ async function handleBuild(args) {
|
|
|
539
574
|
else if (all) {
|
|
540
575
|
// Build all known graphs — user asked for everything, but don't hard-error on missing dirs
|
|
541
576
|
for (const [name] of orderedGraphEntries(Object.entries(GRAPH_CONFIGS))) {
|
|
542
|
-
await buildIndex(cwd, { force, verbose, graph: name, explicit: false });
|
|
577
|
+
await buildIndex(cwd, { force, verbose, includeIgnored, workers, graph: name, explicit: false });
|
|
543
578
|
builtGraphs.add(name);
|
|
544
579
|
}
|
|
545
580
|
jsonBuilt = true;
|
|
@@ -548,7 +583,7 @@ async function handleBuild(args) {
|
|
|
548
583
|
// Default: build graphs with defaultBuild=true; skip gracefully if their dirs don't exist
|
|
549
584
|
for (const [name, config] of orderedGraphEntries(Object.entries(GRAPH_CONFIGS))) {
|
|
550
585
|
if (config.defaultBuild) {
|
|
551
|
-
await buildIndex(cwd, { force, verbose, scope: name === Object.keys(GRAPH_CONFIGS)[0] ? scope : undefined, graph: name, explicit: false });
|
|
586
|
+
await buildIndex(cwd, { force, verbose, includeIgnored, workers, scope: name === Object.keys(GRAPH_CONFIGS)[0] ? scope : undefined, graph: name, explicit: false });
|
|
552
587
|
builtGraphs.add(name);
|
|
553
588
|
}
|
|
554
589
|
}
|
|
@@ -589,18 +624,18 @@ async function syncFortemiCoreCachesAfterBuild(cwd, graphs, verbose) {
|
|
|
589
624
|
const { syncFortemiCoreIndex } = await import('./fortemi-core-sync.js');
|
|
590
625
|
const { loadGraphIndexFile } = await import('./index-reader.js');
|
|
591
626
|
for (const graph of graphs) {
|
|
592
|
-
// Some default-build graphs skip cleanly when their scan roots are absent.
|
|
593
|
-
// Only materialize a cache when this build left an actual source index.
|
|
594
|
-
if (!loadGraphIndexFile(cwd, 'metadata.json', graph))
|
|
595
|
-
continue;
|
|
596
627
|
try {
|
|
628
|
+
// Some auto-selected graphs skip cleanly when their scan roots are absent.
|
|
629
|
+
if (!loadGraphIndexFile(cwd, 'metadata.json', graph))
|
|
630
|
+
continue;
|
|
597
631
|
const manifest = syncFortemiCoreIndex(cwd, { graph });
|
|
598
632
|
if (verbose) {
|
|
599
633
|
console.log(`Fortemi Core ${graph} sync: ${manifest.status}, ${manifest.item_count} item(s) → ${manifest.export_path}`);
|
|
600
634
|
}
|
|
601
635
|
}
|
|
602
636
|
catch (err) {
|
|
603
|
-
|
|
637
|
+
process.exitCode = 1;
|
|
638
|
+
console.error(`Error: Fortemi Core ${graph} sync failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
604
639
|
console.error(`Run \`aiwg index sync --graph ${graph}\` before using Fortemi-backed commands for '${graph}' artifacts.`);
|
|
605
640
|
}
|
|
606
641
|
}
|
|
@@ -1099,19 +1134,30 @@ async function handleSync(args) {
|
|
|
1099
1134
|
if (all) {
|
|
1100
1135
|
const { loadGraphIndexFile } = await import('./index-reader.js');
|
|
1101
1136
|
const manifests = [];
|
|
1137
|
+
const failures = [];
|
|
1102
1138
|
for (const [name] of orderedGraphEntries(Object.entries(GRAPH_CONFIGS))) {
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1139
|
+
try {
|
|
1140
|
+
if (!loadGraphIndexFile(cwd, 'metadata.json', name))
|
|
1141
|
+
continue;
|
|
1142
|
+
manifests.push(syncFortemiCoreIndex(cwd, { ...options, graph: name }));
|
|
1143
|
+
}
|
|
1144
|
+
catch (err) {
|
|
1145
|
+
failures.push({ graph: name, status: 'failed', error: err instanceof Error ? err.message : String(err) });
|
|
1146
|
+
}
|
|
1106
1147
|
}
|
|
1148
|
+
if (failures.length)
|
|
1149
|
+
process.exitCode = 1;
|
|
1107
1150
|
if (json) {
|
|
1108
|
-
console.log(JSON.stringify({ manifests }, null, 2));
|
|
1151
|
+
console.log(JSON.stringify({ manifests, failures }, null, 2));
|
|
1109
1152
|
return;
|
|
1110
1153
|
}
|
|
1111
|
-
console.log(`Fortemi Core sync: ${manifests.length} graph(s)`);
|
|
1154
|
+
console.log(`Fortemi Core sync: ${manifests.length} graph(s) succeeded, ${failures.length} failed`);
|
|
1112
1155
|
for (const manifest of manifests) {
|
|
1113
1156
|
console.log(` ${manifest.graph}: ${manifest.status}, ${manifest.item_count} item(s) → ${manifest.export_path}`);
|
|
1114
1157
|
}
|
|
1158
|
+
for (const failure of failures) {
|
|
1159
|
+
console.error(` ${failure.graph}: failed — ${failure.error}`);
|
|
1160
|
+
}
|
|
1115
1161
|
return;
|
|
1116
1162
|
}
|
|
1117
1163
|
const manifest = syncFortemiCoreIndex(cwd, {
|
|
@@ -1480,7 +1526,7 @@ async function handleDiscover(args) {
|
|
|
1480
1526
|
* artifact by type and name.
|
|
1481
1527
|
*
|
|
1482
1528
|
* Shape (#1218):
|
|
1483
|
-
* aiwg show <type> <name> [--json] [--first] [--graph <name>] [--backend local|fortemi-core]
|
|
1529
|
+
* aiwg show <type> <name> [--json] [--first] [--bound-rule-bodies] [--graph <name>] [--backend local|fortemi-core]
|
|
1484
1530
|
*
|
|
1485
1531
|
* Type is positional (not a flag) so the verb reads as
|
|
1486
1532
|
* "show <kind> <name>". `<type>` is one of the operational show types.
|
|
@@ -1504,8 +1550,8 @@ async function handleShow(args) {
|
|
|
1504
1550
|
}
|
|
1505
1551
|
const HELP_TEXT = [
|
|
1506
1552
|
'',
|
|
1507
|
-
'Usage: aiwg show <type> <name> [--json] [--first] [--graph <name>] [--backend local|fortemi-core] [--resource-source local|web|auto] [--aiwg-version <version|range|digest|channel>] [--offline]',
|
|
1508
|
-
' aiwg show metadata <id-or-name-or-path> [--json] [--first] [--graph <name>] [--backend local|fortemi-core] [--resource-source local|web|auto] [--aiwg-version <version|range|digest|channel>] [--offline]',
|
|
1553
|
+
'Usage: aiwg show <type> <name> [--json] [--first] [--bound-rule-bodies] [--graph <name>] [--backend local|fortemi-core] [--resource-source local|web|auto] [--aiwg-version <version|range|digest|channel>] [--offline]',
|
|
1554
|
+
' aiwg show metadata <id-or-name-or-path> [--json] [--first] [--bound-rule-bodies] [--graph <name>] [--backend local|fortemi-core] [--resource-source local|web|auto] [--aiwg-version <version|range|digest|channel>] [--offline]',
|
|
1509
1555
|
' aiwg index show <type> <name> ...',
|
|
1510
1556
|
'',
|
|
1511
1557
|
`Types: ${OPERATIONAL_SHOW_TYPES.join(' | ')}`,
|
|
@@ -1521,6 +1567,10 @@ async function handleShow(args) {
|
|
|
1521
1567
|
' aiwg show command discover',
|
|
1522
1568
|
' aiwg show skill intake-wizard --resource-source web --aiwg-version stable',
|
|
1523
1569
|
'',
|
|
1570
|
+
'Bound rules: summaries and show pointers are appended for bound skills, agents, and flows.',
|
|
1571
|
+
'Fetch and follow every required_rule_checks entry before starting governed work; summaries do not replace full rules.',
|
|
1572
|
+
'Use --bound-rule-bodies to include their full text (JSON: bound_rules[].content).',
|
|
1573
|
+
'',
|
|
1524
1574
|
'Tip: use `aiwg discover "<phrase>" --json` first to find the stable id.',
|
|
1525
1575
|
].join('\n');
|
|
1526
1576
|
if (positional.length === 0) {
|
|
@@ -1584,6 +1634,7 @@ async function handleShow(args) {
|
|
|
1584
1634
|
: webReleaseOptionsFromEnvironment();
|
|
1585
1635
|
const params = {
|
|
1586
1636
|
name,
|
|
1637
|
+
boundRuleBodies: flags.includes('--bound-rule-bodies'),
|
|
1587
1638
|
typeFilter: type ? [type] : undefined,
|
|
1588
1639
|
json,
|
|
1589
1640
|
first,
|
|
@@ -238,7 +238,7 @@ export function computeSnapshot(root, options = {}) {
|
|
|
238
238
|
if (r.year)
|
|
239
239
|
years.push(r.year);
|
|
240
240
|
inc(sourceTypes, r.sourceType || 'other');
|
|
241
|
-
const grade = r.
|
|
241
|
+
const grade = r.grade?.trim().toUpperCase();
|
|
242
242
|
if (!grade)
|
|
243
243
|
grades.Missing++;
|
|
244
244
|
else if (CONTROLLED_GRADES.includes(grade))
|
|
@@ -60,6 +60,7 @@ const codexAdapter = {
|
|
|
60
60
|
// function's own documented default (see extractPages() below).
|
|
61
61
|
timeout: positiveTimeoutMs(ctx.timeoutSec * 1000, 240_000),
|
|
62
62
|
encoding: 'utf8',
|
|
63
|
+
killSignal: 'SIGKILL',
|
|
63
64
|
});
|
|
64
65
|
if (r.status === 0 && fs.existsSync(tmp)) {
|
|
65
66
|
const text = fs.readFileSync(tmp, 'utf8');
|
|
@@ -174,6 +175,7 @@ function commandAdapter(template) {
|
|
|
174
175
|
const r = spawnSync('sh', ['-c', cmd, 'aiwg-vision', imagePath, promptFile, out], {
|
|
175
176
|
timeout: positiveTimeoutMs(ctx.timeoutSec * 1000, 240_000), encoding: 'utf8',
|
|
176
177
|
env: { ...process.env, AIWG_VISION_IMAGE: imagePath, AIWG_VISION_PROMPT_FILE: promptFile, AIWG_VISION_OUT: out },
|
|
178
|
+
killSignal: 'SIGKILL',
|
|
177
179
|
});
|
|
178
180
|
let text;
|
|
179
181
|
if (fs.existsSync(out))
|