Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 50 additions & 4 deletions architecture.md

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions packages/cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ const syntaxConfig = object({
...field(z.array(z.string()), field.default(["components", "."]), field.array()),
},
json: {
description: "write the catalog as version-2 JSON instead of markdown",
description: "write the symbols as version-2 JSON instead of markdown",
...field(z.boolean(), field.default(false)),
},
});
Expand Down Expand Up @@ -2637,7 +2637,7 @@ function* dispatch(
case "syntax": {
// One inspection per invocation, then one complete document. A failure
// writes nothing to stdout: a healthy subset printed as though it were
// the catalog would read as complete.
// the whole set of symbols would read as complete.
let rendered: string;
try {
const named = command.config.component;
Expand All @@ -2661,13 +2661,13 @@ function* dispatch(
yield* exit(1);
break;
}
// Only the catalog goes through delivery today, because it is the one
// output this command writes in a single call and the only one already
// Only this command's rendering goes through delivery today, because it
// is the one output written in a single call and the only one already
// past a pipe buffer.
const written = yield* deliverWhole(rendered, process.stdout);
if (!written.ok) {
console.error(
`xmd syntax: stdout did not accept the whole catalog: ${describeError(written.error)}`,
`xmd syntax: stdout did not accept the whole output: ${describeError(written.error)}`,
);
yield* exit(1);
}
Expand Down Expand Up @@ -2850,7 +2850,7 @@ export function* runXmd(
const provisional = xmd.parse({ args: helpRequest.args });
const selected = provisional.ok ? provisional.value.config : undefined;
// The two commands a `--timeout` bounds. `xmd plan`'s deadline encloses
// something different from a run's — the catalog, the assistant session,
// something different from a run's — the symbols, the assistant session,
// every repair, the human review, provider teardown, final validation and the
// artifact — and covers no later program, because it starts none.
const planning = selected !== undefined && !selected.help && selected.name === "plan";
Expand Down
12 changes: 6 additions & 6 deletions packages/cli/src/plan-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
*
* `<Syntax />` is not among them. What a document may write here is a public
* question with a public answer, and canonical core owns both — so `Plan.md`
* writes the same component any other document writes, and the catalog the Agent
* writes the same component any other document writes, and the symbols the Agent
* is shown is the one an operator can print.
*/

Expand Down Expand Up @@ -121,8 +121,8 @@
*
* The declarations are read when the question is asked rather than when this is
* built, because the `<Plan>` declaration has to be able to describe itself: the
* profile a Plan will run in contains `<Plan>`, and the catalog the agent was
* shown says so.
* profile a Plan will run in contains `<Plan>`, and the symbols the agent was
* shown say so.
*/
export function structuralValidation(
includes: readonly string[],
Expand Down Expand Up @@ -253,7 +253,7 @@
additionalProperties: false,
};

const OPTIONAL_SESSION = {

Check warning on line 256 in packages/cli/src/plan-component.ts

View workflow job for this annotation

GitHub Actions / lint

eslint(no-unused-vars)

Variable 'OPTIONAL_SESSION' is declared but never used. Unused variables should start with a '_'.
type: "object",
properties: { session: { type: "string", minLength: 1 } },
additionalProperties: false,
Expand Down Expand Up @@ -327,7 +327,7 @@
): Operation<DeclaredMarkdownComponent> {
const source = yield* readPackagedDocument(PLAN_DOCUMENT);
// The admission validates against the profile a Plan will run in, and that
// profile now contains `<Plan>` — the catalog the agent was shown says so. So
// profile now contains `<Plan>` — the symbols the agent was shown say so. So
// the declaration has to be able to describe itself, which is why it is
// assigned back rather than rebuilt: a second copy of these bytes would be a
// second Component identity.
Expand Down Expand Up @@ -368,7 +368,7 @@
* Inspection and validation answer about what a document may write. They mint no
* execution, so there is no claimant to build a private capability from and no
* frame to install — and none of that is describable anyway: a private name
* is not syntax a document may write, so a catalog listing one would describe an
* is not syntax a document may write, so symbols listing one would describe an
* environment that does not exist.
*
* What they do report is the identity: the same name, the same origin, the same
Expand Down Expand Up @@ -437,7 +437,7 @@
*
* The vocabulary the Agent is shown is not here. `<Syntax />` is a public
* component canonical core owns, it retains its own observation, and `Plan.md`
* binds it directly — so the catalog and the question are two records that can
* binds it directly — so the symbols and the question are two records that can
* be read and reconciled independently rather than one that has to be read
* whole.
*
Expand Down
40 changes: 20 additions & 20 deletions packages/cli/tests/syntax-cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* about assembly, not about argv. The grammar, failure and delivery rows shell
* out, so exit status, stdout and stderr are the ones an operator sees.
*
* Catalog behavior itself is Tier SY's; nothing here re-proves selection.
* Symbol behavior itself is Tier SY's; nothing here re-proves selection.
*/

import { describe, it } from "@executablemd/test-support/bdd";
Expand Down Expand Up @@ -59,15 +59,15 @@ const WORKSPACE: Record<string, string> = {
"second/Only.md": "only in the second include\n",
};

function parseCatalog(text: string): SyntaxSymbols {
function parseSymbols(text: string): SyntaxSymbols {
const parsed: unknown = JSON.parse(text);
if (typeof parsed !== "object" || parsed === null) {
throw new Error("the catalog is not an object");
throw new Error("the symbols are not an object");
}
const version = Reflect.get(parsed, "version");
const categories = Reflect.get(parsed, "categories");
if (version !== 2 || !Array.isArray(categories) || categories.length !== 3) {
throw new Error("the catalog is not the version-2 shape");
throw new Error("the symbols are not the version-2 shape");
}
return { version, categories: readCategories(categories) };
}
Expand All @@ -79,7 +79,7 @@ function readCategories(categories: unknown[]): SyntaxSymbols["categories"] {
builtIn?.kind !== "built-in" ||
userProvided?.kind !== "user-provided"
) {
throw new Error("the catalog categories are not the fixed tuple");
throw new Error("the symbol categories are not the fixed tuple");
}
return [
{ kind: "structural", entries: structural.entries },
Expand All @@ -91,11 +91,11 @@ function readCategories(categories: unknown[]): SyntaxSymbols["categories"] {
// deno-lint-ignore no-explicit-any
function readCategory(category: unknown): { kind: unknown; entries: any[] } {
if (typeof category !== "object" || category === null) {
throw new Error("a catalog category is not an object");
throw new Error("a symbol category is not an object");
}
const entries = Reflect.get(category, "entries");
if (!Array.isArray(entries)) {
throw new Error("a catalog category has no entries");
throw new Error("a symbol category has no entries");
}
return { kind: Reflect.get(category, "kind"), entries };
}
Expand All @@ -105,7 +105,7 @@ function names(entries: readonly { name: string }[]): string[] {
}

/** One built-in entry carrying `props`, for a renderer row that supplies its own. */
function catalogWith(props: PropsSchema): SyntaxSymbols {
function symbolsWith(props: PropsSchema): SyntaxSymbols {
return {
version: 2,
categories: [
Expand Down Expand Up @@ -187,7 +187,7 @@ describe("Tier SX — the run profile the command describes", () => {

const [entry] = everywhere;
if (entry === undefined || entry.kind !== "component" || entry.inspectability !== "complete") {
throw new Error("the catalog describes <Syntax> without a contract");
throw new Error("the symbols describe <Syntax> without a contract");
}
expect(entry.origin).toEqual({ kind: "protected", origin: "@executablemd/core" });
expect(entry.sourceKind).toBe("protected");
Expand Down Expand Up @@ -346,7 +346,7 @@ describe("Tier SX — the renderers take a value", () => {

it("SX4b: escapes a table cell that would otherwise shift the columns", function* () {
const markdown = renderSyntaxMarkdown(
catalogWith({
symbolsWith({
type: "object",
properties: {
"left|right": { type: "string", description: "a | in the description, and\na break" },
Expand All @@ -368,7 +368,7 @@ describe("Tier SX — the renderers take a value", () => {
}
});

it("SX5: renders the same bytes twice from the same catalog", function* () {
it("SX5: renders the same bytes twice from the same symbols", function* () {
const catalog = yield* syntaxSymbols([]);

expect(renderSyntaxMarkdown(catalog)).toBe(renderSyntaxMarkdown(catalog));
Expand Down Expand Up @@ -396,7 +396,7 @@ describe("Tier SX — the command line", { sanitizeOps: false, sanitizeResources
["syntax", "--json", "--include", "first", "--include", "second"],
{ cwd },
).expect();
const forwardCatalog = parseCatalog(forward.stdout);
const forwardCatalog = parseSymbols(forward.stdout);
expect(names(forwardCatalog.categories[2].entries)).toEqual(["Only", "Shared"]);
const shared = forwardCatalog.categories[2].entries.find((one) => one.name === "Shared");
expect(shared?.origin).toEqual({ kind: "repository", path: "first/Shared.md" });
Expand All @@ -408,7 +408,7 @@ describe("Tier SX — the command line", { sanitizeOps: false, sanitizeResources
["syntax", "--json", "--include", "second", "--include", "first"],
{ cwd },
).expect();
const reversedShared = parseCatalog(reversed.stdout).categories[2].entries.find(
const reversedShared = parseSymbols(reversed.stdout).categories[2].entries.find(
(one) => one.name === "Shared",
);
expect(reversedShared?.origin).toEqual({ kind: "repository", path: "second/Shared.md" });
Expand All @@ -418,7 +418,7 @@ describe("Tier SX — the command line", { sanitizeOps: false, sanitizeResources
it("SX8: falls back to components and . when no include is written", function* () {
yield* useWorkspace(WORKSPACE, function* (cwd) {
const { stdout } = yield* runCli(["syntax", "--json"], { cwd }).expect();
const catalog = parseCatalog(stdout);
const catalog = parseSymbols(stdout);

expect(names(catalog.categories[2].entries)).toContain("Default");
});
Expand Down Expand Up @@ -457,7 +457,7 @@ describe("Tier SX — the command line", { sanitizeOps: false, sanitizeResources
);
});

it("SX9: reports an unusable include on stderr, exits 1, and prints no catalog", function* () {
it("SX9: reports an unusable include on stderr, exits 1, and prints no symbols", function* () {
yield* useWorkspace({ components: "not a directory\n" }, function* (cwd) {
const { code, stdout, stderr } = yield* runCli(["syntax", "--include", "components"], {
cwd,
Expand Down Expand Up @@ -527,7 +527,7 @@ describe("Tier SX — the command line", { sanitizeOps: false, sanitizeResources
expect(markdown.stdout).toContain("from the first include.");

const json = yield* runCli(["syntax", "--json", "--include", "first"], { cwd }).expect();
const catalog = parseCatalog(json.stdout);
const catalog = parseSymbols(json.stdout);
expect(catalog.version).toBe(2);
expect(names(catalog.categories[2].entries)).toEqual(["Shared"]);
});
Expand Down Expand Up @@ -558,13 +558,13 @@ describe("Tier SX — the command line", { sanitizeOps: false, sanitizeResources

expect(stderr).toBe("");
expect(code).toBe(0);
const catalog = parseCatalog(stdout);
const catalog = parseSymbols(stdout);
expect(names(catalog.categories[2].entries)).toEqual(["Widget"]);
},
);
});

it("SX11: the catalog is inspection, and plan is the command that writes with it", function* () {
it("SX11: the symbols are inspection, and plan is the command that writes with them", function* () {
const { stdout } = yield* runCli(["--help"]).expect();

expect(stdout).toContain("syntax");
Expand Down Expand Up @@ -608,7 +608,7 @@ describe(
const { redirected, piped } = yield* deliveries(["--json"], cwd);

expect(piped).toBe(redirected);
const catalog = parseCatalog(piped);
const catalog = parseSymbols(piped);
expect(catalog.version).toBe(2);
expect(names(catalog.categories[2].entries)).toContain("ZBeyondTheBuffer");
expect(piped.lastIndexOf(`"ZBeyondTheBuffer"`)).toBeGreaterThan(PIPE_BUFFER);
Expand All @@ -626,7 +626,7 @@ describe(

expect(stdout.length).toBe(100);
expect(stderr).toContain("xmd-exit=1");
expect(stderr).toContain("stdout did not accept the whole catalog");
expect(stderr).toContain("stdout did not accept the whole output");
// The broken pipe is reported, not raised: an unhandled write failure
// ends the process with one of these instead.
expect(stderr).not.toContain("Unhandled 'error' event");
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/protected.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* what is invoked.
*
* Protection is not authority to do anything. A protected implementation is
* handed the lexical observation for its site and nothing else: no component
* handed the lexical syntax reference for its site and nothing else: no component
* definitions, no import witness, no invocation capability, no policy table, no
* provider and no registration handle.
*
Expand Down
Loading
Loading