Phase 0 of the Dynamic Context Management epic (#1671): the ADR (documentation) plus a non-shipping reference example under examples/dynamic-context-management/ — the Option-E predicate fact-store parser/selector, a self-contained --check/--write/--select index generator, a sample index, and a runnable demo. The example is intentionally excluded from the build (src/->bin/lib/), the npm package files[], the installer, and the CI test suite (tests/) — nothing here is compiled into or installed with GSD. Production implementation lands in a later phase. Resolves #1672 Refs #1671 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
91 lines
3.5 KiB
JavaScript
91 lines
3.5 KiB
JavaScript
#!/usr/bin/env node
|
|
'use strict';
|
|
|
|
/**
|
|
* Reference example (NOT shipped, NOT compiled, NOT installed) for ADR-1671,
|
|
* "Dynamic context management platform" — the Option-E predicate fact-store.
|
|
*
|
|
* Builds a deterministic, drift-guarded index of every predicate fact in the
|
|
* repo-root CONTEXT.md, and demonstrates a JIT "task -> relevant predicates"
|
|
* selector. Self-contained: depends only on the sibling context-predicates.cjs.
|
|
*
|
|
* Usage (run from the repo root):
|
|
* node examples/dynamic-context-management/gen-context-index.cjs # print index to stdout
|
|
* node examples/dynamic-context-management/gen-context-index.cjs --write # write CONTEXT-INDEX.json (next to this file)
|
|
* node examples/dynamic-context-management/gen-context-index.cjs --check # exit 1 if the committed sample is stale
|
|
* node examples/dynamic-context-management/gen-context-index.cjs --select <query>
|
|
*
|
|
* --select <query> tries, in order: exact class ("PRED"), dotted prefix
|
|
* ("PRED.k320"), then free-text contains — the first non-empty match wins.
|
|
*/
|
|
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
|
|
const { parsePredicates, selectPredicates, buildIndex } = require('./context-predicates.cjs');
|
|
|
|
const REPO_ROOT = path.resolve(__dirname, '..', '..');
|
|
const CONTEXT_PATH = path.join(REPO_ROOT, 'CONTEXT.md');
|
|
const INDEX_PATH = path.join(__dirname, 'CONTEXT-INDEX.json');
|
|
|
|
function buildFreshIndex() {
|
|
const markdown = fs.readFileSync(CONTEXT_PATH, 'utf8');
|
|
const { predicates } = parsePredicates(markdown);
|
|
return buildIndex(predicates);
|
|
}
|
|
|
|
function main(args) {
|
|
const flag = args[0];
|
|
|
|
if (flag === '--check') {
|
|
const committed = JSON.parse(fs.readFileSync(INDEX_PATH, 'utf8'));
|
|
const live = buildFreshIndex();
|
|
if (JSON.stringify(committed, null, 2) !== JSON.stringify(live, null, 2)) {
|
|
process.stderr.write(
|
|
'CONTEXT-INDEX.json is stale. Run:\n' +
|
|
' node examples/dynamic-context-management/gen-context-index.cjs --write\n',
|
|
);
|
|
return 1;
|
|
}
|
|
process.stdout.write('CONTEXT-INDEX.json is up to date.\n');
|
|
return 0;
|
|
}
|
|
|
|
if (flag === '--write') {
|
|
const index = buildFreshIndex();
|
|
fs.writeFileSync(INDEX_PATH, JSON.stringify(index, null, 2) + '\n');
|
|
const dupNote = index.duplicates.length > 0
|
|
? ` (${index.duplicates.length} duplicate id${index.duplicates.length !== 1 ? 's' : ''})`
|
|
: '';
|
|
process.stdout.write(
|
|
`Wrote ${path.relative(REPO_ROOT, INDEX_PATH)}\n` +
|
|
` ${index.count} predicates, ${Object.keys(index.classes).length} classes${dupNote}\n`,
|
|
);
|
|
return 0;
|
|
}
|
|
|
|
if (flag === '--select') {
|
|
const query = args[1];
|
|
if (!query) {
|
|
process.stderr.write('Usage: gen-context-index.cjs --select <query>\n');
|
|
return 1;
|
|
}
|
|
const { predicates } = parsePredicates(fs.readFileSync(CONTEXT_PATH, 'utf8'));
|
|
let results = selectPredicates(predicates, { klass: query });
|
|
if (results.length === 0) results = selectPredicates(predicates, { prefix: query });
|
|
if (results.length === 0) results = selectPredicates(predicates, { contains: query });
|
|
if (results.length === 0) {
|
|
process.stdout.write(`No predicates matched: ${query}\n`);
|
|
return 0;
|
|
}
|
|
for (const p of results) process.stdout.write(`${p.id} = ${p.value}\n`);
|
|
process.stdout.write(`\n(${results.length} predicate${results.length !== 1 ? 's' : ''} matched)\n`);
|
|
return 0;
|
|
}
|
|
|
|
process.stdout.write(JSON.stringify(buildFreshIndex(), null, 2) + '\n');
|
|
return 0;
|
|
}
|
|
|
|
process.exitCode = main(process.argv.slice(2));
|