@abaigram/abaikit 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/abai/learnabai.md +104 -32
- package/dist/abaify.d.ts.map +1 -1
- package/dist/abaify.js +1 -1
- package/dist/abaify.js.map +1 -1
- package/dist/bin.d.ts +2 -1
- package/dist/bin.d.ts.map +1 -1
- package/dist/bin.js +4 -4
- package/dist/bin.js.map +1 -1
- package/dist/check.d.ts.map +1 -1
- package/dist/check.js +2 -2
- package/dist/check.js.map +1 -1
- package/dist/learnabai.d.ts.map +1 -1
- package/dist/learnabai.js +4 -2
- package/dist/learnabai.js.map +1 -1
- package/dist/template-ts.d.ts.map +1 -1
- package/dist/template-ts.js +1 -1
- package/dist/template-ts.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +3 -3
package/dist/bin.js
CHANGED
|
@@ -18,9 +18,9 @@ export { processIo, UsageError } from "./io.js";
|
|
|
18
18
|
const USAGE = [
|
|
19
19
|
"usage: abaikit learnabai|check|new|abaify|run ...",
|
|
20
20
|
" abaikit learnabai [--section <name>] [--json] [--skill] [--skill-dir <dir>]",
|
|
21
|
-
" abaikit check <repo> [--level <1-4>] [--mode <turns|sidecar>] [--entry <cmd>] [--runs <n>] [--timeout <seconds>] [--json]",
|
|
21
|
+
" abaikit check <repo> [--level <1-4>] [--mode <turns|thread|sidecar>] [--entry <cmd>] [--runs <n>] [--timeout <seconds>] [--json]",
|
|
22
22
|
" abaikit new <name> --lang <ts> [--level <1-4>] [--dir <dir>]",
|
|
23
|
-
" abaikit abaify <repo> [--level <1-4>] [--mode <turns|sidecar>] [--rounds <n>] [--dry-run]",
|
|
23
|
+
" abaikit abaify <repo> [--level <1-4>] [--mode <turns|thread|sidecar>] [--rounds <n>] [--dry-run]",
|
|
24
24
|
" abaikit run <repo> [--] ARGS",
|
|
25
25
|
" abaikit abai ... the standard agent entry (session, install, manifest, doctor, config, mcp, run)",
|
|
26
26
|
"",
|
|
@@ -84,8 +84,8 @@ function scan(verb, argv, kinds) {
|
|
|
84
84
|
break;
|
|
85
85
|
}
|
|
86
86
|
case "mode":
|
|
87
|
-
if (value !== "turns" && value !== "sidecar")
|
|
88
|
-
throw new UsageError(`${arg} needs turns or sidecar`);
|
|
87
|
+
if (value !== "turns" && value !== "thread" && value !== "sidecar")
|
|
88
|
+
throw new UsageError(`${arg} needs turns, thread or sidecar`);
|
|
89
89
|
values[arg] = value;
|
|
90
90
|
break;
|
|
91
91
|
}
|
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n// The abaikit binary: learnabai prints the guide, check verifies a\n// repository's conformance, new creates a fresh abaigram, abaify retrofits\n// an existing repository, and run starts a repository's program with an\n// agent attached. `abaikit abai ...` is abaikit's own standard agent entry,\n// served by the stub, since abaikit is itself an abaigram.\nimport { realpathSync } from \"node:fs\";\nimport { pathToFileURL } from \"node:url\";\nimport { runEntry } from \"@abaigram/abai-stub\";\nimport { runAbaify } from \"./abaify.ts\";\nimport { type AbaikitApp, createApp } from \"./app.ts\";\nimport { runCheck } from \"./check.ts\";\nimport { type AbaikitIo, errorMessage, processIo, UsageError } from \"./io.ts\";\nimport { runLearnabai } from \"./learnabai.ts\";\nimport { runNew } from \"./new.ts\";\nimport { runRun } from \"./run.ts\";\n\nexport { type AbaikitIo, processIo, UsageError } from \"./io.ts\";\n\nexport type Mode = \"turns\" | \"sidecar\";\n\nexport type ParsedArgs =\n\t| { verb: \"help\" }\n\t| { verb: \"learnabai\"; section?: string; json: boolean; skill: boolean; skillDir?: string }\n\t| {\n\t\t\tverb: \"check\";\n\t\t\trepo: string;\n\t\t\tlevel?: number;\n\t\t\tmode?: Mode;\n\t\t\tentry?: string;\n\t\t\truns?: number;\n\t\t\ttimeoutS?: number;\n\t\t\tjson: boolean;\n\t }\n\t| { verb: \"new\"; name: string; lang: \"ts\"; level?: number; dir?: string; abaiImport?: string }\n\t| { verb: \"abaify\"; repo: string; level?: number; mode?: Mode; rounds?: number; dryRun: boolean }\n\t| { verb: \"run\"; repo: string; args: string[] };\n\nexport type Verb = ParsedArgs[\"verb\"];\n\nconst USAGE = [\n\t\"usage: abaikit learnabai|check|new|abaify|run ...\",\n\t\" abaikit learnabai [--section <name>] [--json] [--skill] [--skill-dir <dir>]\",\n\t\" abaikit check <repo> [--level <1-4>] [--mode <turns|sidecar>] [--entry <cmd>] [--runs <n>] [--timeout <seconds>] [--json]\",\n\t\" abaikit new <name> --lang <ts> [--level <1-4>] [--dir <dir>]\",\n\t\" abaikit abaify <repo> [--level <1-4>] [--mode <turns|sidecar>] [--rounds <n>] [--dry-run]\",\n\t\" abaikit run <repo> [--] ARGS\",\n\t\" abaikit abai ... the standard agent entry (session, install, manifest, doctor, config, mcp, run)\",\n\t\"\",\n\t\"learnabai prints the guide for an agent; check verifies a repository's conformance and needs no model;\",\n\t\"new creates a fresh abaigram; abaify retrofits an existing repository, adding and never removing;\",\n\t\"run starts the repository's program with everything after -- as its arguments.\",\n];\n\ntype FlagKind = \"bool\" | \"string\" | \"int\" | \"level\" | \"mode\";\n\nfunction positiveInt(value: string, flag: string): number {\n\tconst n = Number(value);\n\tif (!Number.isInteger(n) || n <= 0) throw new UsageError(`${flag} needs a positive integer`);\n\treturn n;\n}\n\n/** The verb's flags and positionals; a flag missing its value, an unknown flag or a stray argument is a usage error. */\nfunction scan(\n\tverb: string,\n\targv: string[],\n\tkinds: Record<string, FlagKind>,\n): { positionals: string[]; values: Record<string, string | number | boolean> } {\n\tconst positionals: string[] = [];\n\tconst values: Record<string, string | number | boolean> = {};\n\tfor (let i = 0; i < argv.length; i++) {\n\t\tconst raw = argv[i];\n\t\tif (raw === \"--\") throw new UsageError(`${verb} takes no program command`);\n\t\tif (!raw.startsWith(\"-\")) {\n\t\t\tpositionals.push(raw);\n\t\t\tcontinue;\n\t\t}\n\t\t// `--flag value` and `--flag=value`, as the stub's entry accepts them\n\t\tconst eq = raw.indexOf(\"=\");\n\t\tconst arg = eq === -1 ? raw : raw.slice(0, eq);\n\t\tconst kind = kinds[arg];\n\t\tif (kind === undefined) throw new UsageError(`unknown argument ${arg}`);\n\t\tif (kind === \"bool\") {\n\t\t\tif (eq !== -1) throw new UsageError(`${arg} takes no value`);\n\t\t\tvalues[arg] = true;\n\t\t\tcontinue;\n\t\t}\n\t\tlet value: string | undefined;\n\t\tif (eq !== -1) value = raw.slice(eq + 1);\n\t\telse {\n\t\t\tvalue = argv[i + 1];\n\t\t\tif (value === undefined || value.startsWith(\"--\")) throw new UsageError(`${arg} needs a value`);\n\t\t\ti += 1;\n\t\t}\n\t\tif (value === \"\") throw new UsageError(`${arg} needs a value`);\n\t\tswitch (kind) {\n\t\t\tcase \"string\":\n\t\t\t\tvalues[arg] = value;\n\t\t\t\tbreak;\n\t\t\tcase \"int\":\n\t\t\t\tvalues[arg] = positiveInt(value, arg);\n\t\t\t\tbreak;\n\t\t\tcase \"level\": {\n\t\t\t\tconst n = Number(value);\n\t\t\t\tif (!Number.isInteger(n) || n < 1 || n > 4) throw new UsageError(`${arg} needs a level from 1 to 4`);\n\t\t\t\tvalues[arg] = n;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"mode\":\n\t\t\t\tif (value !== \"turns\" && value !== \"sidecar\") throw new UsageError(`${arg} needs turns or sidecar`);\n\t\t\t\tvalues[arg] = value;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn { positionals, values };\n}\n\n/** Exactly one positional, named `what` in the error. */\nfunction one(verb: string, positionals: string[], what: string): string {\n\tif (positionals.length === 0) throw new UsageError(`${verb} needs ${what}`);\n\tif (positionals.length > 1) throw new UsageError(`unexpected argument ${positionals[1]}`);\n\treturn positionals[0];\n}\n\nexport function parseArgs(argv: string[]): ParsedArgs {\n\tconst verb = argv[0];\n\tif (verb === undefined || verb === \"help\" || verb === \"--help\" || verb === \"-h\") return { verb: \"help\" };\n\tconst rest = argv.slice(1);\n\tswitch (verb) {\n\t\tcase \"learnabai\": {\n\t\t\tconst { positionals, values } = scan(verb, rest, {\n\t\t\t\t\"--section\": \"string\",\n\t\t\t\t\"--json\": \"bool\",\n\t\t\t\t\"--skill\": \"bool\",\n\t\t\t\t\"--skill-dir\": \"string\",\n\t\t\t});\n\t\t\tif (positionals.length > 0) throw new UsageError(`unexpected argument ${positionals[0]}`);\n\t\t\tif (values[\"--skill-dir\"] !== undefined && values[\"--skill\"] !== true)\n\t\t\t\tthrow new UsageError(\"--skill-dir goes with --skill\");\n\t\t\treturn {\n\t\t\t\tverb,\n\t\t\t\tsection: values[\"--section\"] as string | undefined,\n\t\t\t\tjson: values[\"--json\"] === true,\n\t\t\t\tskill: values[\"--skill\"] === true,\n\t\t\t\tskillDir: values[\"--skill-dir\"] as string | undefined,\n\t\t\t};\n\t\t}\n\t\tcase \"check\": {\n\t\t\tconst { positionals, values } = scan(verb, rest, {\n\t\t\t\t\"--level\": \"level\",\n\t\t\t\t\"--mode\": \"mode\",\n\t\t\t\t\"--entry\": \"string\",\n\t\t\t\t\"--runs\": \"int\",\n\t\t\t\t\"--timeout\": \"int\",\n\t\t\t\t\"--json\": \"bool\",\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tverb,\n\t\t\t\trepo: one(verb, positionals, \"a repository\"),\n\t\t\t\tlevel: values[\"--level\"] as number | undefined,\n\t\t\t\tmode: values[\"--mode\"] as Mode | undefined,\n\t\t\t\tentry: values[\"--entry\"] as string | undefined,\n\t\t\t\truns: values[\"--runs\"] as number | undefined,\n\t\t\t\ttimeoutS: values[\"--timeout\"] as number | undefined,\n\t\t\t\tjson: values[\"--json\"] === true,\n\t\t\t};\n\t\t}\n\t\tcase \"new\": {\n\t\t\tconst { positionals, values } = scan(verb, rest, {\n\t\t\t\t\"--lang\": \"string\",\n\t\t\t\t\"--level\": \"level\",\n\t\t\t\t\"--dir\": \"string\",\n\t\t\t\t\"--abai-import\": \"string\",\n\t\t\t});\n\t\t\tconst name = one(verb, positionals, \"a name\");\n\t\t\tconst lang = values[\"--lang\"];\n\t\t\tif (lang === undefined) throw new UsageError(\"new needs --lang <ts>\");\n\t\t\tif (lang !== \"ts\") throw new UsageError(`unknown language ${lang}; only ts is supported`);\n\t\t\treturn {\n\t\t\t\tverb,\n\t\t\t\tname,\n\t\t\t\tlang,\n\t\t\t\tlevel: values[\"--level\"] as number | undefined,\n\t\t\t\tdir: values[\"--dir\"] as string | undefined,\n\t\t\t\tabaiImport: values[\"--abai-import\"] as string | undefined,\n\t\t\t};\n\t\t}\n\t\tcase \"abaify\": {\n\t\t\tconst { positionals, values } = scan(verb, rest, {\n\t\t\t\t\"--level\": \"level\",\n\t\t\t\t\"--mode\": \"mode\",\n\t\t\t\t\"--rounds\": \"int\",\n\t\t\t\t\"--dry-run\": \"bool\",\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tverb,\n\t\t\t\trepo: one(verb, positionals, \"a repository\"),\n\t\t\t\tlevel: values[\"--level\"] as number | undefined,\n\t\t\t\tmode: values[\"--mode\"] as Mode | undefined,\n\t\t\t\trounds: values[\"--rounds\"] as number | undefined,\n\t\t\t\tdryRun: values[\"--dry-run\"] === true,\n\t\t\t};\n\t\t}\n\t\tcase \"run\": {\n\t\t\t// the repository, then the program's arguments; `--` before them is allowed, as in the stub's own run\n\t\t\tconst repo = rest[0];\n\t\t\tif (repo === undefined || repo.startsWith(\"-\")) throw new UsageError(\"run needs a repository\");\n\t\t\tconst after = rest.slice(1);\n\t\t\treturn { verb, repo, args: after[0] === \"--\" ? after.slice(1) : after };\n\t\t}\n\t\tdefault:\n\t\t\tthrow new UsageError(`unknown verb ${verb}`);\n\t}\n}\n\n/** The binary's entry; resolves to the exit code and never throws. */\nexport async function main(argv: string[], io: AbaikitIo = processIo): Promise<number> {\n\t// abaikit is an abaigram, built before anything else so its own entry, its null harness under check runs and\n\t// its capabilities are there whichever verb runs (section 13: main hands control to the harness at once)\n\tlet bundle: AbaikitApp;\n\ttry {\n\t\tbundle = createApp(io);\n\t} catch (error) {\n\t\tio.err(`abaikit: ${errorMessage(error)}`);\n\t\treturn 1;\n\t}\n\tconst { app } = bundle;\n\ttry {\n\t\tconst code = await runEntry(app, argv, io);\n\t\tif (code >= 0) return code;\n\t} catch (error) {\n\t\tio.err(`abaikit abai: ${errorMessage(error)}`);\n\t\treturn 1;\n\t}\n\tlet parsed: ParsedArgs;\n\ttry {\n\t\tparsed = parseArgs(argv);\n\t} catch (error) {\n\t\tio.err(`abaikit: ${errorMessage(error)}`);\n\t\tfor (const line of USAGE) io.err(line);\n\t\treturn 2;\n\t}\n\ttry {\n\t\tswitch (parsed.verb) {\n\t\t\tcase \"help\":\n\t\t\t\tfor (const line of USAGE) io.out(`${line}\\n`);\n\t\t\t\treturn 0;\n\t\t\tcase \"learnabai\":\n\t\t\t\treturn await runLearnabai(parsed, io);\n\t\t\tcase \"check\":\n\t\t\t\treturn await runCheck(parsed, io, app);\n\t\t\tcase \"new\":\n\t\t\t\treturn await runNew(parsed, io);\n\t\t\tcase \"abaify\":\n\t\t\t\treturn await runAbaify(parsed, io, bundle);\n\t\t\tcase \"run\":\n\t\t\t\treturn await runRun(parsed, io);\n\t\t}\n\t} catch (error) {\n\t\tif (error instanceof UsageError) {\n\t\t\tio.err(`abaikit: ${error.message}`);\n\t\t\treturn 2;\n\t\t}\n\t\tio.err(`abaikit ${parsed.verb}: ${errorMessage(error)}`);\n\t\treturn 1;\n\t}\n}\n\n/** Whether this module is the process's entry: by its real path, so a relative path or npm's bin symlink both count. */\nfunction isEntry(): boolean {\n\tconst entry = process.argv[1];\n\tif (entry === undefined) return false;\n\ttry {\n\t\treturn import.meta.url === pathToFileURL(realpathSync(entry)).href;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nif (isEntry()) {\n\tmain(process.argv.slice(2)).then((code) => {\n\t\tprocess.exitCode = code;\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n// The abaikit binary: learnabai prints the guide, check verifies a\n// repository's conformance, new creates a fresh abaigram, abaify retrofits\n// an existing repository, and run starts a repository's program with an\n// agent attached. `abaikit abai ...` is abaikit's own standard agent entry,\n// served by the stub, since abaikit is itself an abaigram.\nimport { realpathSync } from \"node:fs\";\nimport { pathToFileURL } from \"node:url\";\nimport { type Mode, runEntry } from \"@abaigram/abai-stub\";\nimport { runAbaify } from \"./abaify.ts\";\nimport { type AbaikitApp, createApp } from \"./app.ts\";\nimport { runCheck } from \"./check.ts\";\nimport { type AbaikitIo, errorMessage, processIo, UsageError } from \"./io.ts\";\nimport { runLearnabai } from \"./learnabai.ts\";\nimport { runNew } from \"./new.ts\";\nimport { runRun } from \"./run.ts\";\n\nexport { type AbaikitIo, processIo, UsageError } from \"./io.ts\";\n\nexport type { Mode };\n\nexport type ParsedArgs =\n\t| { verb: \"help\" }\n\t| { verb: \"learnabai\"; section?: string; json: boolean; skill: boolean; skillDir?: string }\n\t| {\n\t\t\tverb: \"check\";\n\t\t\trepo: string;\n\t\t\tlevel?: number;\n\t\t\tmode?: Mode;\n\t\t\tentry?: string;\n\t\t\truns?: number;\n\t\t\ttimeoutS?: number;\n\t\t\tjson: boolean;\n\t }\n\t| { verb: \"new\"; name: string; lang: \"ts\"; level?: number; dir?: string; abaiImport?: string }\n\t| { verb: \"abaify\"; repo: string; level?: number; mode?: Mode; rounds?: number; dryRun: boolean }\n\t| { verb: \"run\"; repo: string; args: string[] };\n\nexport type Verb = ParsedArgs[\"verb\"];\n\nconst USAGE = [\n\t\"usage: abaikit learnabai|check|new|abaify|run ...\",\n\t\" abaikit learnabai [--section <name>] [--json] [--skill] [--skill-dir <dir>]\",\n\t\" abaikit check <repo> [--level <1-4>] [--mode <turns|thread|sidecar>] [--entry <cmd>] [--runs <n>] [--timeout <seconds>] [--json]\",\n\t\" abaikit new <name> --lang <ts> [--level <1-4>] [--dir <dir>]\",\n\t\" abaikit abaify <repo> [--level <1-4>] [--mode <turns|thread|sidecar>] [--rounds <n>] [--dry-run]\",\n\t\" abaikit run <repo> [--] ARGS\",\n\t\" abaikit abai ... the standard agent entry (session, install, manifest, doctor, config, mcp, run)\",\n\t\"\",\n\t\"learnabai prints the guide for an agent; check verifies a repository's conformance and needs no model;\",\n\t\"new creates a fresh abaigram; abaify retrofits an existing repository, adding and never removing;\",\n\t\"run starts the repository's program with everything after -- as its arguments.\",\n];\n\ntype FlagKind = \"bool\" | \"string\" | \"int\" | \"level\" | \"mode\";\n\nfunction positiveInt(value: string, flag: string): number {\n\tconst n = Number(value);\n\tif (!Number.isInteger(n) || n <= 0) throw new UsageError(`${flag} needs a positive integer`);\n\treturn n;\n}\n\n/** The verb's flags and positionals; a flag missing its value, an unknown flag or a stray argument is a usage error. */\nfunction scan(\n\tverb: string,\n\targv: string[],\n\tkinds: Record<string, FlagKind>,\n): { positionals: string[]; values: Record<string, string | number | boolean> } {\n\tconst positionals: string[] = [];\n\tconst values: Record<string, string | number | boolean> = {};\n\tfor (let i = 0; i < argv.length; i++) {\n\t\tconst raw = argv[i];\n\t\tif (raw === \"--\") throw new UsageError(`${verb} takes no program command`);\n\t\tif (!raw.startsWith(\"-\")) {\n\t\t\tpositionals.push(raw);\n\t\t\tcontinue;\n\t\t}\n\t\t// `--flag value` and `--flag=value`, as the stub's entry accepts them\n\t\tconst eq = raw.indexOf(\"=\");\n\t\tconst arg = eq === -1 ? raw : raw.slice(0, eq);\n\t\tconst kind = kinds[arg];\n\t\tif (kind === undefined) throw new UsageError(`unknown argument ${arg}`);\n\t\tif (kind === \"bool\") {\n\t\t\tif (eq !== -1) throw new UsageError(`${arg} takes no value`);\n\t\t\tvalues[arg] = true;\n\t\t\tcontinue;\n\t\t}\n\t\tlet value: string | undefined;\n\t\tif (eq !== -1) value = raw.slice(eq + 1);\n\t\telse {\n\t\t\tvalue = argv[i + 1];\n\t\t\tif (value === undefined || value.startsWith(\"--\")) throw new UsageError(`${arg} needs a value`);\n\t\t\ti += 1;\n\t\t}\n\t\tif (value === \"\") throw new UsageError(`${arg} needs a value`);\n\t\tswitch (kind) {\n\t\t\tcase \"string\":\n\t\t\t\tvalues[arg] = value;\n\t\t\t\tbreak;\n\t\t\tcase \"int\":\n\t\t\t\tvalues[arg] = positiveInt(value, arg);\n\t\t\t\tbreak;\n\t\t\tcase \"level\": {\n\t\t\t\tconst n = Number(value);\n\t\t\t\tif (!Number.isInteger(n) || n < 1 || n > 4) throw new UsageError(`${arg} needs a level from 1 to 4`);\n\t\t\t\tvalues[arg] = n;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"mode\":\n\t\t\t\tif (value !== \"turns\" && value !== \"thread\" && value !== \"sidecar\")\n\t\t\t\t\tthrow new UsageError(`${arg} needs turns, thread or sidecar`);\n\t\t\t\tvalues[arg] = value;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn { positionals, values };\n}\n\n/** Exactly one positional, named `what` in the error. */\nfunction one(verb: string, positionals: string[], what: string): string {\n\tif (positionals.length === 0) throw new UsageError(`${verb} needs ${what}`);\n\tif (positionals.length > 1) throw new UsageError(`unexpected argument ${positionals[1]}`);\n\treturn positionals[0];\n}\n\nexport function parseArgs(argv: string[]): ParsedArgs {\n\tconst verb = argv[0];\n\tif (verb === undefined || verb === \"help\" || verb === \"--help\" || verb === \"-h\") return { verb: \"help\" };\n\tconst rest = argv.slice(1);\n\tswitch (verb) {\n\t\tcase \"learnabai\": {\n\t\t\tconst { positionals, values } = scan(verb, rest, {\n\t\t\t\t\"--section\": \"string\",\n\t\t\t\t\"--json\": \"bool\",\n\t\t\t\t\"--skill\": \"bool\",\n\t\t\t\t\"--skill-dir\": \"string\",\n\t\t\t});\n\t\t\tif (positionals.length > 0) throw new UsageError(`unexpected argument ${positionals[0]}`);\n\t\t\tif (values[\"--skill-dir\"] !== undefined && values[\"--skill\"] !== true)\n\t\t\t\tthrow new UsageError(\"--skill-dir goes with --skill\");\n\t\t\treturn {\n\t\t\t\tverb,\n\t\t\t\tsection: values[\"--section\"] as string | undefined,\n\t\t\t\tjson: values[\"--json\"] === true,\n\t\t\t\tskill: values[\"--skill\"] === true,\n\t\t\t\tskillDir: values[\"--skill-dir\"] as string | undefined,\n\t\t\t};\n\t\t}\n\t\tcase \"check\": {\n\t\t\tconst { positionals, values } = scan(verb, rest, {\n\t\t\t\t\"--level\": \"level\",\n\t\t\t\t\"--mode\": \"mode\",\n\t\t\t\t\"--entry\": \"string\",\n\t\t\t\t\"--runs\": \"int\",\n\t\t\t\t\"--timeout\": \"int\",\n\t\t\t\t\"--json\": \"bool\",\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tverb,\n\t\t\t\trepo: one(verb, positionals, \"a repository\"),\n\t\t\t\tlevel: values[\"--level\"] as number | undefined,\n\t\t\t\tmode: values[\"--mode\"] as Mode | undefined,\n\t\t\t\tentry: values[\"--entry\"] as string | undefined,\n\t\t\t\truns: values[\"--runs\"] as number | undefined,\n\t\t\t\ttimeoutS: values[\"--timeout\"] as number | undefined,\n\t\t\t\tjson: values[\"--json\"] === true,\n\t\t\t};\n\t\t}\n\t\tcase \"new\": {\n\t\t\tconst { positionals, values } = scan(verb, rest, {\n\t\t\t\t\"--lang\": \"string\",\n\t\t\t\t\"--level\": \"level\",\n\t\t\t\t\"--dir\": \"string\",\n\t\t\t\t\"--abai-import\": \"string\",\n\t\t\t});\n\t\t\tconst name = one(verb, positionals, \"a name\");\n\t\t\tconst lang = values[\"--lang\"];\n\t\t\tif (lang === undefined) throw new UsageError(\"new needs --lang <ts>\");\n\t\t\tif (lang !== \"ts\") throw new UsageError(`unknown language ${lang}; only ts is supported`);\n\t\t\treturn {\n\t\t\t\tverb,\n\t\t\t\tname,\n\t\t\t\tlang,\n\t\t\t\tlevel: values[\"--level\"] as number | undefined,\n\t\t\t\tdir: values[\"--dir\"] as string | undefined,\n\t\t\t\tabaiImport: values[\"--abai-import\"] as string | undefined,\n\t\t\t};\n\t\t}\n\t\tcase \"abaify\": {\n\t\t\tconst { positionals, values } = scan(verb, rest, {\n\t\t\t\t\"--level\": \"level\",\n\t\t\t\t\"--mode\": \"mode\",\n\t\t\t\t\"--rounds\": \"int\",\n\t\t\t\t\"--dry-run\": \"bool\",\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tverb,\n\t\t\t\trepo: one(verb, positionals, \"a repository\"),\n\t\t\t\tlevel: values[\"--level\"] as number | undefined,\n\t\t\t\tmode: values[\"--mode\"] as Mode | undefined,\n\t\t\t\trounds: values[\"--rounds\"] as number | undefined,\n\t\t\t\tdryRun: values[\"--dry-run\"] === true,\n\t\t\t};\n\t\t}\n\t\tcase \"run\": {\n\t\t\t// the repository, then the program's arguments; `--` before them is allowed, as in the stub's own run\n\t\t\tconst repo = rest[0];\n\t\t\tif (repo === undefined || repo.startsWith(\"-\")) throw new UsageError(\"run needs a repository\");\n\t\t\tconst after = rest.slice(1);\n\t\t\treturn { verb, repo, args: after[0] === \"--\" ? after.slice(1) : after };\n\t\t}\n\t\tdefault:\n\t\t\tthrow new UsageError(`unknown verb ${verb}`);\n\t}\n}\n\n/** The binary's entry; resolves to the exit code and never throws. */\nexport async function main(argv: string[], io: AbaikitIo = processIo): Promise<number> {\n\t// abaikit is an abaigram, built before anything else so its own entry, its null harness under check runs and\n\t// its capabilities are there whichever verb runs (section 13: main hands control to the harness at once)\n\tlet bundle: AbaikitApp;\n\ttry {\n\t\tbundle = createApp(io);\n\t} catch (error) {\n\t\tio.err(`abaikit: ${errorMessage(error)}`);\n\t\treturn 1;\n\t}\n\tconst { app } = bundle;\n\ttry {\n\t\tconst code = await runEntry(app, argv, io);\n\t\tif (code >= 0) return code;\n\t} catch (error) {\n\t\tio.err(`abaikit abai: ${errorMessage(error)}`);\n\t\treturn 1;\n\t}\n\tlet parsed: ParsedArgs;\n\ttry {\n\t\tparsed = parseArgs(argv);\n\t} catch (error) {\n\t\tio.err(`abaikit: ${errorMessage(error)}`);\n\t\tfor (const line of USAGE) io.err(line);\n\t\treturn 2;\n\t}\n\ttry {\n\t\tswitch (parsed.verb) {\n\t\t\tcase \"help\":\n\t\t\t\tfor (const line of USAGE) io.out(`${line}\\n`);\n\t\t\t\treturn 0;\n\t\t\tcase \"learnabai\":\n\t\t\t\treturn await runLearnabai(parsed, io);\n\t\t\tcase \"check\":\n\t\t\t\treturn await runCheck(parsed, io, app);\n\t\t\tcase \"new\":\n\t\t\t\treturn await runNew(parsed, io);\n\t\t\tcase \"abaify\":\n\t\t\t\treturn await runAbaify(parsed, io, bundle);\n\t\t\tcase \"run\":\n\t\t\t\treturn await runRun(parsed, io);\n\t\t}\n\t} catch (error) {\n\t\tif (error instanceof UsageError) {\n\t\t\tio.err(`abaikit: ${error.message}`);\n\t\t\treturn 2;\n\t\t}\n\t\tio.err(`abaikit ${parsed.verb}: ${errorMessage(error)}`);\n\t\treturn 1;\n\t}\n}\n\n/** Whether this module is the process's entry: by its real path, so a relative path or npm's bin symlink both count. */\nfunction isEntry(): boolean {\n\tconst entry = process.argv[1];\n\tif (entry === undefined) return false;\n\ttry {\n\t\treturn import.meta.url === pathToFileURL(realpathSync(entry)).href;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nif (isEntry()) {\n\tmain(process.argv.slice(2)).then((code) => {\n\t\tprocess.exitCode = code;\n\t});\n}\n"]}
|
package/dist/check.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"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","sourcesContent":["// abaikit check: conformance as section 12 defines it, with no model.\n// Level 1 is reached through the subject's entry alone (what `manifest`\n// prints, byte for byte the checked-in file, and `doctor --offline --json`); levels 2 to 4 through its `check.run`\n// under the exercise null harness, once per declared mode, read from the\n// report the stub prints at exit; the overhead of 11.6 by the same command\n// under `ABAI_HARNESS=off` and `ABAI_HARNESS=null`, interleaved, side by\n// side. The subject's environment is constructed, never inherited: each\n// run gets exactly the `ABAI_HARNESS` and `ABAI_MODE` it means, the entry\n// runs get neither. A level is the one reached under every checked mode,\n// and passing means that level with no violation.\nimport { readFileSync } from \"node:fs\";\nimport type { Abaigram, DoctorCheck, Manifest, Mode } from \"@abaigram/abai-stub\";\nimport { parseManifestYaml, validateManifest } from \"@abaigram/abai-stub\";\nimport type { ParsedArgs } from \"./bin.ts\";\nimport {\n\ttype CommandRun,\n\tjsonDocument,\n\tlastJsonLine,\n\tlastPlainLine,\n\tmedian,\n\trunCommand,\n\tsubjectEnv,\n\ttailOf,\n} from \"./command.ts\";\nimport { type AbaikitIo, errorMessage, UsageError } from \"./io.ts\";\nimport { entryCommand, loadSubject, type Subject } from \"./subject.ts\";\n\nexport const DEFAULT_RUNS = 3;\nexport const DEFAULT_TIMEOUT_MS = 120_000;\n/** How long an entry verb (manifest, doctor) may take. */\nexport const ENTRY_TIMEOUT_MS = 60_000;\n/** Below this median for the off run, startup noise is most of the number. */\nexport const NOISE_FLOOR_MS = 500;\n/** Characters of a run's output the JSON report carries. */\nconst REPORT_TAIL_CHARS = 4096;\nexport const LEVEL_NAMES = [\"none\", \"reachable\", \"observable\", \"steerable\", \"deliberative\"] as const;\n\nexport interface CheckOptions {\n\trepo: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n\tlevel?: number;\n\tmode?: Mode;\n\tentry?: string;\n\truns?: number;\n\ttimeoutMs?: number;\n}\n\n/** What the stub's exercise harness reports at exit (abai's NullHarnessReport, as JSON on stderr). */\nexport interface ExerciseReport {\n\tform: string;\n\tevents: number;\n\tdropped: number;\n\tdecisions: number;\n\tturns: number;\n\ttouchpoints: number;\n\tcellsWritten: string[];\n\t/** The program's own events, by name; absent in a report from an older stub. */\n\teventsEmitted?: string[];\n\tknobsWritten: string[];\n\tcapabilitiesCalled: string[];\n\tunexercised: Array<{ kind: string; name: string; why: string }>;\n}\n\nexport interface Measurement {\n\truns: number;\n\toff: number[];\n\tnull: number[];\n\toffMedianMs: number;\n\tnullMedianMs: number;\n\t/** null over off, minus one; NaN when either side has no run. */\n\tslowdown: number;\n\tlimit?: number;\n\t/** The runs that did not exit 0 or timed out, by harness. */\n\tfailed: string[];\n\t/** The numbers are within startup noise or the two ranges overlap. */\n\twithinNoise: boolean;\n}\n\nexport interface ModeResult {\n\tmode: Mode;\n\t/** The highest level this mode demonstrated, 1 to 4. */\n\tlevel: number;\n\texercise?: { run: CommandRun; report?: ExerciseReport };\n\tevidence: { l2: string; l3: string; l4: string };\n\tmeasurement?: Measurement;\n}\n\nexport interface Violation {\n\twhere: string;\n\twhat: string;\n}\n\nexport interface CheckReport {\n\troot: string;\n\tname: string;\n\tabaigrammar: string;\n\tentry: string;\n\tdeclaredModes: Mode[];\n\tcheckedModes: Mode[];\n\tcheckRun?: string;\n\toverheadLimit?: string;\n\t/** This instantiation offers no build with the stub compiled out, and builds nothing: the command runs as is. */\n\tcompiledOut: \"not offered\";\n\tbuilt: \"no\";\n\tl1: { ok: boolean; manifestAgrees: boolean; doctor: DoctorCheck[]; ran: string[]; detail: string };\n\tperMode: ModeResult[];\n\tlevel: number;\n\trequested?: number;\n\tpassed: boolean;\n\tunexercised: Array<{ mode: Mode; kind: string; name: string; why: string }>;\n\tviolations: Violation[];\n\tnotes: string[];\n}\n\nfunction parseOverhead(limit: string | undefined): number | undefined {\n\tif (limit === undefined) return undefined;\n\tconst match = /^(\\d+(?:\\.\\d+)?)\\s*%$/.exec(limit.trim());\n\treturn match ? Number(match[1]) / 100 : undefined;\n}\n\nfunction firstDifferingLine(a: string, b: string): number {\n\tconst al = a.split(\"\\n\");\n\tconst bl = b.split(\"\\n\");\n\tfor (let i = 0; i < Math.max(al.length, bl.length); i++) if (al[i] !== bl[i]) return i + 1;\n\treturn 0;\n}\n\nfunction isExerciseReport(\n\tvalue: Record<string, unknown> | undefined,\n): value is ExerciseReport & Record<string, unknown> {\n\treturn value !== undefined && value.form === \"exercise\" && Array.isArray(value.unexercised);\n}\n\nfunction describeRun(run: CommandRun): string {\n\tif (run.timedOut) return \"did not finish within the timeout and was ended\";\n\tif (run.code !== 0) return `exited ${run.code ?? run.signal ?? \"?\"}`;\n\treturn \"exited 0\";\n}\n\nfunction lastWords(run: CommandRun): string {\n\treturn lastPlainLine(run.stderr) || lastPlainLine(run.stdout) || \"no output\";\n}\n\n/** A run as the JSON report carries it: the newest part of each stream, not a whole log. */\nfunction trimmed(run: CommandRun): CommandRun {\n\treturn { ...run, stdout: tailOf(run.stdout, REPORT_TAIL_CHARS), stderr: tailOf(run.stderr, REPORT_TAIL_CHARS) };\n}\n\n/** Level 1 through the entry: the effective manifest, the checked-in file, the offline doctor. */\nasync function checkLevelOne(\n\tsubject: Subject,\n\tentry: string,\n\tenv: NodeJS.ProcessEnv,\n\tviolations: Violation[],\n): Promise<CheckReport[\"l1\"]> {\n\tconst manifest = subject.manifest;\n\tconst fileText = readFileSync(subject.manifestPath, \"utf8\");\n\tlet manifestAgrees = false;\n\tconst details: string[] = [];\n\tconst ran: string[] = [];\n\t// what the entry prints is the manifest: byte for byte the checked-in file (section 12), and valid\n\tconst manifestCommand = entryCommand(manifest, \"manifest\");\n\tran.push(manifestCommand);\n\tconst shown = await runCommand(manifestCommand, { cwd: subject.root, env, timeoutMs: ENTRY_TIMEOUT_MS });\n\tif (shown.code !== 0) {\n\t\tviolations.push({ where: manifestCommand, what: `${describeRun(shown)}: ${lastWords(shown)}` });\n\t} else {\n\t\tlet effective: unknown;\n\t\ttry {\n\t\t\teffective = parseManifestYaml(shown.stdout);\n\t\t} catch (error) {\n\t\t\tviolations.push({ where: manifestCommand, what: `did not print a manifest: ${errorMessage(error)}` });\n\t\t}\n\t\tif (effective !== undefined) {\n\t\t\tconst problems = validateManifest(effective);\n\t\t\tif (problems.length > 0) {\n\t\t\t\tviolations.push({\n\t\t\t\t\twhere: manifestCommand,\n\t\t\t\t\twhat: `the printed manifest does not validate: ${problems.join(\"; \")}`,\n\t\t\t\t});\n\t\t\t} else if ((effective as Manifest).name !== manifest.name) {\n\t\t\t\tviolations.push({\n\t\t\t\t\twhere: subject.manifestPath,\n\t\t\t\t\twhat: `names ${manifest.name}, but the entry's program is ${(effective as Manifest).name}`,\n\t\t\t\t});\n\t\t\t} else if (shown.stdout === fileText) {\n\t\t\t\tmanifestAgrees = true;\n\t\t\t\tdetails.push(\"abaigram.yaml is what the entry prints\");\n\t\t\t} else {\n\t\t\t\tviolations.push({\n\t\t\t\t\twhere: subject.manifestPath,\n\t\t\t\t\twhat: `is stale: first difference at line ${firstDifferingLine(fileText, shown.stdout)}; run: ${entry} manifest > abaigram.yaml`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\tlet doctor: DoctorCheck[] = [];\n\tconst doctorCommand = entryCommand(manifest, \"doctor\", \"--offline\", \"--json\");\n\tran.push(doctorCommand);\n\tconst examined = await runCommand(doctorCommand, { cwd: subject.root, env, timeoutMs: ENTRY_TIMEOUT_MS });\n\tconst parsed = jsonDocument(examined.stdout);\n\tif (parsed && Array.isArray(parsed.checks)) {\n\t\tdoctor = parsed.checks as DoctorCheck[];\n\t\tfor (const check of doctor) {\n\t\t\t// the manifest file is judged above, with the hint for this entry; the doctor's word on it would repeat it\n\t\t\tif (check.status === \"fail\" && check.name !== \"abaigram.yaml\") {\n\t\t\t\tviolations.push({ where: `doctor: ${check.name}`, what: check.detail });\n\t\t\t}\n\t\t}\n\t\tconst failed = doctor.filter((c) => c.status === \"fail\").length;\n\t\tdetails.push(`doctor: ${doctor.filter((c) => c.status === \"ok\").length} ok, ${failed} failed`);\n\t} else {\n\t\tviolations.push({\n\t\t\twhere: doctorCommand,\n\t\t\twhat: `${describeRun(examined)} and printed no report: ${lastWords(examined)}`,\n\t\t});\n\t}\n\tconst ok = manifestAgrees && doctor.length > 0 && doctor.every((c) => c.status !== \"fail\");\n\treturn { ok, manifestAgrees, doctor, ran, detail: details.join(\"; \") };\n}\n\nfunction spread(values: number[]): { min: number; max: number } {\n\treturn { min: Math.min(...values), max: Math.max(...values) };\n}\n\n/** Levels 2 to 4 and the measurement, under one mode. */\nasync function checkMode(\n\tsubject: Subject,\n\tmode: Mode,\n\toptions: { runs: number; timeoutMs: number; env: NodeJS.ProcessEnv },\n\tviolations: Violation[],\n\tunexercised: CheckReport[\"unexercised\"],\n\tnotes: string[],\n): Promise<ModeResult> {\n\tconst manifest = subject.manifest;\n\tconst check = manifest.check as { run: string; overhead?: string };\n\tconst result: ModeResult = { mode, level: 1, evidence: { l2: \"\", l3: \"\", l4: \"\" } };\n\tconst where = (harness: string) => `check.run under ${mode} with ABAI_HARNESS=${harness}`;\n\tconst run = await runCommand(check.run, {\n\t\tcwd: subject.root,\n\t\tenv: subjectEnv(options.env, { ABAI_HARNESS: \"exercise\", ABAI_MODE: mode }),\n\t\ttimeoutMs: options.timeoutMs,\n\t});\n\tresult.exercise = { run: trimmed(run) };\n\t// the report is the stub's exit hook: it is there even when the program failed, and says what was reached\n\tconst report = lastJsonLine(run.stderr, (v) => v.form === \"exercise\");\n\tif (isExerciseReport(report)) {\n\t\tresult.exercise.report = report;\n\t\tfor (const u of report.unexercised) unexercised.push({ mode, ...u });\n\t\tfor (const cell of manifest.cells) {\n\t\t\tif (cell.access === \"read\" && !report.cellsWritten.includes(cell.name)) {\n\t\t\t\tunexercised.push({ mode, kind: \"cell\", name: cell.name, why: \"not written during the exercise run\" });\n\t\t\t}\n\t\t}\n\t\tif (report.eventsEmitted) {\n\t\t\tfor (const event of manifest.events) {\n\t\t\t\tif (!report.eventsEmitted.includes(event.name)) {\n\t\t\t\t\tunexercised.push({ mode, kind: \"event\", name: event.name, why: \"not emitted during the exercise run\" });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (run.timedOut || run.code !== 0) {\n\t\tviolations.push({ where: where(\"exercise\"), what: `${describeRun(run)}: ${lastWords(run)}` });\n\t\treturn result;\n\t}\n\tif (!isExerciseReport(report)) {\n\t\tviolations.push({\n\t\t\twhere: where(\"exercise\"),\n\t\t\twhat: `printed no exercise report at exit${run.dropped.stderr > 0 ? ` in the ${run.stderr.length} newest bytes of stderr kept` : \"\"}: the stub did not attach its null harness (is the entry hook in main, and the program built?)`,\n\t\t});\n\t\treturn result;\n\t}\n\t// the program's own events, by name; a report that names none (an older stub) shows none: the library's do not count\n\tconst emitted = report.eventsEmitted ?? [];\n\tconst l2 = report.cellsWritten.length > 0 || emitted.length > 0;\n\tresult.evidence.l2 = l2\n\t\t? `cells written: ${report.cellsWritten.join(\", \") || \"none\"}; events: ${emitted.join(\", \") || \"none\"}`\n\t\t: \"no cell written and no event emitted during the exercise run\";\n\tconst l3 = report.capabilitiesCalled.length > 0 || report.knobsWritten.length > 0;\n\tresult.evidence.l3 = l3\n\t\t? `capabilities called: ${report.capabilitiesCalled.join(\", \") || \"none\"}; knobs landed: ${report.knobsWritten.join(\", \") || \"none\"}`\n\t\t: \"no capability called and no knob landed\";\n\tconst l4 = report.decisions > 0;\n\tresult.evidence.l4 = l4 ? `decisions reached: ${report.decisions}` : \"no decision reached\";\n\tresult.level = l2 ? (l3 ? (l4 ? 4 : 3) : 2) : 1;\n\n\t// the measurement (11.6): off and null, interleaved so drift lands on both, K runs each, the medians side by side\n\tconst measurement: Measurement = {\n\t\truns: options.runs,\n\t\toff: [],\n\t\tnull: [],\n\t\toffMedianMs: Number.NaN,\n\t\tnullMedianMs: Number.NaN,\n\t\tslowdown: Number.NaN,\n\t\tfailed: [],\n\t\twithinNoise: false,\n\t};\n\tfor (let i = 0; i < options.runs; i++) {\n\t\tfor (const harness of [\"off\", \"null\"] as const) {\n\t\t\tconst timed = await runCommand(check.run, {\n\t\t\t\tcwd: subject.root,\n\t\t\t\tenv: subjectEnv(options.env, { ABAI_HARNESS: harness, ABAI_MODE: mode }),\n\t\t\t\ttimeoutMs: options.timeoutMs,\n\t\t\t});\n\t\t\tif (timed.timedOut || timed.code !== 0) measurement.failed.push(`${harness}: ${describeRun(timed)}`);\n\t\t\telse measurement[harness].push(timed.ms);\n\t\t}\n\t}\n\tif (measurement.failed.length > 0) {\n\t\tviolations.push({\n\t\t\twhere: `check.run under ${mode} with ABAI_HARNESS=off and null`,\n\t\t\twhat: `measurement runs failed: ${measurement.failed.join(\"; \")}`,\n\t\t});\n\t}\n\tif (measurement.off.length > 0 && measurement.null.length > 0) {\n\t\tmeasurement.offMedianMs = median(measurement.off);\n\t\tmeasurement.nullMedianMs = median(measurement.null);\n\t\tmeasurement.slowdown =\n\t\t\tmeasurement.offMedianMs > 0 ? measurement.nullMedianMs / measurement.offMedianMs - 1 : Number.NaN;\n\t\tconst off = spread(measurement.off);\n\t\tconst nul = spread(measurement.null);\n\t\tmeasurement.withinNoise = measurement.offMedianMs < NOISE_FLOOR_MS || (nul.min <= off.max && off.min <= nul.max);\n\t\tif (measurement.withinNoise) {\n\t\t\tnotes.push(\n\t\t\t\t`under ${mode} the overhead numbers are within noise (off ${off.min.toFixed(0)}..${off.max.toFixed(0)} ms, null ${nul.min.toFixed(0)}..${nul.max.toFixed(0)} ms, ${options.runs} runs each): raise --runs or give check.run more work before reading the slowdown`,\n\t\t\t);\n\t\t}\n\t\tconst limit = parseOverhead(check.overhead);\n\t\tif (check.overhead !== undefined && limit === undefined) {\n\t\t\tviolations.push({\n\t\t\t\twhere: \"check.overhead\",\n\t\t\t\twhat: `${JSON.stringify(check.overhead)} is not a percentage such as \"5%\"`,\n\t\t\t});\n\t\t} else if (limit !== undefined) {\n\t\t\tmeasurement.limit = limit;\n\t\t\tif (measurement.slowdown > limit) {\n\t\t\t\tviolations.push({\n\t\t\t\t\twhere: where(\"null\"),\n\t\t\t\t\twhat: `the null-harness run is ${(measurement.slowdown * 100).toFixed(1)}% slower than the off run (medians of ${options.runs}${measurement.withinNoise ? \", within noise\" : \"\"}); check.overhead allows ${check.overhead}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\tresult.measurement = measurement;\n\treturn result;\n}\n\nexport async function checkRepository(options: CheckOptions): Promise<CheckReport> {\n\tconst violations: Violation[] = [];\n\tconst unexercised: CheckReport[\"unexercised\"] = [];\n\tconst notes: string[] = [];\n\tconst subject = loadSubject(options.repo, options.cwd);\n\tconst manifest = subject.manifest;\n\tconst entry = options.entry ?? manifest.entry;\n\tconst subjectForEntry: Subject = options.entry\n\t\t? { ...subject, manifest: { ...manifest, entry: options.entry } }\n\t\t: subject;\n\tconst runs = options.runs ?? DEFAULT_RUNS;\n\tconst timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\n\tconst l1 = await checkLevelOne(subjectForEntry, entry, subjectEnv(options.env), violations);\n\n\tlet checkedModes: Mode[] = manifest.modes;\n\tif (options.mode !== undefined) {\n\t\tif (!manifest.modes.includes(options.mode)) {\n\t\t\tviolations.push({\n\t\t\t\twhere: \"--mode\",\n\t\t\t\twhat: `${manifest.name} declares ${manifest.modes.join(\", \")}, not ${options.mode}`,\n\t\t\t});\n\t\t\tcheckedModes = [];\n\t\t} else checkedModes = [options.mode];\n\t}\n\tif (!/\\babai$/.test(entry.trim())) {\n\t\tnotes.push(\n\t\t\t`the entry \"${entry}\" does not end in the word abai: the stub's runEntry answers only \"abai ...\", so the verbs reach the program only if it translates them itself`,\n\t\t);\n\t}\n\tif (checkedModes.includes(\"sidecar\") && manifest.check?.run) {\n\t\tnotes.push(\n\t\t\t\"under sidecar this instantiation keeps the null harness in the program's process and opens no socket for it, so the measured overhead leaves out the serialization sidecar observation costs (a deviation every manifest it writes declares)\",\n\t\t);\n\t}\n\n\tconst perMode: ModeResult[] = [];\n\tif (l1.ok && manifest.check?.run) {\n\t\tfor (const mode of checkedModes) {\n\t\t\tperMode.push(\n\t\t\t\tawait checkMode(subject, mode, { runs, timeoutMs, env: options.env }, violations, unexercised, notes),\n\t\t\t);\n\t\t}\n\t} else if (l1.ok) {\n\t\tnotes.push(\n\t\t\t\"check.run is not declared, so nothing above level 1 can be shown and nothing is measured (section 12)\",\n\t\t);\n\t}\n\n\tlet level = 0;\n\tif (l1.ok) level = perMode.length > 0 ? Math.min(...perMode.map((m) => m.level)) : 1;\n\tconst requested = options.level;\n\tconst passed = level >= (requested ?? 1) && violations.length === 0;\n\treturn {\n\t\troot: subject.root,\n\t\tname: manifest.name,\n\t\tabaigrammar: manifest.abaigrammar,\n\t\tentry,\n\t\tdeclaredModes: manifest.modes,\n\t\tcheckedModes,\n\t\tcheckRun: manifest.check?.run,\n\t\toverheadLimit: manifest.check?.overhead,\n\t\tcompiledOut: \"not offered\",\n\t\tbuilt: \"no\",\n\t\tl1,\n\t\tperMode,\n\t\tlevel,\n\t\trequested,\n\t\tpassed,\n\t\tunexercised,\n\t\tviolations,\n\t\tnotes,\n\t};\n}\n\nfunction pct(value: number): string {\n\treturn Number.isNaN(value) ? \"n/a\" : `${value >= 0 ? \"+\" : \"\"}${(value * 100).toFixed(1)}%`;\n}\n\nfunction range(values: number[]): string {\n\tif (values.length === 0) return \"failed\";\n\tconst { min, max } = spread(values);\n\treturn `${median(values).toFixed(0)} (${min.toFixed(0)}..${max.toFixed(0)})`;\n}\n\nexport function renderReport(report: CheckReport): string {\n\tconst lines: string[] = [];\n\tlines.push(\n\t\t`abaikit check: ${report.name} at ${report.root} (abaigrammar ${report.abaigrammar}, entry: ${report.entry})`,\n\t);\n\tlet verdict: string;\n\tif (report.requested === undefined) verdict = report.violations.length === 0 ? \"no violations\" : \"with violations\";\n\telse if (report.level < report.requested) verdict = `requested ${report.requested}: not reached`;\n\telse\n\t\tverdict =\n\t\t\treport.violations.length === 0\n\t\t\t\t? `requested ${report.requested}: passed`\n\t\t\t\t: `requested ${report.requested}: reached, with violations`;\n\tlines.push(\n\t\treport.level === 0\n\t\t\t? `level: 0 (L1 not reached; ${verdict})`\n\t\t\t: `level: ${report.level} ${LEVEL_NAMES[report.level]} (${verdict})`,\n\t);\n\tlines.push(\n\t\t`modes: ${report.declaredModes.join(\", \")}${report.checkedModes.length === report.declaredModes.length ? \"\" : `; checked: ${report.checkedModes.join(\", \") || \"none\"}`}`,\n\t);\n\tlines.push(\n\t\t`L1 reachable: ${report.l1.ok ? \"ok\" : \"not reached\"}${report.l1.detail ? ` (${report.l1.detail})` : \"\"}; ran: ${report.l1.ran.join(\"; \")}`,\n\t);\n\tfor (const n of [2, 3, 4] as const) {\n\t\tconst key = `l${n}` as const;\n\t\tconst parts = report.perMode.map((m) => {\n\t\t\tif (m.exercise && !m.exercise.report) return `${m.mode}: exercise run failed`;\n\t\t\tif (!m.evidence[key]) return `${m.mode}: not run`;\n\t\t\treturn `${m.mode}: ${m.level >= n ? \"ok\" : \"no\"}, ${m.evidence[key]}`;\n\t\t});\n\t\tlines.push(`L${n} ${LEVEL_NAMES[n]}: ${parts.length > 0 ? parts.join(\"; \") : \"not shown\"}`);\n\t}\n\tif (report.checkRun !== undefined && report.perMode.some((m) => m.measurement)) {\n\t\tlines.push(\n\t\t\t`overhead (check.run: ${report.checkRun}; built: ${report.built}, the command runs as is; compiled out: ${report.compiledOut}; median ms (min..max) of each run set):`,\n\t\t);\n\t\tlines.push(\" mode runs off null slowdown limit\");\n\t\tfor (const m of report.perMode) {\n\t\t\tconst x = m.measurement;\n\t\t\tif (!x) continue;\n\t\t\tconst limit = x.limit === undefined ? \"none\" : `${(x.limit * 100).toFixed(1)}%`;\n\t\t\tlines.push(\n\t\t\t\t` ${m.mode.padEnd(9)} ${String(x.runs).padEnd(5)} ${range(x.off).padEnd(18)} ${range(x.null).padEnd(18)} ${pct(x.slowdown).padEnd(10)} ${limit}${x.withinNoise ? \" (within noise)\" : \"\"}`,\n\t\t\t);\n\t\t}\n\t}\n\tlines.push(\n\t\treport.unexercised.length === 0\n\t\t\t? \"unexercised: none\"\n\t\t\t: `unexercised:\\n${report.unexercised.map((u) => ` ${u.mode}: ${u.kind} ${u.name}: ${u.why}`).join(\"\\n\")}`,\n\t);\n\tlines.push(\n\t\treport.violations.length === 0\n\t\t\t? \"violations: none\"\n\t\t\t: `violations:\\n${report.violations.map((v) => ` ${v.where}: ${v.what}`).join(\"\\n\")}`,\n\t);\n\tfor (const note of report.notes) lines.push(`note: ${note}`);\n\treturn `${lines.join(\"\\n\")}\\n`;\n}\n\n/** abaikit's own channels see every check: two cells and one event, for the agent fused into abaikit. */\nexport function recordCheck(app: Abaigram | undefined, report: CheckReport): void {\n\tif (!app) return;\n\tconst runs = app.cell<number>(\"check.runs\");\n\truns.set((runs.get() ?? 0) + 1);\n\tapp.cell<number>(\"check.last_level\").set(report.level);\n\tapp.event(\"check.completed\").emit({ repo: report.root, level: report.level });\n}\n\n/** The `check` capability: the same check, its report as text, for the agent on any front end. */\nexport function checkHandler(app: Abaigram, io: Pick<AbaikitIo, \"cwd\" | \"env\">) {\n\treturn async (params: Record<string, unknown>): Promise<{ level: number; passed: boolean; report: string }> => {\n\t\tif (typeof params.repo !== \"string\" || params.repo === \"\") throw new UsageError(\"check needs a repo\");\n\t\tconst level = typeof params.level === \"number\" ? params.level : undefined;\n\t\tif (level !== undefined && (!Number.isInteger(level) || level < 1 || level > 4)) {\n\t\t\tthrow new UsageError(\"level must be 1 to 4\");\n\t\t}\n\t\tconst mode = typeof params.mode === \"string\" && params.mode !== \"\" ? params.mode : undefined;\n\t\tif (mode !== undefined && mode !== \"turns\" && mode !== \"sidecar\")\n\t\t\tthrow new UsageError(\"mode must be turns or sidecar\");\n\t\tconst entry = typeof params.entry === \"string\" && params.entry !== \"\" ? params.entry : undefined;\n\t\tconst runs =\n\t\t\ttypeof params.runs === \"number\" && Number.isInteger(params.runs) && params.runs > 0 ? params.runs : undefined;\n\t\tconst report = await checkRepository({ repo: params.repo, cwd: io.cwd, env: io.env, level, mode, entry, runs });\n\t\trecordCheck(app, report);\n\t\treturn { level: report.level, passed: report.passed, report: renderReport(report) };\n\t};\n}\n\nexport async function runCheck(\n\tparsed: Extract<ParsedArgs, { verb: \"check\" }>,\n\tio: AbaikitIo,\n\tapp?: Abaigram,\n): Promise<number> {\n\tconst report = await checkRepository({\n\t\trepo: parsed.repo,\n\t\tcwd: io.cwd,\n\t\tenv: io.env,\n\t\tlevel: parsed.level,\n\t\tmode: parsed.mode,\n\t\tentry: parsed.entry,\n\t\truns: parsed.runs,\n\t\ttimeoutMs: parsed.timeoutS === undefined ? undefined : parsed.timeoutS * 1000,\n\t});\n\trecordCheck(app, report);\n\tio.out(parsed.json ? `${JSON.stringify(report, null, 2)}\\n` : renderReport(report));\n\treturn report.passed ? 0 : 1;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAY,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAEjF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EACN,KAAK,UAAU,EAQf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,SAAS,EAA4B,MAAM,SAAS,CAAC;AAGnE,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,eAAO,MAAM,kBAAkB,SAAU,CAAC;AAC1C,0DAA0D;AAC1D,eAAO,MAAM,gBAAgB,QAAS,CAAC;AACvC,8EAA8E;AAC9E,eAAO,MAAM,cAAc,MAAM,CAAC;AAGlC,eAAO,MAAM,WAAW,2EAA4E,CAAC;AAErG,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,sGAAsG;AACtG,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,gFAAgF;IAChF,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,sEAAsE;IACtE,WAAW,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,IAAI,CAAC;IACX,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE;QAAE,GAAG,EAAE,UAAU,CAAC;QAAC,MAAM,CAAC,EAAE,cAAc,CAAA;KAAE,CAAC;IACxD,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,WAAW,CAAC,EAAE,WAAW,CAAC;CAC1B;AAED,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,IAAI,EAAE,CAAC;IACtB,YAAY,EAAE,IAAI,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iHAAiH;IACjH,WAAW,EAAE,aAAa,CAAC;IAC3B,KAAK,EAAE,IAAI,CAAC;IACZ,EAAE,EAAE;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,cAAc,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,WAAW,EAAE,CAAC;QAAC,GAAG,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACnG,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5E,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,EAAE,CAAC;CAChB;AA4OD,wBAAsB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAyEjF;AAYD,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CA2DxD;AAED,yGAAyG;AACzG,wBAAgB,WAAW,CAAC,GAAG,EAAE,QAAQ,GAAG,SAAS,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAMhF;AAED,kGAAkG;AAClG,wBAAgB,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,CAAC,SAAS,EAAE,KAAK,GAAG,KAAK,CAAC;;;;GAiB7E;AAED,wBAAsB,QAAQ,CAC7B,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,EAC9C,EAAE,EAAE,SAAS,EACb,GAAG,CAAC,EAAE,QAAQ,GACZ,OAAO,CAAC,MAAM,CAAC,CAcjB","sourcesContent":["// abaikit check: conformance as section 12 defines it, with no model.\n// Level 1 is reached through the subject's entry alone (what `manifest`\n// prints, byte for byte the checked-in file, and `doctor --offline --json`); levels 2 to 4 through its `check.run`\n// under the exercise null harness, once per declared mode, read from the\n// report the stub prints at exit; the overhead of 11.6 by the same command\n// under `ABAI_HARNESS=off` and `ABAI_HARNESS=null`, interleaved, side by\n// side. The subject's environment is constructed, never inherited: each\n// run gets exactly the `ABAI_HARNESS` and `ABAI_MODE` it means, the entry\n// runs get neither. A level is the one reached under every checked mode,\n// and passing means that level with no violation.\nimport { readFileSync } from \"node:fs\";\nimport type { Abaigram, DoctorCheck, Manifest, Mode } from \"@abaigram/abai-stub\";\nimport { parseManifestYaml, validateManifest } from \"@abaigram/abai-stub\";\nimport type { ParsedArgs } from \"./bin.ts\";\nimport {\n\ttype CommandRun,\n\tjsonDocument,\n\tlastJsonLine,\n\tlastPlainLine,\n\tmedian,\n\trunCommand,\n\tsubjectEnv,\n\ttailOf,\n} from \"./command.ts\";\nimport { type AbaikitIo, errorMessage, UsageError } from \"./io.ts\";\nimport { entryCommand, loadSubject, type Subject } from \"./subject.ts\";\n\nexport const DEFAULT_RUNS = 3;\nexport const DEFAULT_TIMEOUT_MS = 120_000;\n/** How long an entry verb (manifest, doctor) may take. */\nexport const ENTRY_TIMEOUT_MS = 60_000;\n/** Below this median for the off run, startup noise is most of the number. */\nexport const NOISE_FLOOR_MS = 500;\n/** Characters of a run's output the JSON report carries. */\nconst REPORT_TAIL_CHARS = 4096;\nexport const LEVEL_NAMES = [\"none\", \"reachable\", \"observable\", \"steerable\", \"deliberative\"] as const;\n\nexport interface CheckOptions {\n\trepo: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n\tlevel?: number;\n\tmode?: Mode;\n\tentry?: string;\n\truns?: number;\n\ttimeoutMs?: number;\n}\n\n/** What the stub's exercise harness reports at exit (abai's NullHarnessReport, as JSON on stderr). */\nexport interface ExerciseReport {\n\tform: string;\n\tevents: number;\n\tdropped: number;\n\tdecisions: number;\n\tturns: number;\n\ttouchpoints: number;\n\tcellsWritten: string[];\n\t/** The program's own events, by name; absent in a report from an older stub. */\n\teventsEmitted?: string[];\n\tknobsWritten: string[];\n\tcapabilitiesCalled: string[];\n\tunexercised: Array<{ kind: string; name: string; why: string }>;\n}\n\nexport interface Measurement {\n\truns: number;\n\toff: number[];\n\tnull: number[];\n\toffMedianMs: number;\n\tnullMedianMs: number;\n\t/** null over off, minus one; NaN when either side has no run. */\n\tslowdown: number;\n\tlimit?: number;\n\t/** The runs that did not exit 0 or timed out, by harness. */\n\tfailed: string[];\n\t/** The numbers are within startup noise or the two ranges overlap. */\n\twithinNoise: boolean;\n}\n\nexport interface ModeResult {\n\tmode: Mode;\n\t/** The highest level this mode demonstrated, 1 to 4. */\n\tlevel: number;\n\texercise?: { run: CommandRun; report?: ExerciseReport };\n\tevidence: { l2: string; l3: string; l4: string };\n\tmeasurement?: Measurement;\n}\n\nexport interface Violation {\n\twhere: string;\n\twhat: string;\n}\n\nexport interface CheckReport {\n\troot: string;\n\tname: string;\n\tabaigrammar: string;\n\tentry: string;\n\tdeclaredModes: Mode[];\n\tcheckedModes: Mode[];\n\tcheckRun?: string;\n\toverheadLimit?: string;\n\t/** This instantiation offers no build with the stub compiled out, and builds nothing: the command runs as is. */\n\tcompiledOut: \"not offered\";\n\tbuilt: \"no\";\n\tl1: { ok: boolean; manifestAgrees: boolean; doctor: DoctorCheck[]; ran: string[]; detail: string };\n\tperMode: ModeResult[];\n\tlevel: number;\n\trequested?: number;\n\tpassed: boolean;\n\tunexercised: Array<{ mode: Mode; kind: string; name: string; why: string }>;\n\tviolations: Violation[];\n\tnotes: string[];\n}\n\nfunction parseOverhead(limit: string | undefined): number | undefined {\n\tif (limit === undefined) return undefined;\n\tconst match = /^(\\d+(?:\\.\\d+)?)\\s*%$/.exec(limit.trim());\n\treturn match ? Number(match[1]) / 100 : undefined;\n}\n\nfunction firstDifferingLine(a: string, b: string): number {\n\tconst al = a.split(\"\\n\");\n\tconst bl = b.split(\"\\n\");\n\tfor (let i = 0; i < Math.max(al.length, bl.length); i++) if (al[i] !== bl[i]) return i + 1;\n\treturn 0;\n}\n\nfunction isExerciseReport(\n\tvalue: Record<string, unknown> | undefined,\n): value is ExerciseReport & Record<string, unknown> {\n\treturn value !== undefined && value.form === \"exercise\" && Array.isArray(value.unexercised);\n}\n\nfunction describeRun(run: CommandRun): string {\n\tif (run.timedOut) return \"did not finish within the timeout and was ended\";\n\tif (run.code !== 0) return `exited ${run.code ?? run.signal ?? \"?\"}`;\n\treturn \"exited 0\";\n}\n\nfunction lastWords(run: CommandRun): string {\n\treturn lastPlainLine(run.stderr) || lastPlainLine(run.stdout) || \"no output\";\n}\n\n/** A run as the JSON report carries it: the newest part of each stream, not a whole log. */\nfunction trimmed(run: CommandRun): CommandRun {\n\treturn { ...run, stdout: tailOf(run.stdout, REPORT_TAIL_CHARS), stderr: tailOf(run.stderr, REPORT_TAIL_CHARS) };\n}\n\n/** Level 1 through the entry: the effective manifest, the checked-in file, the offline doctor. */\nasync function checkLevelOne(\n\tsubject: Subject,\n\tentry: string,\n\tenv: NodeJS.ProcessEnv,\n\tviolations: Violation[],\n): Promise<CheckReport[\"l1\"]> {\n\tconst manifest = subject.manifest;\n\tconst fileText = readFileSync(subject.manifestPath, \"utf8\");\n\tlet manifestAgrees = false;\n\tconst details: string[] = [];\n\tconst ran: string[] = [];\n\t// what the entry prints is the manifest: byte for byte the checked-in file (section 12), and valid\n\tconst manifestCommand = entryCommand(manifest, \"manifest\");\n\tran.push(manifestCommand);\n\tconst shown = await runCommand(manifestCommand, { cwd: subject.root, env, timeoutMs: ENTRY_TIMEOUT_MS });\n\tif (shown.code !== 0) {\n\t\tviolations.push({ where: manifestCommand, what: `${describeRun(shown)}: ${lastWords(shown)}` });\n\t} else {\n\t\tlet effective: unknown;\n\t\ttry {\n\t\t\teffective = parseManifestYaml(shown.stdout);\n\t\t} catch (error) {\n\t\t\tviolations.push({ where: manifestCommand, what: `did not print a manifest: ${errorMessage(error)}` });\n\t\t}\n\t\tif (effective !== undefined) {\n\t\t\tconst problems = validateManifest(effective);\n\t\t\tif (problems.length > 0) {\n\t\t\t\tviolations.push({\n\t\t\t\t\twhere: manifestCommand,\n\t\t\t\t\twhat: `the printed manifest does not validate: ${problems.join(\"; \")}`,\n\t\t\t\t});\n\t\t\t} else if ((effective as Manifest).name !== manifest.name) {\n\t\t\t\tviolations.push({\n\t\t\t\t\twhere: subject.manifestPath,\n\t\t\t\t\twhat: `names ${manifest.name}, but the entry's program is ${(effective as Manifest).name}`,\n\t\t\t\t});\n\t\t\t} else if (shown.stdout === fileText) {\n\t\t\t\tmanifestAgrees = true;\n\t\t\t\tdetails.push(\"abaigram.yaml is what the entry prints\");\n\t\t\t} else {\n\t\t\t\tviolations.push({\n\t\t\t\t\twhere: subject.manifestPath,\n\t\t\t\t\twhat: `is stale: first difference at line ${firstDifferingLine(fileText, shown.stdout)}; run: ${entry} manifest > abaigram.yaml`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\tlet doctor: DoctorCheck[] = [];\n\tconst doctorCommand = entryCommand(manifest, \"doctor\", \"--offline\", \"--json\");\n\tran.push(doctorCommand);\n\tconst examined = await runCommand(doctorCommand, { cwd: subject.root, env, timeoutMs: ENTRY_TIMEOUT_MS });\n\tconst parsed = jsonDocument(examined.stdout);\n\tif (parsed && Array.isArray(parsed.checks)) {\n\t\tdoctor = parsed.checks as DoctorCheck[];\n\t\tfor (const check of doctor) {\n\t\t\t// the manifest file is judged above, with the hint for this entry; the doctor's word on it would repeat it\n\t\t\tif (check.status === \"fail\" && check.name !== \"abaigram.yaml\") {\n\t\t\t\tviolations.push({ where: `doctor: ${check.name}`, what: check.detail });\n\t\t\t}\n\t\t}\n\t\tconst failed = doctor.filter((c) => c.status === \"fail\").length;\n\t\tdetails.push(`doctor: ${doctor.filter((c) => c.status === \"ok\").length} ok, ${failed} failed`);\n\t} else {\n\t\tviolations.push({\n\t\t\twhere: doctorCommand,\n\t\t\twhat: `${describeRun(examined)} and printed no report: ${lastWords(examined)}`,\n\t\t});\n\t}\n\tconst ok = manifestAgrees && doctor.length > 0 && doctor.every((c) => c.status !== \"fail\");\n\treturn { ok, manifestAgrees, doctor, ran, detail: details.join(\"; \") };\n}\n\nfunction spread(values: number[]): { min: number; max: number } {\n\treturn { min: Math.min(...values), max: Math.max(...values) };\n}\n\n/** Levels 2 to 4 and the measurement, under one mode. */\nasync function checkMode(\n\tsubject: Subject,\n\tmode: Mode,\n\toptions: { runs: number; timeoutMs: number; env: NodeJS.ProcessEnv },\n\tviolations: Violation[],\n\tunexercised: CheckReport[\"unexercised\"],\n\tnotes: string[],\n): Promise<ModeResult> {\n\tconst manifest = subject.manifest;\n\tconst check = manifest.check as { run: string; overhead?: string };\n\tconst result: ModeResult = { mode, level: 1, evidence: { l2: \"\", l3: \"\", l4: \"\" } };\n\tconst where = (harness: string) => `check.run under ${mode} with ABAI_HARNESS=${harness}`;\n\tconst run = await runCommand(check.run, {\n\t\tcwd: subject.root,\n\t\tenv: subjectEnv(options.env, { ABAI_HARNESS: \"exercise\", ABAI_MODE: mode }),\n\t\ttimeoutMs: options.timeoutMs,\n\t});\n\tresult.exercise = { run: trimmed(run) };\n\t// the report is the stub's exit hook: it is there even when the program failed, and says what was reached\n\tconst report = lastJsonLine(run.stderr, (v) => v.form === \"exercise\");\n\tif (isExerciseReport(report)) {\n\t\tresult.exercise.report = report;\n\t\tfor (const u of report.unexercised) unexercised.push({ mode, ...u });\n\t\tfor (const cell of manifest.cells) {\n\t\t\tif (cell.access === \"read\" && !report.cellsWritten.includes(cell.name)) {\n\t\t\t\tunexercised.push({ mode, kind: \"cell\", name: cell.name, why: \"not written during the exercise run\" });\n\t\t\t}\n\t\t}\n\t\tif (report.eventsEmitted) {\n\t\t\tfor (const event of manifest.events) {\n\t\t\t\tif (!report.eventsEmitted.includes(event.name)) {\n\t\t\t\t\tunexercised.push({ mode, kind: \"event\", name: event.name, why: \"not emitted during the exercise run\" });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (run.timedOut || run.code !== 0) {\n\t\tviolations.push({ where: where(\"exercise\"), what: `${describeRun(run)}: ${lastWords(run)}` });\n\t\treturn result;\n\t}\n\tif (!isExerciseReport(report)) {\n\t\tviolations.push({\n\t\t\twhere: where(\"exercise\"),\n\t\t\twhat: `printed no exercise report at exit${run.dropped.stderr > 0 ? ` in the ${run.stderr.length} newest bytes of stderr kept` : \"\"}: the stub did not attach its null harness (is the entry hook in main, and the program built?)`,\n\t\t});\n\t\treturn result;\n\t}\n\t// the program's own events, by name; a report that names none (an older stub) shows none: the library's do not count\n\tconst emitted = report.eventsEmitted ?? [];\n\tconst l2 = report.cellsWritten.length > 0 || emitted.length > 0;\n\tresult.evidence.l2 = l2\n\t\t? `cells written: ${report.cellsWritten.join(\", \") || \"none\"}; events: ${emitted.join(\", \") || \"none\"}`\n\t\t: \"no cell written and no event emitted during the exercise run\";\n\tconst l3 = report.capabilitiesCalled.length > 0 || report.knobsWritten.length > 0;\n\tresult.evidence.l3 = l3\n\t\t? `capabilities called: ${report.capabilitiesCalled.join(\", \") || \"none\"}; knobs landed: ${report.knobsWritten.join(\", \") || \"none\"}`\n\t\t: \"no capability called and no knob landed\";\n\tconst l4 = report.decisions > 0;\n\tresult.evidence.l4 = l4 ? `decisions reached: ${report.decisions}` : \"no decision reached\";\n\tresult.level = l2 ? (l3 ? (l4 ? 4 : 3) : 2) : 1;\n\n\t// the measurement (11.6): off and null, interleaved so drift lands on both, K runs each, the medians side by side\n\tconst measurement: Measurement = {\n\t\truns: options.runs,\n\t\toff: [],\n\t\tnull: [],\n\t\toffMedianMs: Number.NaN,\n\t\tnullMedianMs: Number.NaN,\n\t\tslowdown: Number.NaN,\n\t\tfailed: [],\n\t\twithinNoise: false,\n\t};\n\tfor (let i = 0; i < options.runs; i++) {\n\t\tfor (const harness of [\"off\", \"null\"] as const) {\n\t\t\tconst timed = await runCommand(check.run, {\n\t\t\t\tcwd: subject.root,\n\t\t\t\tenv: subjectEnv(options.env, { ABAI_HARNESS: harness, ABAI_MODE: mode }),\n\t\t\t\ttimeoutMs: options.timeoutMs,\n\t\t\t});\n\t\t\tif (timed.timedOut || timed.code !== 0) measurement.failed.push(`${harness}: ${describeRun(timed)}`);\n\t\t\telse measurement[harness].push(timed.ms);\n\t\t}\n\t}\n\tif (measurement.failed.length > 0) {\n\t\tviolations.push({\n\t\t\twhere: `check.run under ${mode} with ABAI_HARNESS=off and null`,\n\t\t\twhat: `measurement runs failed: ${measurement.failed.join(\"; \")}`,\n\t\t});\n\t}\n\tif (measurement.off.length > 0 && measurement.null.length > 0) {\n\t\tmeasurement.offMedianMs = median(measurement.off);\n\t\tmeasurement.nullMedianMs = median(measurement.null);\n\t\tmeasurement.slowdown =\n\t\t\tmeasurement.offMedianMs > 0 ? measurement.nullMedianMs / measurement.offMedianMs - 1 : Number.NaN;\n\t\tconst off = spread(measurement.off);\n\t\tconst nul = spread(measurement.null);\n\t\tmeasurement.withinNoise = measurement.offMedianMs < NOISE_FLOOR_MS || (nul.min <= off.max && off.min <= nul.max);\n\t\tif (measurement.withinNoise) {\n\t\t\tnotes.push(\n\t\t\t\t`under ${mode} the overhead numbers are within noise (off ${off.min.toFixed(0)}..${off.max.toFixed(0)} ms, null ${nul.min.toFixed(0)}..${nul.max.toFixed(0)} ms, ${options.runs} runs each): raise --runs or give check.run more work before reading the slowdown`,\n\t\t\t);\n\t\t}\n\t\tconst limit = parseOverhead(check.overhead);\n\t\tif (check.overhead !== undefined && limit === undefined) {\n\t\t\tviolations.push({\n\t\t\t\twhere: \"check.overhead\",\n\t\t\t\twhat: `${JSON.stringify(check.overhead)} is not a percentage such as \"5%\"`,\n\t\t\t});\n\t\t} else if (limit !== undefined) {\n\t\t\tmeasurement.limit = limit;\n\t\t\tif (measurement.slowdown > limit) {\n\t\t\t\tviolations.push({\n\t\t\t\t\twhere: where(\"null\"),\n\t\t\t\t\twhat: `the null-harness run is ${(measurement.slowdown * 100).toFixed(1)}% slower than the off run (medians of ${options.runs}${measurement.withinNoise ? \", within noise\" : \"\"}); check.overhead allows ${check.overhead}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\tresult.measurement = measurement;\n\treturn result;\n}\n\nexport async function checkRepository(options: CheckOptions): Promise<CheckReport> {\n\tconst violations: Violation[] = [];\n\tconst unexercised: CheckReport[\"unexercised\"] = [];\n\tconst notes: string[] = [];\n\tconst subject = loadSubject(options.repo, options.cwd);\n\tconst manifest = subject.manifest;\n\tconst entry = options.entry ?? manifest.entry;\n\tconst subjectForEntry: Subject = options.entry\n\t\t? { ...subject, manifest: { ...manifest, entry: options.entry } }\n\t\t: subject;\n\tconst runs = options.runs ?? DEFAULT_RUNS;\n\tconst timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\n\tconst l1 = await checkLevelOne(subjectForEntry, entry, subjectEnv(options.env), violations);\n\n\tlet checkedModes: Mode[] = manifest.modes;\n\tif (options.mode !== undefined) {\n\t\tif (!manifest.modes.includes(options.mode)) {\n\t\t\tviolations.push({\n\t\t\t\twhere: \"--mode\",\n\t\t\t\twhat: `${manifest.name} declares ${manifest.modes.join(\", \")}, not ${options.mode}`,\n\t\t\t});\n\t\t\tcheckedModes = [];\n\t\t} else checkedModes = [options.mode];\n\t}\n\tif (!/\\babai$/.test(entry.trim())) {\n\t\tnotes.push(\n\t\t\t`the entry \"${entry}\" does not end in the word abai: the stub's runEntry answers only \"abai ...\", so the verbs reach the program only if it translates them itself`,\n\t\t);\n\t}\n\tif (checkedModes.includes(\"sidecar\") && manifest.check?.run) {\n\t\tnotes.push(\n\t\t\t\"under sidecar this instantiation keeps the null harness in the program's process and opens no socket for it, so the measured overhead leaves out the serialization sidecar observation costs (a deviation every manifest it writes declares)\",\n\t\t);\n\t}\n\n\tconst perMode: ModeResult[] = [];\n\tif (l1.ok && manifest.check?.run) {\n\t\tfor (const mode of checkedModes) {\n\t\t\tperMode.push(\n\t\t\t\tawait checkMode(subject, mode, { runs, timeoutMs, env: options.env }, violations, unexercised, notes),\n\t\t\t);\n\t\t}\n\t} else if (l1.ok) {\n\t\tnotes.push(\n\t\t\t\"check.run is not declared, so nothing above level 1 can be shown and nothing is measured (section 12)\",\n\t\t);\n\t}\n\n\tlet level = 0;\n\tif (l1.ok) level = perMode.length > 0 ? Math.min(...perMode.map((m) => m.level)) : 1;\n\tconst requested = options.level;\n\tconst passed = level >= (requested ?? 1) && violations.length === 0;\n\treturn {\n\t\troot: subject.root,\n\t\tname: manifest.name,\n\t\tabaigrammar: manifest.abaigrammar,\n\t\tentry,\n\t\tdeclaredModes: manifest.modes,\n\t\tcheckedModes,\n\t\tcheckRun: manifest.check?.run,\n\t\toverheadLimit: manifest.check?.overhead,\n\t\tcompiledOut: \"not offered\",\n\t\tbuilt: \"no\",\n\t\tl1,\n\t\tperMode,\n\t\tlevel,\n\t\trequested,\n\t\tpassed,\n\t\tunexercised,\n\t\tviolations,\n\t\tnotes,\n\t};\n}\n\nfunction pct(value: number): string {\n\treturn Number.isNaN(value) ? \"n/a\" : `${value >= 0 ? \"+\" : \"\"}${(value * 100).toFixed(1)}%`;\n}\n\nfunction range(values: number[]): string {\n\tif (values.length === 0) return \"failed\";\n\tconst { min, max } = spread(values);\n\treturn `${median(values).toFixed(0)} (${min.toFixed(0)}..${max.toFixed(0)})`;\n}\n\nexport function renderReport(report: CheckReport): string {\n\tconst lines: string[] = [];\n\tlines.push(\n\t\t`abaikit check: ${report.name} at ${report.root} (abaigrammar ${report.abaigrammar}, entry: ${report.entry})`,\n\t);\n\tlet verdict: string;\n\tif (report.requested === undefined) verdict = report.violations.length === 0 ? \"no violations\" : \"with violations\";\n\telse if (report.level < report.requested) verdict = `requested ${report.requested}: not reached`;\n\telse\n\t\tverdict =\n\t\t\treport.violations.length === 0\n\t\t\t\t? `requested ${report.requested}: passed`\n\t\t\t\t: `requested ${report.requested}: reached, with violations`;\n\tlines.push(\n\t\treport.level === 0\n\t\t\t? `level: 0 (L1 not reached; ${verdict})`\n\t\t\t: `level: ${report.level} ${LEVEL_NAMES[report.level]} (${verdict})`,\n\t);\n\tlines.push(\n\t\t`modes: ${report.declaredModes.join(\", \")}${report.checkedModes.length === report.declaredModes.length ? \"\" : `; checked: ${report.checkedModes.join(\", \") || \"none\"}`}`,\n\t);\n\tlines.push(\n\t\t`L1 reachable: ${report.l1.ok ? \"ok\" : \"not reached\"}${report.l1.detail ? ` (${report.l1.detail})` : \"\"}; ran: ${report.l1.ran.join(\"; \")}`,\n\t);\n\tfor (const n of [2, 3, 4] as const) {\n\t\tconst key = `l${n}` as const;\n\t\tconst parts = report.perMode.map((m) => {\n\t\t\tif (m.exercise && !m.exercise.report) return `${m.mode}: exercise run failed`;\n\t\t\tif (!m.evidence[key]) return `${m.mode}: not run`;\n\t\t\treturn `${m.mode}: ${m.level >= n ? \"ok\" : \"no\"}, ${m.evidence[key]}`;\n\t\t});\n\t\tlines.push(`L${n} ${LEVEL_NAMES[n]}: ${parts.length > 0 ? parts.join(\"; \") : \"not shown\"}`);\n\t}\n\tif (report.checkRun !== undefined && report.perMode.some((m) => m.measurement)) {\n\t\tlines.push(\n\t\t\t`overhead (check.run: ${report.checkRun}; built: ${report.built}, the command runs as is; compiled out: ${report.compiledOut}; median ms (min..max) of each run set):`,\n\t\t);\n\t\tlines.push(\" mode runs off null slowdown limit\");\n\t\tfor (const m of report.perMode) {\n\t\t\tconst x = m.measurement;\n\t\t\tif (!x) continue;\n\t\t\tconst limit = x.limit === undefined ? \"none\" : `${(x.limit * 100).toFixed(1)}%`;\n\t\t\tlines.push(\n\t\t\t\t` ${m.mode.padEnd(9)} ${String(x.runs).padEnd(5)} ${range(x.off).padEnd(18)} ${range(x.null).padEnd(18)} ${pct(x.slowdown).padEnd(10)} ${limit}${x.withinNoise ? \" (within noise)\" : \"\"}`,\n\t\t\t);\n\t\t}\n\t}\n\tlines.push(\n\t\treport.unexercised.length === 0\n\t\t\t? \"unexercised: none\"\n\t\t\t: `unexercised:\\n${report.unexercised.map((u) => ` ${u.mode}: ${u.kind} ${u.name}: ${u.why}`).join(\"\\n\")}`,\n\t);\n\tlines.push(\n\t\treport.violations.length === 0\n\t\t\t? \"violations: none\"\n\t\t\t: `violations:\\n${report.violations.map((v) => ` ${v.where}: ${v.what}`).join(\"\\n\")}`,\n\t);\n\tfor (const note of report.notes) lines.push(`note: ${note}`);\n\treturn `${lines.join(\"\\n\")}\\n`;\n}\n\n/** abaikit's own channels see every check: two cells and one event, for the agent fused into abaikit. */\nexport function recordCheck(app: Abaigram | undefined, report: CheckReport): void {\n\tif (!app) return;\n\tconst runs = app.cell<number>(\"check.runs\");\n\truns.set((runs.get() ?? 0) + 1);\n\tapp.cell<number>(\"check.last_level\").set(report.level);\n\tapp.event(\"check.completed\").emit({ repo: report.root, level: report.level });\n}\n\n/** The `check` capability: the same check, its report as text, for the agent on any front end. */\nexport function checkHandler(app: Abaigram, io: Pick<AbaikitIo, \"cwd\" | \"env\">) {\n\treturn async (params: Record<string, unknown>): Promise<{ level: number; passed: boolean; report: string }> => {\n\t\tif (typeof params.repo !== \"string\" || params.repo === \"\") throw new UsageError(\"check needs a repo\");\n\t\tconst level = typeof params.level === \"number\" ? params.level : undefined;\n\t\tif (level !== undefined && (!Number.isInteger(level) || level < 1 || level > 4)) {\n\t\t\tthrow new UsageError(\"level must be 1 to 4\");\n\t\t}\n\t\tconst mode = typeof params.mode === \"string\" && params.mode !== \"\" ? params.mode : undefined;\n\t\tif (mode !== undefined && mode !== \"turns\" && mode !== \"thread\" && mode !== \"sidecar\")\n\t\t\tthrow new UsageError(\"mode must be turns, thread or sidecar\");\n\t\tconst entry = typeof params.entry === \"string\" && params.entry !== \"\" ? params.entry : undefined;\n\t\tconst runs =\n\t\t\ttypeof params.runs === \"number\" && Number.isInteger(params.runs) && params.runs > 0 ? params.runs : undefined;\n\t\tconst report = await checkRepository({ repo: params.repo, cwd: io.cwd, env: io.env, level, mode, entry, runs });\n\t\trecordCheck(app, report);\n\t\treturn { level: report.level, passed: report.passed, report: renderReport(report) };\n\t};\n}\n\nexport async function runCheck(\n\tparsed: Extract<ParsedArgs, { verb: \"check\" }>,\n\tio: AbaikitIo,\n\tapp?: Abaigram,\n): Promise<number> {\n\tconst report = await checkRepository({\n\t\trepo: parsed.repo,\n\t\tcwd: io.cwd,\n\t\tenv: io.env,\n\t\tlevel: parsed.level,\n\t\tmode: parsed.mode,\n\t\tentry: parsed.entry,\n\t\truns: parsed.runs,\n\t\ttimeoutMs: parsed.timeoutS === undefined ? undefined : parsed.timeoutS * 1000,\n\t});\n\trecordCheck(app, report);\n\tio.out(parsed.json ? `${JSON.stringify(report, null, 2)}\\n` : renderReport(report));\n\treturn report.passed ? 0 : 1;\n}\n"]}
|
package/dist/check.js
CHANGED
|
@@ -389,8 +389,8 @@ export function checkHandler(app, io) {
|
|
|
389
389
|
throw new UsageError("level must be 1 to 4");
|
|
390
390
|
}
|
|
391
391
|
const mode = typeof params.mode === "string" && params.mode !== "" ? params.mode : undefined;
|
|
392
|
-
if (mode !== undefined && mode !== "turns" && mode !== "sidecar")
|
|
393
|
-
throw new UsageError("mode must be turns or sidecar");
|
|
392
|
+
if (mode !== undefined && mode !== "turns" && mode !== "thread" && mode !== "sidecar")
|
|
393
|
+
throw new UsageError("mode must be turns, thread or sidecar");
|
|
394
394
|
const entry = typeof params.entry === "string" && params.entry !== "" ? params.entry : undefined;
|
|
395
395
|
const runs = typeof params.runs === "number" && Number.isInteger(params.runs) && params.runs > 0 ? params.runs : undefined;
|
|
396
396
|
const report = await checkRepository({ repo: params.repo, cwd: io.cwd, env: io.env, level, mode, entry, runs });
|
package/dist/check.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.js","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"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","sourcesContent":["// abaikit check: conformance as section 12 defines it, with no model.\n// Level 1 is reached through the subject's entry alone (what `manifest`\n// prints, byte for byte the checked-in file, and `doctor --offline --json`); levels 2 to 4 through its `check.run`\n// under the exercise null harness, once per declared mode, read from the\n// report the stub prints at exit; the overhead of 11.6 by the same command\n// under `ABAI_HARNESS=off` and `ABAI_HARNESS=null`, interleaved, side by\n// side. The subject's environment is constructed, never inherited: each\n// run gets exactly the `ABAI_HARNESS` and `ABAI_MODE` it means, the entry\n// runs get neither. A level is the one reached under every checked mode,\n// and passing means that level with no violation.\nimport { readFileSync } from \"node:fs\";\nimport type { Abaigram, DoctorCheck, Manifest, Mode } from \"@abaigram/abai-stub\";\nimport { parseManifestYaml, validateManifest } from \"@abaigram/abai-stub\";\nimport type { ParsedArgs } from \"./bin.ts\";\nimport {\n\ttype CommandRun,\n\tjsonDocument,\n\tlastJsonLine,\n\tlastPlainLine,\n\tmedian,\n\trunCommand,\n\tsubjectEnv,\n\ttailOf,\n} from \"./command.ts\";\nimport { type AbaikitIo, errorMessage, UsageError } from \"./io.ts\";\nimport { entryCommand, loadSubject, type Subject } from \"./subject.ts\";\n\nexport const DEFAULT_RUNS = 3;\nexport const DEFAULT_TIMEOUT_MS = 120_000;\n/** How long an entry verb (manifest, doctor) may take. */\nexport const ENTRY_TIMEOUT_MS = 60_000;\n/** Below this median for the off run, startup noise is most of the number. */\nexport const NOISE_FLOOR_MS = 500;\n/** Characters of a run's output the JSON report carries. */\nconst REPORT_TAIL_CHARS = 4096;\nexport const LEVEL_NAMES = [\"none\", \"reachable\", \"observable\", \"steerable\", \"deliberative\"] as const;\n\nexport interface CheckOptions {\n\trepo: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n\tlevel?: number;\n\tmode?: Mode;\n\tentry?: string;\n\truns?: number;\n\ttimeoutMs?: number;\n}\n\n/** What the stub's exercise harness reports at exit (abai's NullHarnessReport, as JSON on stderr). */\nexport interface ExerciseReport {\n\tform: string;\n\tevents: number;\n\tdropped: number;\n\tdecisions: number;\n\tturns: number;\n\ttouchpoints: number;\n\tcellsWritten: string[];\n\t/** The program's own events, by name; absent in a report from an older stub. */\n\teventsEmitted?: string[];\n\tknobsWritten: string[];\n\tcapabilitiesCalled: string[];\n\tunexercised: Array<{ kind: string; name: string; why: string }>;\n}\n\nexport interface Measurement {\n\truns: number;\n\toff: number[];\n\tnull: number[];\n\toffMedianMs: number;\n\tnullMedianMs: number;\n\t/** null over off, minus one; NaN when either side has no run. */\n\tslowdown: number;\n\tlimit?: number;\n\t/** The runs that did not exit 0 or timed out, by harness. */\n\tfailed: string[];\n\t/** The numbers are within startup noise or the two ranges overlap. */\n\twithinNoise: boolean;\n}\n\nexport interface ModeResult {\n\tmode: Mode;\n\t/** The highest level this mode demonstrated, 1 to 4. */\n\tlevel: number;\n\texercise?: { run: CommandRun; report?: ExerciseReport };\n\tevidence: { l2: string; l3: string; l4: string };\n\tmeasurement?: Measurement;\n}\n\nexport interface Violation {\n\twhere: string;\n\twhat: string;\n}\n\nexport interface CheckReport {\n\troot: string;\n\tname: string;\n\tabaigrammar: string;\n\tentry: string;\n\tdeclaredModes: Mode[];\n\tcheckedModes: Mode[];\n\tcheckRun?: string;\n\toverheadLimit?: string;\n\t/** This instantiation offers no build with the stub compiled out, and builds nothing: the command runs as is. */\n\tcompiledOut: \"not offered\";\n\tbuilt: \"no\";\n\tl1: { ok: boolean; manifestAgrees: boolean; doctor: DoctorCheck[]; ran: string[]; detail: string };\n\tperMode: ModeResult[];\n\tlevel: number;\n\trequested?: number;\n\tpassed: boolean;\n\tunexercised: Array<{ mode: Mode; kind: string; name: string; why: string }>;\n\tviolations: Violation[];\n\tnotes: string[];\n}\n\nfunction parseOverhead(limit: string | undefined): number | undefined {\n\tif (limit === undefined) return undefined;\n\tconst match = /^(\\d+(?:\\.\\d+)?)\\s*%$/.exec(limit.trim());\n\treturn match ? Number(match[1]) / 100 : undefined;\n}\n\nfunction firstDifferingLine(a: string, b: string): number {\n\tconst al = a.split(\"\\n\");\n\tconst bl = b.split(\"\\n\");\n\tfor (let i = 0; i < Math.max(al.length, bl.length); i++) if (al[i] !== bl[i]) return i + 1;\n\treturn 0;\n}\n\nfunction isExerciseReport(\n\tvalue: Record<string, unknown> | undefined,\n): value is ExerciseReport & Record<string, unknown> {\n\treturn value !== undefined && value.form === \"exercise\" && Array.isArray(value.unexercised);\n}\n\nfunction describeRun(run: CommandRun): string {\n\tif (run.timedOut) return \"did not finish within the timeout and was ended\";\n\tif (run.code !== 0) return `exited ${run.code ?? run.signal ?? \"?\"}`;\n\treturn \"exited 0\";\n}\n\nfunction lastWords(run: CommandRun): string {\n\treturn lastPlainLine(run.stderr) || lastPlainLine(run.stdout) || \"no output\";\n}\n\n/** A run as the JSON report carries it: the newest part of each stream, not a whole log. */\nfunction trimmed(run: CommandRun): CommandRun {\n\treturn { ...run, stdout: tailOf(run.stdout, REPORT_TAIL_CHARS), stderr: tailOf(run.stderr, REPORT_TAIL_CHARS) };\n}\n\n/** Level 1 through the entry: the effective manifest, the checked-in file, the offline doctor. */\nasync function checkLevelOne(\n\tsubject: Subject,\n\tentry: string,\n\tenv: NodeJS.ProcessEnv,\n\tviolations: Violation[],\n): Promise<CheckReport[\"l1\"]> {\n\tconst manifest = subject.manifest;\n\tconst fileText = readFileSync(subject.manifestPath, \"utf8\");\n\tlet manifestAgrees = false;\n\tconst details: string[] = [];\n\tconst ran: string[] = [];\n\t// what the entry prints is the manifest: byte for byte the checked-in file (section 12), and valid\n\tconst manifestCommand = entryCommand(manifest, \"manifest\");\n\tran.push(manifestCommand);\n\tconst shown = await runCommand(manifestCommand, { cwd: subject.root, env, timeoutMs: ENTRY_TIMEOUT_MS });\n\tif (shown.code !== 0) {\n\t\tviolations.push({ where: manifestCommand, what: `${describeRun(shown)}: ${lastWords(shown)}` });\n\t} else {\n\t\tlet effective: unknown;\n\t\ttry {\n\t\t\teffective = parseManifestYaml(shown.stdout);\n\t\t} catch (error) {\n\t\t\tviolations.push({ where: manifestCommand, what: `did not print a manifest: ${errorMessage(error)}` });\n\t\t}\n\t\tif (effective !== undefined) {\n\t\t\tconst problems = validateManifest(effective);\n\t\t\tif (problems.length > 0) {\n\t\t\t\tviolations.push({\n\t\t\t\t\twhere: manifestCommand,\n\t\t\t\t\twhat: `the printed manifest does not validate: ${problems.join(\"; \")}`,\n\t\t\t\t});\n\t\t\t} else if ((effective as Manifest).name !== manifest.name) {\n\t\t\t\tviolations.push({\n\t\t\t\t\twhere: subject.manifestPath,\n\t\t\t\t\twhat: `names ${manifest.name}, but the entry's program is ${(effective as Manifest).name}`,\n\t\t\t\t});\n\t\t\t} else if (shown.stdout === fileText) {\n\t\t\t\tmanifestAgrees = true;\n\t\t\t\tdetails.push(\"abaigram.yaml is what the entry prints\");\n\t\t\t} else {\n\t\t\t\tviolations.push({\n\t\t\t\t\twhere: subject.manifestPath,\n\t\t\t\t\twhat: `is stale: first difference at line ${firstDifferingLine(fileText, shown.stdout)}; run: ${entry} manifest > abaigram.yaml`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\tlet doctor: DoctorCheck[] = [];\n\tconst doctorCommand = entryCommand(manifest, \"doctor\", \"--offline\", \"--json\");\n\tran.push(doctorCommand);\n\tconst examined = await runCommand(doctorCommand, { cwd: subject.root, env, timeoutMs: ENTRY_TIMEOUT_MS });\n\tconst parsed = jsonDocument(examined.stdout);\n\tif (parsed && Array.isArray(parsed.checks)) {\n\t\tdoctor = parsed.checks as DoctorCheck[];\n\t\tfor (const check of doctor) {\n\t\t\t// the manifest file is judged above, with the hint for this entry; the doctor's word on it would repeat it\n\t\t\tif (check.status === \"fail\" && check.name !== \"abaigram.yaml\") {\n\t\t\t\tviolations.push({ where: `doctor: ${check.name}`, what: check.detail });\n\t\t\t}\n\t\t}\n\t\tconst failed = doctor.filter((c) => c.status === \"fail\").length;\n\t\tdetails.push(`doctor: ${doctor.filter((c) => c.status === \"ok\").length} ok, ${failed} failed`);\n\t} else {\n\t\tviolations.push({\n\t\t\twhere: doctorCommand,\n\t\t\twhat: `${describeRun(examined)} and printed no report: ${lastWords(examined)}`,\n\t\t});\n\t}\n\tconst ok = manifestAgrees && doctor.length > 0 && doctor.every((c) => c.status !== \"fail\");\n\treturn { ok, manifestAgrees, doctor, ran, detail: details.join(\"; \") };\n}\n\nfunction spread(values: number[]): { min: number; max: number } {\n\treturn { min: Math.min(...values), max: Math.max(...values) };\n}\n\n/** Levels 2 to 4 and the measurement, under one mode. */\nasync function checkMode(\n\tsubject: Subject,\n\tmode: Mode,\n\toptions: { runs: number; timeoutMs: number; env: NodeJS.ProcessEnv },\n\tviolations: Violation[],\n\tunexercised: CheckReport[\"unexercised\"],\n\tnotes: string[],\n): Promise<ModeResult> {\n\tconst manifest = subject.manifest;\n\tconst check = manifest.check as { run: string; overhead?: string };\n\tconst result: ModeResult = { mode, level: 1, evidence: { l2: \"\", l3: \"\", l4: \"\" } };\n\tconst where = (harness: string) => `check.run under ${mode} with ABAI_HARNESS=${harness}`;\n\tconst run = await runCommand(check.run, {\n\t\tcwd: subject.root,\n\t\tenv: subjectEnv(options.env, { ABAI_HARNESS: \"exercise\", ABAI_MODE: mode }),\n\t\ttimeoutMs: options.timeoutMs,\n\t});\n\tresult.exercise = { run: trimmed(run) };\n\t// the report is the stub's exit hook: it is there even when the program failed, and says what was reached\n\tconst report = lastJsonLine(run.stderr, (v) => v.form === \"exercise\");\n\tif (isExerciseReport(report)) {\n\t\tresult.exercise.report = report;\n\t\tfor (const u of report.unexercised) unexercised.push({ mode, ...u });\n\t\tfor (const cell of manifest.cells) {\n\t\t\tif (cell.access === \"read\" && !report.cellsWritten.includes(cell.name)) {\n\t\t\t\tunexercised.push({ mode, kind: \"cell\", name: cell.name, why: \"not written during the exercise run\" });\n\t\t\t}\n\t\t}\n\t\tif (report.eventsEmitted) {\n\t\t\tfor (const event of manifest.events) {\n\t\t\t\tif (!report.eventsEmitted.includes(event.name)) {\n\t\t\t\t\tunexercised.push({ mode, kind: \"event\", name: event.name, why: \"not emitted during the exercise run\" });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (run.timedOut || run.code !== 0) {\n\t\tviolations.push({ where: where(\"exercise\"), what: `${describeRun(run)}: ${lastWords(run)}` });\n\t\treturn result;\n\t}\n\tif (!isExerciseReport(report)) {\n\t\tviolations.push({\n\t\t\twhere: where(\"exercise\"),\n\t\t\twhat: `printed no exercise report at exit${run.dropped.stderr > 0 ? ` in the ${run.stderr.length} newest bytes of stderr kept` : \"\"}: the stub did not attach its null harness (is the entry hook in main, and the program built?)`,\n\t\t});\n\t\treturn result;\n\t}\n\t// the program's own events, by name; a report that names none (an older stub) shows none: the library's do not count\n\tconst emitted = report.eventsEmitted ?? [];\n\tconst l2 = report.cellsWritten.length > 0 || emitted.length > 0;\n\tresult.evidence.l2 = l2\n\t\t? `cells written: ${report.cellsWritten.join(\", \") || \"none\"}; events: ${emitted.join(\", \") || \"none\"}`\n\t\t: \"no cell written and no event emitted during the exercise run\";\n\tconst l3 = report.capabilitiesCalled.length > 0 || report.knobsWritten.length > 0;\n\tresult.evidence.l3 = l3\n\t\t? `capabilities called: ${report.capabilitiesCalled.join(\", \") || \"none\"}; knobs landed: ${report.knobsWritten.join(\", \") || \"none\"}`\n\t\t: \"no capability called and no knob landed\";\n\tconst l4 = report.decisions > 0;\n\tresult.evidence.l4 = l4 ? `decisions reached: ${report.decisions}` : \"no decision reached\";\n\tresult.level = l2 ? (l3 ? (l4 ? 4 : 3) : 2) : 1;\n\n\t// the measurement (11.6): off and null, interleaved so drift lands on both, K runs each, the medians side by side\n\tconst measurement: Measurement = {\n\t\truns: options.runs,\n\t\toff: [],\n\t\tnull: [],\n\t\toffMedianMs: Number.NaN,\n\t\tnullMedianMs: Number.NaN,\n\t\tslowdown: Number.NaN,\n\t\tfailed: [],\n\t\twithinNoise: false,\n\t};\n\tfor (let i = 0; i < options.runs; i++) {\n\t\tfor (const harness of [\"off\", \"null\"] as const) {\n\t\t\tconst timed = await runCommand(check.run, {\n\t\t\t\tcwd: subject.root,\n\t\t\t\tenv: subjectEnv(options.env, { ABAI_HARNESS: harness, ABAI_MODE: mode }),\n\t\t\t\ttimeoutMs: options.timeoutMs,\n\t\t\t});\n\t\t\tif (timed.timedOut || timed.code !== 0) measurement.failed.push(`${harness}: ${describeRun(timed)}`);\n\t\t\telse measurement[harness].push(timed.ms);\n\t\t}\n\t}\n\tif (measurement.failed.length > 0) {\n\t\tviolations.push({\n\t\t\twhere: `check.run under ${mode} with ABAI_HARNESS=off and null`,\n\t\t\twhat: `measurement runs failed: ${measurement.failed.join(\"; \")}`,\n\t\t});\n\t}\n\tif (measurement.off.length > 0 && measurement.null.length > 0) {\n\t\tmeasurement.offMedianMs = median(measurement.off);\n\t\tmeasurement.nullMedianMs = median(measurement.null);\n\t\tmeasurement.slowdown =\n\t\t\tmeasurement.offMedianMs > 0 ? measurement.nullMedianMs / measurement.offMedianMs - 1 : Number.NaN;\n\t\tconst off = spread(measurement.off);\n\t\tconst nul = spread(measurement.null);\n\t\tmeasurement.withinNoise = measurement.offMedianMs < NOISE_FLOOR_MS || (nul.min <= off.max && off.min <= nul.max);\n\t\tif (measurement.withinNoise) {\n\t\t\tnotes.push(\n\t\t\t\t`under ${mode} the overhead numbers are within noise (off ${off.min.toFixed(0)}..${off.max.toFixed(0)} ms, null ${nul.min.toFixed(0)}..${nul.max.toFixed(0)} ms, ${options.runs} runs each): raise --runs or give check.run more work before reading the slowdown`,\n\t\t\t);\n\t\t}\n\t\tconst limit = parseOverhead(check.overhead);\n\t\tif (check.overhead !== undefined && limit === undefined) {\n\t\t\tviolations.push({\n\t\t\t\twhere: \"check.overhead\",\n\t\t\t\twhat: `${JSON.stringify(check.overhead)} is not a percentage such as \"5%\"`,\n\t\t\t});\n\t\t} else if (limit !== undefined) {\n\t\t\tmeasurement.limit = limit;\n\t\t\tif (measurement.slowdown > limit) {\n\t\t\t\tviolations.push({\n\t\t\t\t\twhere: where(\"null\"),\n\t\t\t\t\twhat: `the null-harness run is ${(measurement.slowdown * 100).toFixed(1)}% slower than the off run (medians of ${options.runs}${measurement.withinNoise ? \", within noise\" : \"\"}); check.overhead allows ${check.overhead}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\tresult.measurement = measurement;\n\treturn result;\n}\n\nexport async function checkRepository(options: CheckOptions): Promise<CheckReport> {\n\tconst violations: Violation[] = [];\n\tconst unexercised: CheckReport[\"unexercised\"] = [];\n\tconst notes: string[] = [];\n\tconst subject = loadSubject(options.repo, options.cwd);\n\tconst manifest = subject.manifest;\n\tconst entry = options.entry ?? manifest.entry;\n\tconst subjectForEntry: Subject = options.entry\n\t\t? { ...subject, manifest: { ...manifest, entry: options.entry } }\n\t\t: subject;\n\tconst runs = options.runs ?? DEFAULT_RUNS;\n\tconst timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\n\tconst l1 = await checkLevelOne(subjectForEntry, entry, subjectEnv(options.env), violations);\n\n\tlet checkedModes: Mode[] = manifest.modes;\n\tif (options.mode !== undefined) {\n\t\tif (!manifest.modes.includes(options.mode)) {\n\t\t\tviolations.push({\n\t\t\t\twhere: \"--mode\",\n\t\t\t\twhat: `${manifest.name} declares ${manifest.modes.join(\", \")}, not ${options.mode}`,\n\t\t\t});\n\t\t\tcheckedModes = [];\n\t\t} else checkedModes = [options.mode];\n\t}\n\tif (!/\\babai$/.test(entry.trim())) {\n\t\tnotes.push(\n\t\t\t`the entry \"${entry}\" does not end in the word abai: the stub's runEntry answers only \"abai ...\", so the verbs reach the program only if it translates them itself`,\n\t\t);\n\t}\n\tif (checkedModes.includes(\"sidecar\") && manifest.check?.run) {\n\t\tnotes.push(\n\t\t\t\"under sidecar this instantiation keeps the null harness in the program's process and opens no socket for it, so the measured overhead leaves out the serialization sidecar observation costs (a deviation every manifest it writes declares)\",\n\t\t);\n\t}\n\n\tconst perMode: ModeResult[] = [];\n\tif (l1.ok && manifest.check?.run) {\n\t\tfor (const mode of checkedModes) {\n\t\t\tperMode.push(\n\t\t\t\tawait checkMode(subject, mode, { runs, timeoutMs, env: options.env }, violations, unexercised, notes),\n\t\t\t);\n\t\t}\n\t} else if (l1.ok) {\n\t\tnotes.push(\n\t\t\t\"check.run is not declared, so nothing above level 1 can be shown and nothing is measured (section 12)\",\n\t\t);\n\t}\n\n\tlet level = 0;\n\tif (l1.ok) level = perMode.length > 0 ? Math.min(...perMode.map((m) => m.level)) : 1;\n\tconst requested = options.level;\n\tconst passed = level >= (requested ?? 1) && violations.length === 0;\n\treturn {\n\t\troot: subject.root,\n\t\tname: manifest.name,\n\t\tabaigrammar: manifest.abaigrammar,\n\t\tentry,\n\t\tdeclaredModes: manifest.modes,\n\t\tcheckedModes,\n\t\tcheckRun: manifest.check?.run,\n\t\toverheadLimit: manifest.check?.overhead,\n\t\tcompiledOut: \"not offered\",\n\t\tbuilt: \"no\",\n\t\tl1,\n\t\tperMode,\n\t\tlevel,\n\t\trequested,\n\t\tpassed,\n\t\tunexercised,\n\t\tviolations,\n\t\tnotes,\n\t};\n}\n\nfunction pct(value: number): string {\n\treturn Number.isNaN(value) ? \"n/a\" : `${value >= 0 ? \"+\" : \"\"}${(value * 100).toFixed(1)}%`;\n}\n\nfunction range(values: number[]): string {\n\tif (values.length === 0) return \"failed\";\n\tconst { min, max } = spread(values);\n\treturn `${median(values).toFixed(0)} (${min.toFixed(0)}..${max.toFixed(0)})`;\n}\n\nexport function renderReport(report: CheckReport): string {\n\tconst lines: string[] = [];\n\tlines.push(\n\t\t`abaikit check: ${report.name} at ${report.root} (abaigrammar ${report.abaigrammar}, entry: ${report.entry})`,\n\t);\n\tlet verdict: string;\n\tif (report.requested === undefined) verdict = report.violations.length === 0 ? \"no violations\" : \"with violations\";\n\telse if (report.level < report.requested) verdict = `requested ${report.requested}: not reached`;\n\telse\n\t\tverdict =\n\t\t\treport.violations.length === 0\n\t\t\t\t? `requested ${report.requested}: passed`\n\t\t\t\t: `requested ${report.requested}: reached, with violations`;\n\tlines.push(\n\t\treport.level === 0\n\t\t\t? `level: 0 (L1 not reached; ${verdict})`\n\t\t\t: `level: ${report.level} ${LEVEL_NAMES[report.level]} (${verdict})`,\n\t);\n\tlines.push(\n\t\t`modes: ${report.declaredModes.join(\", \")}${report.checkedModes.length === report.declaredModes.length ? \"\" : `; checked: ${report.checkedModes.join(\", \") || \"none\"}`}`,\n\t);\n\tlines.push(\n\t\t`L1 reachable: ${report.l1.ok ? \"ok\" : \"not reached\"}${report.l1.detail ? ` (${report.l1.detail})` : \"\"}; ran: ${report.l1.ran.join(\"; \")}`,\n\t);\n\tfor (const n of [2, 3, 4] as const) {\n\t\tconst key = `l${n}` as const;\n\t\tconst parts = report.perMode.map((m) => {\n\t\t\tif (m.exercise && !m.exercise.report) return `${m.mode}: exercise run failed`;\n\t\t\tif (!m.evidence[key]) return `${m.mode}: not run`;\n\t\t\treturn `${m.mode}: ${m.level >= n ? \"ok\" : \"no\"}, ${m.evidence[key]}`;\n\t\t});\n\t\tlines.push(`L${n} ${LEVEL_NAMES[n]}: ${parts.length > 0 ? parts.join(\"; \") : \"not shown\"}`);\n\t}\n\tif (report.checkRun !== undefined && report.perMode.some((m) => m.measurement)) {\n\t\tlines.push(\n\t\t\t`overhead (check.run: ${report.checkRun}; built: ${report.built}, the command runs as is; compiled out: ${report.compiledOut}; median ms (min..max) of each run set):`,\n\t\t);\n\t\tlines.push(\" mode runs off null slowdown limit\");\n\t\tfor (const m of report.perMode) {\n\t\t\tconst x = m.measurement;\n\t\t\tif (!x) continue;\n\t\t\tconst limit = x.limit === undefined ? \"none\" : `${(x.limit * 100).toFixed(1)}%`;\n\t\t\tlines.push(\n\t\t\t\t` ${m.mode.padEnd(9)} ${String(x.runs).padEnd(5)} ${range(x.off).padEnd(18)} ${range(x.null).padEnd(18)} ${pct(x.slowdown).padEnd(10)} ${limit}${x.withinNoise ? \" (within noise)\" : \"\"}`,\n\t\t\t);\n\t\t}\n\t}\n\tlines.push(\n\t\treport.unexercised.length === 0\n\t\t\t? \"unexercised: none\"\n\t\t\t: `unexercised:\\n${report.unexercised.map((u) => ` ${u.mode}: ${u.kind} ${u.name}: ${u.why}`).join(\"\\n\")}`,\n\t);\n\tlines.push(\n\t\treport.violations.length === 0\n\t\t\t? \"violations: none\"\n\t\t\t: `violations:\\n${report.violations.map((v) => ` ${v.where}: ${v.what}`).join(\"\\n\")}`,\n\t);\n\tfor (const note of report.notes) lines.push(`note: ${note}`);\n\treturn `${lines.join(\"\\n\")}\\n`;\n}\n\n/** abaikit's own channels see every check: two cells and one event, for the agent fused into abaikit. */\nexport function recordCheck(app: Abaigram | undefined, report: CheckReport): void {\n\tif (!app) return;\n\tconst runs = app.cell<number>(\"check.runs\");\n\truns.set((runs.get() ?? 0) + 1);\n\tapp.cell<number>(\"check.last_level\").set(report.level);\n\tapp.event(\"check.completed\").emit({ repo: report.root, level: report.level });\n}\n\n/** The `check` capability: the same check, its report as text, for the agent on any front end. */\nexport function checkHandler(app: Abaigram, io: Pick<AbaikitIo, \"cwd\" | \"env\">) {\n\treturn async (params: Record<string, unknown>): Promise<{ level: number; passed: boolean; report: string }> => {\n\t\tif (typeof params.repo !== \"string\" || params.repo === \"\") throw new UsageError(\"check needs a repo\");\n\t\tconst level = typeof params.level === \"number\" ? params.level : undefined;\n\t\tif (level !== undefined && (!Number.isInteger(level) || level < 1 || level > 4)) {\n\t\t\tthrow new UsageError(\"level must be 1 to 4\");\n\t\t}\n\t\tconst mode = typeof params.mode === \"string\" && params.mode !== \"\" ? params.mode : undefined;\n\t\tif (mode !== undefined && mode !== \"turns\" && mode !== \"sidecar\")\n\t\t\tthrow new UsageError(\"mode must be turns or sidecar\");\n\t\tconst entry = typeof params.entry === \"string\" && params.entry !== \"\" ? params.entry : undefined;\n\t\tconst runs =\n\t\t\ttypeof params.runs === \"number\" && Number.isInteger(params.runs) && params.runs > 0 ? params.runs : undefined;\n\t\tconst report = await checkRepository({ repo: params.repo, cwd: io.cwd, env: io.env, level, mode, entry, runs });\n\t\trecordCheck(app, report);\n\t\treturn { level: report.level, passed: report.passed, report: renderReport(report) };\n\t};\n}\n\nexport async function runCheck(\n\tparsed: Extract<ParsedArgs, { verb: \"check\" }>,\n\tio: AbaikitIo,\n\tapp?: Abaigram,\n): Promise<number> {\n\tconst report = await checkRepository({\n\t\trepo: parsed.repo,\n\t\tcwd: io.cwd,\n\t\tenv: io.env,\n\t\tlevel: parsed.level,\n\t\tmode: parsed.mode,\n\t\tentry: parsed.entry,\n\t\truns: parsed.runs,\n\t\ttimeoutMs: parsed.timeoutS === undefined ? undefined : parsed.timeoutS * 1000,\n\t});\n\trecordCheck(app, report);\n\tio.out(parsed.json ? `${JSON.stringify(report, null, 2)}\\n` : renderReport(report));\n\treturn report.passed ? 0 : 1;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"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","sourcesContent":["// abaikit check: conformance as section 12 defines it, with no model.\n// Level 1 is reached through the subject's entry alone (what `manifest`\n// prints, byte for byte the checked-in file, and `doctor --offline --json`); levels 2 to 4 through its `check.run`\n// under the exercise null harness, once per declared mode, read from the\n// report the stub prints at exit; the overhead of 11.6 by the same command\n// under `ABAI_HARNESS=off` and `ABAI_HARNESS=null`, interleaved, side by\n// side. The subject's environment is constructed, never inherited: each\n// run gets exactly the `ABAI_HARNESS` and `ABAI_MODE` it means, the entry\n// runs get neither. A level is the one reached under every checked mode,\n// and passing means that level with no violation.\nimport { readFileSync } from \"node:fs\";\nimport type { Abaigram, DoctorCheck, Manifest, Mode } from \"@abaigram/abai-stub\";\nimport { parseManifestYaml, validateManifest } from \"@abaigram/abai-stub\";\nimport type { ParsedArgs } from \"./bin.ts\";\nimport {\n\ttype CommandRun,\n\tjsonDocument,\n\tlastJsonLine,\n\tlastPlainLine,\n\tmedian,\n\trunCommand,\n\tsubjectEnv,\n\ttailOf,\n} from \"./command.ts\";\nimport { type AbaikitIo, errorMessage, UsageError } from \"./io.ts\";\nimport { entryCommand, loadSubject, type Subject } from \"./subject.ts\";\n\nexport const DEFAULT_RUNS = 3;\nexport const DEFAULT_TIMEOUT_MS = 120_000;\n/** How long an entry verb (manifest, doctor) may take. */\nexport const ENTRY_TIMEOUT_MS = 60_000;\n/** Below this median for the off run, startup noise is most of the number. */\nexport const NOISE_FLOOR_MS = 500;\n/** Characters of a run's output the JSON report carries. */\nconst REPORT_TAIL_CHARS = 4096;\nexport const LEVEL_NAMES = [\"none\", \"reachable\", \"observable\", \"steerable\", \"deliberative\"] as const;\n\nexport interface CheckOptions {\n\trepo: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n\tlevel?: number;\n\tmode?: Mode;\n\tentry?: string;\n\truns?: number;\n\ttimeoutMs?: number;\n}\n\n/** What the stub's exercise harness reports at exit (abai's NullHarnessReport, as JSON on stderr). */\nexport interface ExerciseReport {\n\tform: string;\n\tevents: number;\n\tdropped: number;\n\tdecisions: number;\n\tturns: number;\n\ttouchpoints: number;\n\tcellsWritten: string[];\n\t/** The program's own events, by name; absent in a report from an older stub. */\n\teventsEmitted?: string[];\n\tknobsWritten: string[];\n\tcapabilitiesCalled: string[];\n\tunexercised: Array<{ kind: string; name: string; why: string }>;\n}\n\nexport interface Measurement {\n\truns: number;\n\toff: number[];\n\tnull: number[];\n\toffMedianMs: number;\n\tnullMedianMs: number;\n\t/** null over off, minus one; NaN when either side has no run. */\n\tslowdown: number;\n\tlimit?: number;\n\t/** The runs that did not exit 0 or timed out, by harness. */\n\tfailed: string[];\n\t/** The numbers are within startup noise or the two ranges overlap. */\n\twithinNoise: boolean;\n}\n\nexport interface ModeResult {\n\tmode: Mode;\n\t/** The highest level this mode demonstrated, 1 to 4. */\n\tlevel: number;\n\texercise?: { run: CommandRun; report?: ExerciseReport };\n\tevidence: { l2: string; l3: string; l4: string };\n\tmeasurement?: Measurement;\n}\n\nexport interface Violation {\n\twhere: string;\n\twhat: string;\n}\n\nexport interface CheckReport {\n\troot: string;\n\tname: string;\n\tabaigrammar: string;\n\tentry: string;\n\tdeclaredModes: Mode[];\n\tcheckedModes: Mode[];\n\tcheckRun?: string;\n\toverheadLimit?: string;\n\t/** This instantiation offers no build with the stub compiled out, and builds nothing: the command runs as is. */\n\tcompiledOut: \"not offered\";\n\tbuilt: \"no\";\n\tl1: { ok: boolean; manifestAgrees: boolean; doctor: DoctorCheck[]; ran: string[]; detail: string };\n\tperMode: ModeResult[];\n\tlevel: number;\n\trequested?: number;\n\tpassed: boolean;\n\tunexercised: Array<{ mode: Mode; kind: string; name: string; why: string }>;\n\tviolations: Violation[];\n\tnotes: string[];\n}\n\nfunction parseOverhead(limit: string | undefined): number | undefined {\n\tif (limit === undefined) return undefined;\n\tconst match = /^(\\d+(?:\\.\\d+)?)\\s*%$/.exec(limit.trim());\n\treturn match ? Number(match[1]) / 100 : undefined;\n}\n\nfunction firstDifferingLine(a: string, b: string): number {\n\tconst al = a.split(\"\\n\");\n\tconst bl = b.split(\"\\n\");\n\tfor (let i = 0; i < Math.max(al.length, bl.length); i++) if (al[i] !== bl[i]) return i + 1;\n\treturn 0;\n}\n\nfunction isExerciseReport(\n\tvalue: Record<string, unknown> | undefined,\n): value is ExerciseReport & Record<string, unknown> {\n\treturn value !== undefined && value.form === \"exercise\" && Array.isArray(value.unexercised);\n}\n\nfunction describeRun(run: CommandRun): string {\n\tif (run.timedOut) return \"did not finish within the timeout and was ended\";\n\tif (run.code !== 0) return `exited ${run.code ?? run.signal ?? \"?\"}`;\n\treturn \"exited 0\";\n}\n\nfunction lastWords(run: CommandRun): string {\n\treturn lastPlainLine(run.stderr) || lastPlainLine(run.stdout) || \"no output\";\n}\n\n/** A run as the JSON report carries it: the newest part of each stream, not a whole log. */\nfunction trimmed(run: CommandRun): CommandRun {\n\treturn { ...run, stdout: tailOf(run.stdout, REPORT_TAIL_CHARS), stderr: tailOf(run.stderr, REPORT_TAIL_CHARS) };\n}\n\n/** Level 1 through the entry: the effective manifest, the checked-in file, the offline doctor. */\nasync function checkLevelOne(\n\tsubject: Subject,\n\tentry: string,\n\tenv: NodeJS.ProcessEnv,\n\tviolations: Violation[],\n): Promise<CheckReport[\"l1\"]> {\n\tconst manifest = subject.manifest;\n\tconst fileText = readFileSync(subject.manifestPath, \"utf8\");\n\tlet manifestAgrees = false;\n\tconst details: string[] = [];\n\tconst ran: string[] = [];\n\t// what the entry prints is the manifest: byte for byte the checked-in file (section 12), and valid\n\tconst manifestCommand = entryCommand(manifest, \"manifest\");\n\tran.push(manifestCommand);\n\tconst shown = await runCommand(manifestCommand, { cwd: subject.root, env, timeoutMs: ENTRY_TIMEOUT_MS });\n\tif (shown.code !== 0) {\n\t\tviolations.push({ where: manifestCommand, what: `${describeRun(shown)}: ${lastWords(shown)}` });\n\t} else {\n\t\tlet effective: unknown;\n\t\ttry {\n\t\t\teffective = parseManifestYaml(shown.stdout);\n\t\t} catch (error) {\n\t\t\tviolations.push({ where: manifestCommand, what: `did not print a manifest: ${errorMessage(error)}` });\n\t\t}\n\t\tif (effective !== undefined) {\n\t\t\tconst problems = validateManifest(effective);\n\t\t\tif (problems.length > 0) {\n\t\t\t\tviolations.push({\n\t\t\t\t\twhere: manifestCommand,\n\t\t\t\t\twhat: `the printed manifest does not validate: ${problems.join(\"; \")}`,\n\t\t\t\t});\n\t\t\t} else if ((effective as Manifest).name !== manifest.name) {\n\t\t\t\tviolations.push({\n\t\t\t\t\twhere: subject.manifestPath,\n\t\t\t\t\twhat: `names ${manifest.name}, but the entry's program is ${(effective as Manifest).name}`,\n\t\t\t\t});\n\t\t\t} else if (shown.stdout === fileText) {\n\t\t\t\tmanifestAgrees = true;\n\t\t\t\tdetails.push(\"abaigram.yaml is what the entry prints\");\n\t\t\t} else {\n\t\t\t\tviolations.push({\n\t\t\t\t\twhere: subject.manifestPath,\n\t\t\t\t\twhat: `is stale: first difference at line ${firstDifferingLine(fileText, shown.stdout)}; run: ${entry} manifest > abaigram.yaml`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\tlet doctor: DoctorCheck[] = [];\n\tconst doctorCommand = entryCommand(manifest, \"doctor\", \"--offline\", \"--json\");\n\tran.push(doctorCommand);\n\tconst examined = await runCommand(doctorCommand, { cwd: subject.root, env, timeoutMs: ENTRY_TIMEOUT_MS });\n\tconst parsed = jsonDocument(examined.stdout);\n\tif (parsed && Array.isArray(parsed.checks)) {\n\t\tdoctor = parsed.checks as DoctorCheck[];\n\t\tfor (const check of doctor) {\n\t\t\t// the manifest file is judged above, with the hint for this entry; the doctor's word on it would repeat it\n\t\t\tif (check.status === \"fail\" && check.name !== \"abaigram.yaml\") {\n\t\t\t\tviolations.push({ where: `doctor: ${check.name}`, what: check.detail });\n\t\t\t}\n\t\t}\n\t\tconst failed = doctor.filter((c) => c.status === \"fail\").length;\n\t\tdetails.push(`doctor: ${doctor.filter((c) => c.status === \"ok\").length} ok, ${failed} failed`);\n\t} else {\n\t\tviolations.push({\n\t\t\twhere: doctorCommand,\n\t\t\twhat: `${describeRun(examined)} and printed no report: ${lastWords(examined)}`,\n\t\t});\n\t}\n\tconst ok = manifestAgrees && doctor.length > 0 && doctor.every((c) => c.status !== \"fail\");\n\treturn { ok, manifestAgrees, doctor, ran, detail: details.join(\"; \") };\n}\n\nfunction spread(values: number[]): { min: number; max: number } {\n\treturn { min: Math.min(...values), max: Math.max(...values) };\n}\n\n/** Levels 2 to 4 and the measurement, under one mode. */\nasync function checkMode(\n\tsubject: Subject,\n\tmode: Mode,\n\toptions: { runs: number; timeoutMs: number; env: NodeJS.ProcessEnv },\n\tviolations: Violation[],\n\tunexercised: CheckReport[\"unexercised\"],\n\tnotes: string[],\n): Promise<ModeResult> {\n\tconst manifest = subject.manifest;\n\tconst check = manifest.check as { run: string; overhead?: string };\n\tconst result: ModeResult = { mode, level: 1, evidence: { l2: \"\", l3: \"\", l4: \"\" } };\n\tconst where = (harness: string) => `check.run under ${mode} with ABAI_HARNESS=${harness}`;\n\tconst run = await runCommand(check.run, {\n\t\tcwd: subject.root,\n\t\tenv: subjectEnv(options.env, { ABAI_HARNESS: \"exercise\", ABAI_MODE: mode }),\n\t\ttimeoutMs: options.timeoutMs,\n\t});\n\tresult.exercise = { run: trimmed(run) };\n\t// the report is the stub's exit hook: it is there even when the program failed, and says what was reached\n\tconst report = lastJsonLine(run.stderr, (v) => v.form === \"exercise\");\n\tif (isExerciseReport(report)) {\n\t\tresult.exercise.report = report;\n\t\tfor (const u of report.unexercised) unexercised.push({ mode, ...u });\n\t\tfor (const cell of manifest.cells) {\n\t\t\tif (cell.access === \"read\" && !report.cellsWritten.includes(cell.name)) {\n\t\t\t\tunexercised.push({ mode, kind: \"cell\", name: cell.name, why: \"not written during the exercise run\" });\n\t\t\t}\n\t\t}\n\t\tif (report.eventsEmitted) {\n\t\t\tfor (const event of manifest.events) {\n\t\t\t\tif (!report.eventsEmitted.includes(event.name)) {\n\t\t\t\t\tunexercised.push({ mode, kind: \"event\", name: event.name, why: \"not emitted during the exercise run\" });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (run.timedOut || run.code !== 0) {\n\t\tviolations.push({ where: where(\"exercise\"), what: `${describeRun(run)}: ${lastWords(run)}` });\n\t\treturn result;\n\t}\n\tif (!isExerciseReport(report)) {\n\t\tviolations.push({\n\t\t\twhere: where(\"exercise\"),\n\t\t\twhat: `printed no exercise report at exit${run.dropped.stderr > 0 ? ` in the ${run.stderr.length} newest bytes of stderr kept` : \"\"}: the stub did not attach its null harness (is the entry hook in main, and the program built?)`,\n\t\t});\n\t\treturn result;\n\t}\n\t// the program's own events, by name; a report that names none (an older stub) shows none: the library's do not count\n\tconst emitted = report.eventsEmitted ?? [];\n\tconst l2 = report.cellsWritten.length > 0 || emitted.length > 0;\n\tresult.evidence.l2 = l2\n\t\t? `cells written: ${report.cellsWritten.join(\", \") || \"none\"}; events: ${emitted.join(\", \") || \"none\"}`\n\t\t: \"no cell written and no event emitted during the exercise run\";\n\tconst l3 = report.capabilitiesCalled.length > 0 || report.knobsWritten.length > 0;\n\tresult.evidence.l3 = l3\n\t\t? `capabilities called: ${report.capabilitiesCalled.join(\", \") || \"none\"}; knobs landed: ${report.knobsWritten.join(\", \") || \"none\"}`\n\t\t: \"no capability called and no knob landed\";\n\tconst l4 = report.decisions > 0;\n\tresult.evidence.l4 = l4 ? `decisions reached: ${report.decisions}` : \"no decision reached\";\n\tresult.level = l2 ? (l3 ? (l4 ? 4 : 3) : 2) : 1;\n\n\t// the measurement (11.6): off and null, interleaved so drift lands on both, K runs each, the medians side by side\n\tconst measurement: Measurement = {\n\t\truns: options.runs,\n\t\toff: [],\n\t\tnull: [],\n\t\toffMedianMs: Number.NaN,\n\t\tnullMedianMs: Number.NaN,\n\t\tslowdown: Number.NaN,\n\t\tfailed: [],\n\t\twithinNoise: false,\n\t};\n\tfor (let i = 0; i < options.runs; i++) {\n\t\tfor (const harness of [\"off\", \"null\"] as const) {\n\t\t\tconst timed = await runCommand(check.run, {\n\t\t\t\tcwd: subject.root,\n\t\t\t\tenv: subjectEnv(options.env, { ABAI_HARNESS: harness, ABAI_MODE: mode }),\n\t\t\t\ttimeoutMs: options.timeoutMs,\n\t\t\t});\n\t\t\tif (timed.timedOut || timed.code !== 0) measurement.failed.push(`${harness}: ${describeRun(timed)}`);\n\t\t\telse measurement[harness].push(timed.ms);\n\t\t}\n\t}\n\tif (measurement.failed.length > 0) {\n\t\tviolations.push({\n\t\t\twhere: `check.run under ${mode} with ABAI_HARNESS=off and null`,\n\t\t\twhat: `measurement runs failed: ${measurement.failed.join(\"; \")}`,\n\t\t});\n\t}\n\tif (measurement.off.length > 0 && measurement.null.length > 0) {\n\t\tmeasurement.offMedianMs = median(measurement.off);\n\t\tmeasurement.nullMedianMs = median(measurement.null);\n\t\tmeasurement.slowdown =\n\t\t\tmeasurement.offMedianMs > 0 ? measurement.nullMedianMs / measurement.offMedianMs - 1 : Number.NaN;\n\t\tconst off = spread(measurement.off);\n\t\tconst nul = spread(measurement.null);\n\t\tmeasurement.withinNoise = measurement.offMedianMs < NOISE_FLOOR_MS || (nul.min <= off.max && off.min <= nul.max);\n\t\tif (measurement.withinNoise) {\n\t\t\tnotes.push(\n\t\t\t\t`under ${mode} the overhead numbers are within noise (off ${off.min.toFixed(0)}..${off.max.toFixed(0)} ms, null ${nul.min.toFixed(0)}..${nul.max.toFixed(0)} ms, ${options.runs} runs each): raise --runs or give check.run more work before reading the slowdown`,\n\t\t\t);\n\t\t}\n\t\tconst limit = parseOverhead(check.overhead);\n\t\tif (check.overhead !== undefined && limit === undefined) {\n\t\t\tviolations.push({\n\t\t\t\twhere: \"check.overhead\",\n\t\t\t\twhat: `${JSON.stringify(check.overhead)} is not a percentage such as \"5%\"`,\n\t\t\t});\n\t\t} else if (limit !== undefined) {\n\t\t\tmeasurement.limit = limit;\n\t\t\tif (measurement.slowdown > limit) {\n\t\t\t\tviolations.push({\n\t\t\t\t\twhere: where(\"null\"),\n\t\t\t\t\twhat: `the null-harness run is ${(measurement.slowdown * 100).toFixed(1)}% slower than the off run (medians of ${options.runs}${measurement.withinNoise ? \", within noise\" : \"\"}); check.overhead allows ${check.overhead}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\tresult.measurement = measurement;\n\treturn result;\n}\n\nexport async function checkRepository(options: CheckOptions): Promise<CheckReport> {\n\tconst violations: Violation[] = [];\n\tconst unexercised: CheckReport[\"unexercised\"] = [];\n\tconst notes: string[] = [];\n\tconst subject = loadSubject(options.repo, options.cwd);\n\tconst manifest = subject.manifest;\n\tconst entry = options.entry ?? manifest.entry;\n\tconst subjectForEntry: Subject = options.entry\n\t\t? { ...subject, manifest: { ...manifest, entry: options.entry } }\n\t\t: subject;\n\tconst runs = options.runs ?? DEFAULT_RUNS;\n\tconst timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\n\tconst l1 = await checkLevelOne(subjectForEntry, entry, subjectEnv(options.env), violations);\n\n\tlet checkedModes: Mode[] = manifest.modes;\n\tif (options.mode !== undefined) {\n\t\tif (!manifest.modes.includes(options.mode)) {\n\t\t\tviolations.push({\n\t\t\t\twhere: \"--mode\",\n\t\t\t\twhat: `${manifest.name} declares ${manifest.modes.join(\", \")}, not ${options.mode}`,\n\t\t\t});\n\t\t\tcheckedModes = [];\n\t\t} else checkedModes = [options.mode];\n\t}\n\tif (!/\\babai$/.test(entry.trim())) {\n\t\tnotes.push(\n\t\t\t`the entry \"${entry}\" does not end in the word abai: the stub's runEntry answers only \"abai ...\", so the verbs reach the program only if it translates them itself`,\n\t\t);\n\t}\n\tif (checkedModes.includes(\"sidecar\") && manifest.check?.run) {\n\t\tnotes.push(\n\t\t\t\"under sidecar this instantiation keeps the null harness in the program's process and opens no socket for it, so the measured overhead leaves out the serialization sidecar observation costs (a deviation every manifest it writes declares)\",\n\t\t);\n\t}\n\n\tconst perMode: ModeResult[] = [];\n\tif (l1.ok && manifest.check?.run) {\n\t\tfor (const mode of checkedModes) {\n\t\t\tperMode.push(\n\t\t\t\tawait checkMode(subject, mode, { runs, timeoutMs, env: options.env }, violations, unexercised, notes),\n\t\t\t);\n\t\t}\n\t} else if (l1.ok) {\n\t\tnotes.push(\n\t\t\t\"check.run is not declared, so nothing above level 1 can be shown and nothing is measured (section 12)\",\n\t\t);\n\t}\n\n\tlet level = 0;\n\tif (l1.ok) level = perMode.length > 0 ? Math.min(...perMode.map((m) => m.level)) : 1;\n\tconst requested = options.level;\n\tconst passed = level >= (requested ?? 1) && violations.length === 0;\n\treturn {\n\t\troot: subject.root,\n\t\tname: manifest.name,\n\t\tabaigrammar: manifest.abaigrammar,\n\t\tentry,\n\t\tdeclaredModes: manifest.modes,\n\t\tcheckedModes,\n\t\tcheckRun: manifest.check?.run,\n\t\toverheadLimit: manifest.check?.overhead,\n\t\tcompiledOut: \"not offered\",\n\t\tbuilt: \"no\",\n\t\tl1,\n\t\tperMode,\n\t\tlevel,\n\t\trequested,\n\t\tpassed,\n\t\tunexercised,\n\t\tviolations,\n\t\tnotes,\n\t};\n}\n\nfunction pct(value: number): string {\n\treturn Number.isNaN(value) ? \"n/a\" : `${value >= 0 ? \"+\" : \"\"}${(value * 100).toFixed(1)}%`;\n}\n\nfunction range(values: number[]): string {\n\tif (values.length === 0) return \"failed\";\n\tconst { min, max } = spread(values);\n\treturn `${median(values).toFixed(0)} (${min.toFixed(0)}..${max.toFixed(0)})`;\n}\n\nexport function renderReport(report: CheckReport): string {\n\tconst lines: string[] = [];\n\tlines.push(\n\t\t`abaikit check: ${report.name} at ${report.root} (abaigrammar ${report.abaigrammar}, entry: ${report.entry})`,\n\t);\n\tlet verdict: string;\n\tif (report.requested === undefined) verdict = report.violations.length === 0 ? \"no violations\" : \"with violations\";\n\telse if (report.level < report.requested) verdict = `requested ${report.requested}: not reached`;\n\telse\n\t\tverdict =\n\t\t\treport.violations.length === 0\n\t\t\t\t? `requested ${report.requested}: passed`\n\t\t\t\t: `requested ${report.requested}: reached, with violations`;\n\tlines.push(\n\t\treport.level === 0\n\t\t\t? `level: 0 (L1 not reached; ${verdict})`\n\t\t\t: `level: ${report.level} ${LEVEL_NAMES[report.level]} (${verdict})`,\n\t);\n\tlines.push(\n\t\t`modes: ${report.declaredModes.join(\", \")}${report.checkedModes.length === report.declaredModes.length ? \"\" : `; checked: ${report.checkedModes.join(\", \") || \"none\"}`}`,\n\t);\n\tlines.push(\n\t\t`L1 reachable: ${report.l1.ok ? \"ok\" : \"not reached\"}${report.l1.detail ? ` (${report.l1.detail})` : \"\"}; ran: ${report.l1.ran.join(\"; \")}`,\n\t);\n\tfor (const n of [2, 3, 4] as const) {\n\t\tconst key = `l${n}` as const;\n\t\tconst parts = report.perMode.map((m) => {\n\t\t\tif (m.exercise && !m.exercise.report) return `${m.mode}: exercise run failed`;\n\t\t\tif (!m.evidence[key]) return `${m.mode}: not run`;\n\t\t\treturn `${m.mode}: ${m.level >= n ? \"ok\" : \"no\"}, ${m.evidence[key]}`;\n\t\t});\n\t\tlines.push(`L${n} ${LEVEL_NAMES[n]}: ${parts.length > 0 ? parts.join(\"; \") : \"not shown\"}`);\n\t}\n\tif (report.checkRun !== undefined && report.perMode.some((m) => m.measurement)) {\n\t\tlines.push(\n\t\t\t`overhead (check.run: ${report.checkRun}; built: ${report.built}, the command runs as is; compiled out: ${report.compiledOut}; median ms (min..max) of each run set):`,\n\t\t);\n\t\tlines.push(\" mode runs off null slowdown limit\");\n\t\tfor (const m of report.perMode) {\n\t\t\tconst x = m.measurement;\n\t\t\tif (!x) continue;\n\t\t\tconst limit = x.limit === undefined ? \"none\" : `${(x.limit * 100).toFixed(1)}%`;\n\t\t\tlines.push(\n\t\t\t\t` ${m.mode.padEnd(9)} ${String(x.runs).padEnd(5)} ${range(x.off).padEnd(18)} ${range(x.null).padEnd(18)} ${pct(x.slowdown).padEnd(10)} ${limit}${x.withinNoise ? \" (within noise)\" : \"\"}`,\n\t\t\t);\n\t\t}\n\t}\n\tlines.push(\n\t\treport.unexercised.length === 0\n\t\t\t? \"unexercised: none\"\n\t\t\t: `unexercised:\\n${report.unexercised.map((u) => ` ${u.mode}: ${u.kind} ${u.name}: ${u.why}`).join(\"\\n\")}`,\n\t);\n\tlines.push(\n\t\treport.violations.length === 0\n\t\t\t? \"violations: none\"\n\t\t\t: `violations:\\n${report.violations.map((v) => ` ${v.where}: ${v.what}`).join(\"\\n\")}`,\n\t);\n\tfor (const note of report.notes) lines.push(`note: ${note}`);\n\treturn `${lines.join(\"\\n\")}\\n`;\n}\n\n/** abaikit's own channels see every check: two cells and one event, for the agent fused into abaikit. */\nexport function recordCheck(app: Abaigram | undefined, report: CheckReport): void {\n\tif (!app) return;\n\tconst runs = app.cell<number>(\"check.runs\");\n\truns.set((runs.get() ?? 0) + 1);\n\tapp.cell<number>(\"check.last_level\").set(report.level);\n\tapp.event(\"check.completed\").emit({ repo: report.root, level: report.level });\n}\n\n/** The `check` capability: the same check, its report as text, for the agent on any front end. */\nexport function checkHandler(app: Abaigram, io: Pick<AbaikitIo, \"cwd\" | \"env\">) {\n\treturn async (params: Record<string, unknown>): Promise<{ level: number; passed: boolean; report: string }> => {\n\t\tif (typeof params.repo !== \"string\" || params.repo === \"\") throw new UsageError(\"check needs a repo\");\n\t\tconst level = typeof params.level === \"number\" ? params.level : undefined;\n\t\tif (level !== undefined && (!Number.isInteger(level) || level < 1 || level > 4)) {\n\t\t\tthrow new UsageError(\"level must be 1 to 4\");\n\t\t}\n\t\tconst mode = typeof params.mode === \"string\" && params.mode !== \"\" ? params.mode : undefined;\n\t\tif (mode !== undefined && mode !== \"turns\" && mode !== \"thread\" && mode !== \"sidecar\")\n\t\t\tthrow new UsageError(\"mode must be turns, thread or sidecar\");\n\t\tconst entry = typeof params.entry === \"string\" && params.entry !== \"\" ? params.entry : undefined;\n\t\tconst runs =\n\t\t\ttypeof params.runs === \"number\" && Number.isInteger(params.runs) && params.runs > 0 ? params.runs : undefined;\n\t\tconst report = await checkRepository({ repo: params.repo, cwd: io.cwd, env: io.env, level, mode, entry, runs });\n\t\trecordCheck(app, report);\n\t\treturn { level: report.level, passed: report.passed, report: renderReport(report) };\n\t};\n}\n\nexport async function runCheck(\n\tparsed: Extract<ParsedArgs, { verb: \"check\" }>,\n\tio: AbaikitIo,\n\tapp?: Abaigram,\n): Promise<number> {\n\tconst report = await checkRepository({\n\t\trepo: parsed.repo,\n\t\tcwd: io.cwd,\n\t\tenv: io.env,\n\t\tlevel: parsed.level,\n\t\tmode: parsed.mode,\n\t\tentry: parsed.entry,\n\t\truns: parsed.runs,\n\t\ttimeoutMs: parsed.timeoutS === undefined ? undefined : parsed.timeoutS * 1000,\n\t});\n\trecordCheck(app, report);\n\tio.out(parsed.json ? `${JSON.stringify(report, null, 2)}\\n` : renderReport(report));\n\treturn report.passed ? 0 : 1;\n}\n"]}
|
package/dist/learnabai.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learnabai.d.ts","sourceRoot":"","sources":["../src/learnabai.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,SAAS,CAAC;AAGrD,eAAO,MAAM,UAAU,QAA6C,CAAC;AACrE,eAAO,MAAM,UAAU,cAAc,CAAC;AAEtC,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC5B,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,kHAAkH;IAClH,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,qFAAqF;IACrF,aAAa,EAAE,OAAO,CAAC;IACvB,4GAA4G;IAC5G,KAAK,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,KAAK;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,QAAQ,EAAE,YAAY,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACb;AAcD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,WAAW,GAAE,MAAqB,GAAG,YAAY,CA6B7E;AAOD,wDAAwD;AACxD,wBAAgB,SAAS,CAAC,IAAI,GAAE,MAAmB,EAAE,WAAW,GAAE,MAAqB,GAAG,KAAK,CAoD9F;AAED,gEAAgE;AAChE,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,GAAG,YAAY,CAIlE;AAED,mDAAmD;AACnD,wBAAgB,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED,8EAA8E;AAC9E,eAAO,MAAM,gBAAgB;;CAG5B,CAAC;AAEF,gGAAgG;AAChG,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAY9C;AAED,2GAA2G;AAC3G,wBAAgB,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAK7D;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC,EAAE,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBrH","sourcesContent":["// abaikit learnabai: the guide an agent reads before it creates or\n// retrofits an abaigram. One text, `abai/learnabai.md`, delivered three\n// ways: printed by the verb (whole, one section, or as JSON), returned by\n// the `learnabai` capability to an agent on the MCP front end, and written\n// as a Claude Code skill by `--skill`. The text names this machine's way\n// to install the packages and the stub's own deviations, filled in here,\n// so it is never out of step with what is installed.\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { basename, join, resolve } from \"node:path\";\nimport {\n\tABAI_STUB_VERSION,\n\tABAIGRAMMAR_VERSION,\n\tINSTANTIATION_DEVIATIONS,\n\tSIDECAR_DEVIATION,\n} from \"@abaigram/abai-stub\";\nimport { PACKAGE_ROOT } from \"./abaigram.ts\";\nimport type { ParsedArgs } from \"./bin.ts\";\nimport { type AbaikitIo, UsageError } from \"./io.ts\";\nimport { ABAIKIT_VERSION } from \"./version.ts\";\n\nexport const GUIDE_FILE = join(PACKAGE_ROOT, \"abai\", \"learnabai.md\");\nexport const SKILL_NAME = \"learnabai\";\n\nexport interface GuideSection {\n\tid: string;\n\ttitle: string;\n\ttext: string;\n}\n\nexport interface PackageSpecs {\n\t/** `npm install` arguments: `file:` paths, or `name@^version`. */\n\tabai: string;\n\tharness: string;\n\t/** The same packages as package.json values: `file:` paths, or `^version`; abaikit itself for a devDependency. */\n\tdependency: { abai: string; harness: string; abaikit: string };\n\t/** The specs are `file:` paths into a workspace checkout, not published versions. */\n\tfromWorkspace: boolean;\n\t/** Workspace checkouts only: both packages have their `dist/` built, so `npm install` of them works now. */\n\tbuilt: boolean;\n}\n\nexport interface Guide {\n\tabaigrammar: string;\n\tstub: string;\n\tabaikit: string;\n\t/** How this machine installs the stub and the harness. */\n\tpackages: PackageSpecs;\n\theader: string;\n\tsections: GuideSection[];\n\ttext: string;\n}\n\nconst require = createRequire(import.meta.url);\n\nfunction readPackage(dir: string): { name?: unknown; workspaces?: unknown } | undefined {\n\tconst path = join(dir, \"package.json\");\n\tif (!existsSync(path)) return undefined;\n\ttry {\n\t\treturn JSON.parse(readFileSync(path, \"utf8\")) as { name?: unknown; workspaces?: unknown };\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * The specs `npm install` takes for the two packages an abaigram needs, as\n * this abaikit can reach them. Inside the workspace checkout (the parent\n * is the workspace root whose `workspaces` name abaikit, not some\n * `node_modules` where hoisted siblings happen to sit) they are `file:`\n * paths to the sibling packages; anywhere else, the published versions.\n */\nexport function packageSpecs(packageRoot: string = PACKAGE_ROOT): PackageSpecs {\n\tconst workspace = resolve(packageRoot, \"..\");\n\tconst root = readPackage(workspace);\n\tconst workspaces = Array.isArray(root?.workspaces) ? (root.workspaces as unknown[]) : [];\n\tconst inWorkspace = basename(workspace) !== \"node_modules\" && workspaces.includes(basename(packageRoot));\n\tconst abai = join(workspace, \"abai-stub\");\n\tconst harness = join(workspace, \"abai-embedded-harness\");\n\tif (\n\t\tinWorkspace &&\n\t\treadPackage(abai)?.name === \"@abaigram/abai-stub\" &&\n\t\treadPackage(harness)?.name === \"@abaigram/abai-embedded-harness\"\n\t) {\n\t\tconst built = existsSync(join(abai, \"dist\", \"index.js\")) && existsSync(join(harness, \"dist\", \"index.js\"));\n\t\treturn {\n\t\t\tabai: `file:${abai}`,\n\t\t\tharness: `file:${harness}`,\n\t\t\tdependency: { abai: `file:${abai}`, harness: `file:${harness}`, abaikit: `file:${resolve(packageRoot)}` },\n\t\t\tfromWorkspace: true,\n\t\t\tbuilt,\n\t\t};\n\t}\n\tconst harnessVersion = (require(\"@abaigram/abai-embedded-harness/package.json\") as { version: string }).version;\n\treturn {\n\t\tabai: `@abaigram/abai-stub@^${ABAI_STUB_VERSION}`,\n\t\tharness: `@abaigram/abai-embedded-harness@^${harnessVersion}`,\n\t\tdependency: { abai: `^${ABAI_STUB_VERSION}`, harness: `^${harnessVersion}`, abaikit: `^${ABAIKIT_VERSION}` },\n\t\tfromWorkspace: false,\n\t\tbuilt: true,\n\t};\n}\n\n/** The text with every fenced block blanked, so a heading inside one is not a section. */\nfunction outsideFences(text: string): string {\n\treturn text.replace(/^```[a-z]*\\n[\\s\\S]*?^```$/gm, (block) => block.replace(/[^\\n]/g, \" \"));\n}\n\n/** The guide, filled in and split into its sections. */\nexport function loadGuide(file: string = GUIDE_FILE, packageRoot: string = PACKAGE_ROOT): Guide {\n\tconst packages = packageSpecs(packageRoot);\n\tconst deviations = [...INSTANTIATION_DEVIATIONS, SIDECAR_DEVIATION].map((d) => `- ${d}`).join(\"\\n\");\n\tlet workspaceNote = \"\";\n\tif (packages.fromWorkspace && !packages.built) {\n\t\tworkspaceNote =\n\t\t\t\"\\nThese are workspace checkouts whose `dist/` is not built yet: run `npm run build` in the workspace first, or the packages install with nothing to import.\\n\";\n\t} else if (packages.fromWorkspace) {\n\t\tworkspaceNote = \"\\n(These are the workspace's own checkouts, built; `npm install` links them.)\\n\";\n\t}\n\tconst values: Record<string, string> = {\n\t\tabaigrammar: ABAIGRAMMAR_VERSION,\n\t\tstub: ABAI_STUB_VERSION,\n\t\tabaikit: ABAIKIT_VERSION,\n\t\tabai_spec: packages.abai,\n\t\tharness_spec: packages.harness,\n\t\tworkspace_note: workspaceNote,\n\t\tdeviations,\n\t};\n\tconst text = readFileSync(file, \"utf8\").replace(/\\{\\{([a-z_]+)\\}\\}/g, (whole, key: string) => {\n\t\tconst value = values[key];\n\t\tif (value === undefined) throw new Error(`${file} names an unknown value ${whole}`);\n\t\treturn value;\n\t});\n\t// sections are the level-two headings outside fenced blocks, each ending in its id in parentheses\n\tconst scan = outsideFences(text);\n\tconst sections: GuideSection[] = [];\n\tlet header = text;\n\tlet previous: { id: string; title: string; start: number } | undefined;\n\tfor (const match of scan.matchAll(/^## (.*)$/gm)) {\n\t\tconst titled = /^(.+?) \\(([a-z]+)\\)$/.exec(match[1]);\n\t\tif (!titled) throw new Error(`${file}: the heading \"## ${match[1]}\" ends in no (id)`);\n\t\tconst [, title, id] = titled;\n\t\tif (sections.some((s) => s.id === id) || previous?.id === id) {\n\t\t\tthrow new Error(`${file}: two sections are named (${id})`);\n\t\t}\n\t\tconst start = match.index;\n\t\tif (previous) {\n\t\t\tsections.push({ id: previous.id, title: previous.title, text: text.slice(previous.start, start).trimEnd() });\n\t\t} else header = text.slice(0, start).trimEnd();\n\t\tprevious = { id, title, start };\n\t}\n\tif (previous) sections.push({ id: previous.id, title: previous.title, text: text.slice(previous.start).trimEnd() });\n\treturn {\n\t\tabaigrammar: ABAIGRAMMAR_VERSION,\n\t\tstub: ABAI_STUB_VERSION,\n\t\tabaikit: ABAIKIT_VERSION,\n\t\tpackages,\n\t\theader,\n\t\tsections,\n\t\ttext,\n\t};\n}\n\n/** One section by id; an unknown id names the ids there are. */\nexport function findSection(guide: Guide, id: string): GuideSection {\n\tconst found = guide.sections.find((s) => s.id === id);\n\tif (!found) throw new UsageError(`no section ${id}; the sections are ${guide.sections.map((s) => s.id).join(\", \")}`);\n\treturn found;\n}\n\n/** The whole guide, or one section, as printed. */\nexport function guideText(section?: string): string {\n\tconst guide = loadGuide();\n\tif (section === undefined || section === \"\") return guide.text;\n\treturn `${findSection(guide, section).text}\\n`;\n}\n\n/** The `learnabai` capability: the guide for an agent, one section or all. */\nexport const learnabaiHandler = (params: Record<string, unknown>): { text: string } => {\n\tconst section = typeof params.section === \"string\" ? params.section : undefined;\n\treturn { text: guideText(section) };\n};\n\n/** The skill file Claude Code loads as `/learnabai`: the whole guide, with its source named. */\nexport function skillText(guide: Guide): string {\n\treturn [\n\t\t\"---\",\n\t\t`name: ${SKILL_NAME}`,\n\t\t\"description: How to create an abaigram or retrofit a repository into one with abai (the stub, the standard entry, the conformance levels, the step-by-step retrofit, and what never to do). Use when asked to abaify a repository, add abai to a program, or check an abaigram's conformance.\",\n\t\t\"---\",\n\t\t\"\",\n\t\t`This is the output of \\`abaikit learnabai\\` for abaikit ${guide.abaikit}; run that command for the current text and \\`abaikit learnabai --section <id>\\` for one section.`,\n\t\t\"\",\n\t\tguide.text.trimEnd(),\n\t\t\"\",\n\t].join(\"\\n\");\n}\n\n/** Where `--skill` writes: `<dir>/learnabai/SKILL.md`, the dir defaulting to Claude Code's user skills. */\nexport function skillPath(io: AbaikitIo, dir?: string): string {\n\tif (dir !== undefined) return join(resolve(io.cwd, dir), SKILL_NAME, \"SKILL.md\");\n\tconst home = io.env.HOME;\n\tif (!home) throw new UsageError(\"--skill needs HOME, or --skill-dir <dir>, to know where Claude Code's skills live\");\n\treturn join(home, \".claude\", \"skills\", SKILL_NAME, \"SKILL.md\");\n}\n\nexport async function runLearnabai(parsed: Extract<ParsedArgs, { verb: \"learnabai\" }>, io: AbaikitIo): Promise<number> {\n\tif (parsed.skill) {\n\t\tconst path = skillPath(io, parsed.skillDir);\n\t\tmkdirSync(join(path, \"..\"), { recursive: true });\n\t\twriteFileSync(path, skillText(loadGuide()));\n\t\tio.out(`${path}\\n`);\n\t\treturn 0;\n\t}\n\tif (parsed.json) {\n\t\tconst guide = loadGuide();\n\t\tconst sections: Record<string, string> = {};\n\t\tconst picked = parsed.section === undefined ? guide.sections : [findSection(guide, parsed.section)];\n\t\tfor (const s of picked) sections[s.id] = s.text;\n\t\tconst json = {\n\t\t\tabaigrammar: guide.abaigrammar,\n\t\t\tstub: guide.stub,\n\t\t\tabaikit: guide.abaikit,\n\t\t\tpackages: guide.packages,\n\t\t\tsections,\n\t\t};\n\t\tio.out(`${JSON.stringify(json, null, 2)}\\n`);\n\t\treturn 0;\n\t}\n\tio.out(guideText(parsed.section));\n\treturn 0;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"learnabai.d.ts","sourceRoot":"","sources":["../src/learnabai.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,SAAS,CAAC;AAGrD,eAAO,MAAM,UAAU,QAA6C,CAAC;AACrE,eAAO,MAAM,UAAU,cAAc,CAAC;AAEtC,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC5B,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,kHAAkH;IAClH,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,qFAAqF;IACrF,aAAa,EAAE,OAAO,CAAC;IACvB,4GAA4G;IAC5G,KAAK,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,KAAK;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,QAAQ,EAAE,YAAY,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACb;AAcD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,WAAW,GAAE,MAAqB,GAAG,YAAY,CA6B7E;AAOD,wDAAwD;AACxD,wBAAgB,SAAS,CAAC,IAAI,GAAE,MAAmB,EAAE,WAAW,GAAE,MAAqB,GAAG,KAAK,CAsD9F;AAED,gEAAgE;AAChE,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,GAAG,YAAY,CAIlE;AAED,mDAAmD;AACnD,wBAAgB,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED,8EAA8E;AAC9E,eAAO,MAAM,gBAAgB;;CAG5B,CAAC;AAEF,gGAAgG;AAChG,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAY9C;AAED,2GAA2G;AAC3G,wBAAgB,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAK7D;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC,EAAE,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBrH","sourcesContent":["// abaikit learnabai: the guide an agent reads before it creates or\n// retrofits an abaigram. One text, `abai/learnabai.md`, delivered three\n// ways: printed by the verb (whole, one section, or as JSON), returned by\n// the `learnabai` capability to an agent on the MCP front end, and written\n// as a Claude Code skill by `--skill`. The text names this machine's way\n// to install the packages and the stub's own deviations, filled in here,\n// so it is never out of step with what is installed.\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { basename, join, resolve } from \"node:path\";\nimport {\n\tABAI_STUB_VERSION,\n\tABAIGRAMMAR_VERSION,\n\tINSTANTIATION_DEVIATIONS,\n\tSIDECAR_DEVIATION,\n\tTHREAD_DEVIATION,\n} from \"@abaigram/abai-stub\";\nimport { PACKAGE_ROOT } from \"./abaigram.ts\";\nimport type { ParsedArgs } from \"./bin.ts\";\nimport { type AbaikitIo, UsageError } from \"./io.ts\";\nimport { ABAIKIT_VERSION } from \"./version.ts\";\n\nexport const GUIDE_FILE = join(PACKAGE_ROOT, \"abai\", \"learnabai.md\");\nexport const SKILL_NAME = \"learnabai\";\n\nexport interface GuideSection {\n\tid: string;\n\ttitle: string;\n\ttext: string;\n}\n\nexport interface PackageSpecs {\n\t/** `npm install` arguments: `file:` paths, or `name@^version`. */\n\tabai: string;\n\tharness: string;\n\t/** The same packages as package.json values: `file:` paths, or `^version`; abaikit itself for a devDependency. */\n\tdependency: { abai: string; harness: string; abaikit: string };\n\t/** The specs are `file:` paths into a workspace checkout, not published versions. */\n\tfromWorkspace: boolean;\n\t/** Workspace checkouts only: both packages have their `dist/` built, so `npm install` of them works now. */\n\tbuilt: boolean;\n}\n\nexport interface Guide {\n\tabaigrammar: string;\n\tstub: string;\n\tabaikit: string;\n\t/** How this machine installs the stub and the harness. */\n\tpackages: PackageSpecs;\n\theader: string;\n\tsections: GuideSection[];\n\ttext: string;\n}\n\nconst require = createRequire(import.meta.url);\n\nfunction readPackage(dir: string): { name?: unknown; workspaces?: unknown } | undefined {\n\tconst path = join(dir, \"package.json\");\n\tif (!existsSync(path)) return undefined;\n\ttry {\n\t\treturn JSON.parse(readFileSync(path, \"utf8\")) as { name?: unknown; workspaces?: unknown };\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * The specs `npm install` takes for the two packages an abaigram needs, as\n * this abaikit can reach them. Inside the workspace checkout (the parent\n * is the workspace root whose `workspaces` name abaikit, not some\n * `node_modules` where hoisted siblings happen to sit) they are `file:`\n * paths to the sibling packages; anywhere else, the published versions.\n */\nexport function packageSpecs(packageRoot: string = PACKAGE_ROOT): PackageSpecs {\n\tconst workspace = resolve(packageRoot, \"..\");\n\tconst root = readPackage(workspace);\n\tconst workspaces = Array.isArray(root?.workspaces) ? (root.workspaces as unknown[]) : [];\n\tconst inWorkspace = basename(workspace) !== \"node_modules\" && workspaces.includes(basename(packageRoot));\n\tconst abai = join(workspace, \"abai-stub\");\n\tconst harness = join(workspace, \"abai-embedded-harness\");\n\tif (\n\t\tinWorkspace &&\n\t\treadPackage(abai)?.name === \"@abaigram/abai-stub\" &&\n\t\treadPackage(harness)?.name === \"@abaigram/abai-embedded-harness\"\n\t) {\n\t\tconst built = existsSync(join(abai, \"dist\", \"index.js\")) && existsSync(join(harness, \"dist\", \"index.js\"));\n\t\treturn {\n\t\t\tabai: `file:${abai}`,\n\t\t\tharness: `file:${harness}`,\n\t\t\tdependency: { abai: `file:${abai}`, harness: `file:${harness}`, abaikit: `file:${resolve(packageRoot)}` },\n\t\t\tfromWorkspace: true,\n\t\t\tbuilt,\n\t\t};\n\t}\n\tconst harnessVersion = (require(\"@abaigram/abai-embedded-harness/package.json\") as { version: string }).version;\n\treturn {\n\t\tabai: `@abaigram/abai-stub@^${ABAI_STUB_VERSION}`,\n\t\tharness: `@abaigram/abai-embedded-harness@^${harnessVersion}`,\n\t\tdependency: { abai: `^${ABAI_STUB_VERSION}`, harness: `^${harnessVersion}`, abaikit: `^${ABAIKIT_VERSION}` },\n\t\tfromWorkspace: false,\n\t\tbuilt: true,\n\t};\n}\n\n/** The text with every fenced block blanked, so a heading inside one is not a section. */\nfunction outsideFences(text: string): string {\n\treturn text.replace(/^```[a-z]*\\n[\\s\\S]*?^```$/gm, (block) => block.replace(/[^\\n]/g, \" \"));\n}\n\n/** The guide, filled in and split into its sections. */\nexport function loadGuide(file: string = GUIDE_FILE, packageRoot: string = PACKAGE_ROOT): Guide {\n\tconst packages = packageSpecs(packageRoot);\n\tconst deviations = [...INSTANTIATION_DEVIATIONS, THREAD_DEVIATION, SIDECAR_DEVIATION]\n\t\t.map((d) => `- ${d}`)\n\t\t.join(\"\\n\");\n\tlet workspaceNote = \"\";\n\tif (packages.fromWorkspace && !packages.built) {\n\t\tworkspaceNote =\n\t\t\t\"\\nThese are workspace checkouts whose `dist/` is not built yet: run `npm run build` in the workspace first, or the packages install with nothing to import.\\n\";\n\t} else if (packages.fromWorkspace) {\n\t\tworkspaceNote = \"\\n(These are the workspace's own checkouts, built; `npm install` links them.)\\n\";\n\t}\n\tconst values: Record<string, string> = {\n\t\tabaigrammar: ABAIGRAMMAR_VERSION,\n\t\tstub: ABAI_STUB_VERSION,\n\t\tabaikit: ABAIKIT_VERSION,\n\t\tabai_spec: packages.abai,\n\t\tharness_spec: packages.harness,\n\t\tworkspace_note: workspaceNote,\n\t\tdeviations,\n\t};\n\tconst text = readFileSync(file, \"utf8\").replace(/\\{\\{([a-z_]+)\\}\\}/g, (whole, key: string) => {\n\t\tconst value = values[key];\n\t\tif (value === undefined) throw new Error(`${file} names an unknown value ${whole}`);\n\t\treturn value;\n\t});\n\t// sections are the level-two headings outside fenced blocks, each ending in its id in parentheses\n\tconst scan = outsideFences(text);\n\tconst sections: GuideSection[] = [];\n\tlet header = text;\n\tlet previous: { id: string; title: string; start: number } | undefined;\n\tfor (const match of scan.matchAll(/^## (.*)$/gm)) {\n\t\tconst titled = /^(.+?) \\(([a-z]+)\\)$/.exec(match[1]);\n\t\tif (!titled) throw new Error(`${file}: the heading \"## ${match[1]}\" ends in no (id)`);\n\t\tconst [, title, id] = titled;\n\t\tif (sections.some((s) => s.id === id) || previous?.id === id) {\n\t\t\tthrow new Error(`${file}: two sections are named (${id})`);\n\t\t}\n\t\tconst start = match.index;\n\t\tif (previous) {\n\t\t\tsections.push({ id: previous.id, title: previous.title, text: text.slice(previous.start, start).trimEnd() });\n\t\t} else header = text.slice(0, start).trimEnd();\n\t\tprevious = { id, title, start };\n\t}\n\tif (previous) sections.push({ id: previous.id, title: previous.title, text: text.slice(previous.start).trimEnd() });\n\treturn {\n\t\tabaigrammar: ABAIGRAMMAR_VERSION,\n\t\tstub: ABAI_STUB_VERSION,\n\t\tabaikit: ABAIKIT_VERSION,\n\t\tpackages,\n\t\theader,\n\t\tsections,\n\t\ttext,\n\t};\n}\n\n/** One section by id; an unknown id names the ids there are. */\nexport function findSection(guide: Guide, id: string): GuideSection {\n\tconst found = guide.sections.find((s) => s.id === id);\n\tif (!found) throw new UsageError(`no section ${id}; the sections are ${guide.sections.map((s) => s.id).join(\", \")}`);\n\treturn found;\n}\n\n/** The whole guide, or one section, as printed. */\nexport function guideText(section?: string): string {\n\tconst guide = loadGuide();\n\tif (section === undefined || section === \"\") return guide.text;\n\treturn `${findSection(guide, section).text}\\n`;\n}\n\n/** The `learnabai` capability: the guide for an agent, one section or all. */\nexport const learnabaiHandler = (params: Record<string, unknown>): { text: string } => {\n\tconst section = typeof params.section === \"string\" ? params.section : undefined;\n\treturn { text: guideText(section) };\n};\n\n/** The skill file Claude Code loads as `/learnabai`: the whole guide, with its source named. */\nexport function skillText(guide: Guide): string {\n\treturn [\n\t\t\"---\",\n\t\t`name: ${SKILL_NAME}`,\n\t\t\"description: How to create an abaigram or retrofit a repository into one with abai (the stub, the standard entry, the conformance levels, the step-by-step retrofit, and what never to do). Use when asked to abaify a repository, add abai to a program, or check an abaigram's conformance.\",\n\t\t\"---\",\n\t\t\"\",\n\t\t`This is the output of \\`abaikit learnabai\\` for abaikit ${guide.abaikit}; run that command for the current text and \\`abaikit learnabai --section <id>\\` for one section.`,\n\t\t\"\",\n\t\tguide.text.trimEnd(),\n\t\t\"\",\n\t].join(\"\\n\");\n}\n\n/** Where `--skill` writes: `<dir>/learnabai/SKILL.md`, the dir defaulting to Claude Code's user skills. */\nexport function skillPath(io: AbaikitIo, dir?: string): string {\n\tif (dir !== undefined) return join(resolve(io.cwd, dir), SKILL_NAME, \"SKILL.md\");\n\tconst home = io.env.HOME;\n\tif (!home) throw new UsageError(\"--skill needs HOME, or --skill-dir <dir>, to know where Claude Code's skills live\");\n\treturn join(home, \".claude\", \"skills\", SKILL_NAME, \"SKILL.md\");\n}\n\nexport async function runLearnabai(parsed: Extract<ParsedArgs, { verb: \"learnabai\" }>, io: AbaikitIo): Promise<number> {\n\tif (parsed.skill) {\n\t\tconst path = skillPath(io, parsed.skillDir);\n\t\tmkdirSync(join(path, \"..\"), { recursive: true });\n\t\twriteFileSync(path, skillText(loadGuide()));\n\t\tio.out(`${path}\\n`);\n\t\treturn 0;\n\t}\n\tif (parsed.json) {\n\t\tconst guide = loadGuide();\n\t\tconst sections: Record<string, string> = {};\n\t\tconst picked = parsed.section === undefined ? guide.sections : [findSection(guide, parsed.section)];\n\t\tfor (const s of picked) sections[s.id] = s.text;\n\t\tconst json = {\n\t\t\tabaigrammar: guide.abaigrammar,\n\t\t\tstub: guide.stub,\n\t\t\tabaikit: guide.abaikit,\n\t\t\tpackages: guide.packages,\n\t\t\tsections,\n\t\t};\n\t\tio.out(`${JSON.stringify(json, null, 2)}\\n`);\n\t\treturn 0;\n\t}\n\tio.out(guideText(parsed.section));\n\treturn 0;\n}\n"]}
|
package/dist/learnabai.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
9
9
|
import { createRequire } from "node:module";
|
|
10
10
|
import { basename, join, resolve } from "node:path";
|
|
11
|
-
import { ABAI_STUB_VERSION, ABAIGRAMMAR_VERSION, INSTANTIATION_DEVIATIONS, SIDECAR_DEVIATION, } from "@abaigram/abai-stub";
|
|
11
|
+
import { ABAI_STUB_VERSION, ABAIGRAMMAR_VERSION, INSTANTIATION_DEVIATIONS, SIDECAR_DEVIATION, THREAD_DEVIATION, } from "@abaigram/abai-stub";
|
|
12
12
|
import { PACKAGE_ROOT } from "./abaigram.js";
|
|
13
13
|
import { UsageError } from "./io.js";
|
|
14
14
|
import { ABAIKIT_VERSION } from "./version.js";
|
|
@@ -68,7 +68,9 @@ function outsideFences(text) {
|
|
|
68
68
|
/** The guide, filled in and split into its sections. */
|
|
69
69
|
export function loadGuide(file = GUIDE_FILE, packageRoot = PACKAGE_ROOT) {
|
|
70
70
|
const packages = packageSpecs(packageRoot);
|
|
71
|
-
const deviations = [...INSTANTIATION_DEVIATIONS, SIDECAR_DEVIATION]
|
|
71
|
+
const deviations = [...INSTANTIATION_DEVIATIONS, THREAD_DEVIATION, SIDECAR_DEVIATION]
|
|
72
|
+
.map((d) => `- ${d}`)
|
|
73
|
+
.join("\n");
|
|
72
74
|
let workspaceNote = "";
|
|
73
75
|
if (packages.fromWorkspace && !packages.built) {
|
|
74
76
|
workspaceNote =
|