Skip to content

✨ Evaluate generated XMD text with constrained authority (#713) - #756

Open
taras wants to merge 7 commits into
mainfrom
agent/issue-713-evaluate-program
Open

✨ Evaluate generated XMD text with constrained authority (#713)#756
taras wants to merge 7 commits into
mainfrom
agent/issue-713-evaluate-program

Conversation

@taras

@taras taras commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Why

Issue #713 makes generated XMD fragment text explicitly evaluable in ordinary and workflow documents while keeping the authority restriction trustworthy.

The current PR revision is not mergeable. It implements a superseded complete-program model on a pre-#759 base. Its replaceable <Evaluate> name would also let a repository or middleware implementation ignore allow and run with wider site authority.

Architecture correction required

Restart the correction from a clean worktree based on the latest main containing merged PR #759. Do not use an obsolete exact commit from this branch's complete-program implementation as the base, and do not preserve code merely because it exists on the old branch.

<Plan> produces inert XMD fragment text. It does not execute that text and does not return a special Program value.

<Evaluate> evaluates the text through two disjoint forms:

<Evaluate text={program} allow={["read"]} />
<Evaluate allow={["read"]}>
  <Plan>Ask for the user's age.</Plan>
</Evaluate>

The paired form privately renders its content to obtain the exact fragment. Validate input shape and allow before producer work. allow applies to evaluation of the resulting text, not to its producer. Omitted allow means read.

The result remains { observations, output }; as captures it, and otherwise it is discarded. Evaluation emits no fragment output into the enclosing document. Fragments introduce no root frontmatter, root props, root returns, or independent <Output> selection.

Approved description:

Evaluate program text. <Evaluate text={program} allow={["read"]} /> runs it.

Protected ownership

<Evaluate> is a public, engine-owned member of #758's canonical protected component tier. Canonical core owns its name, input grammar, admission, allow interpretation, result shape, and invocation identity.

A repository component, workflow bundle member, declared Markdown component, ordinary or reserved registration, Component.importComponent middleware answer, document context value, or implementation from another loaded package copy cannot answer for or replace it. Middleware may observe, delegate, or refuse the protected import, but cannot provide, alter, redirect, retain for reuse, or invoke a replacement.

Protection decides which policy interpreter runs. It grants no authority. Each trusted host supplies one private fragment-evaluation profile to canonical execution before document code. The profile states the maximum available authority through exact identities, forms, request limits, retained-root access where applicable, and provider operations. allow separately narrows that profile. A missing or duplicate profile refuses before producer or fragment work.

Structural constructs remain protected through structural dispatch, not the protected component table. Ordinary defaults including <File>, <Fetch>, and <Elicit> remain replaceable at ordinary authored sites. Generated evaluation runs only the exact identity and form the trusted profile admitted and the durable record retained.

Authority and syntax

For both standard host profiles, read selects exactly self-closing <File>. write selects exactly paired <File>, paired <Dir>, and self-closing <File.Delete> and does not imply read; allow={["read", "write"]} selects both. Ordinary runs use their Files provider, while workflow runs use the retained Workspace's transaction-bound Files provider. Bounded Fetch and any further entry exist only as exact trusted-host extensions retained in policy.

After form, allow, and profile validation, Evaluate derives the selected vocabulary and installs it through merged #759's engine-owned lexical syntax reference while rendering paired content and evaluating the resulting fragment. Public <Syntax> and a directly nested Plan read it before admission; preflight enforces the same table before effects. Plan has no private Syntax implementation. A deferred Plan sees its own authoring site, and later Evaluate preflights its exact text before effects. Reading symbols grants no authority.

Durability and compatibility

Use one generalized, versioned generated_xmd protocol shared by ordinary and workflow hosts. Keep old untagged #369 records readable as version 1 and write the closed successor as version 2. Retain exact text, policy, trusted limits, admitted identities, occurrence identity, and the committed result and effects required for replay. Hostile or stale records refuse before fragment effects.

text is canonical. Preserve released workflow source only as the silent deprecated alias in the workflow profile; ordinary evaluation rejects it. Use this approved Syntax documentation:

Deprecated compatibility spelling for workflow documents. Use text in new documents.

Remove the unmerged program spelling.

Retain and adapt

  • exact input retention and stale-input refusal;
  • hostile durable-record parsing;
  • replay without repeating Plan or completed effects;
  • evaluation-site authority rather than producer-private authority;
  • declared-component private-closure isolation;
  • occurrence identity for repeated evaluations;
  • reconciliation of admissible middleware-provided components using the actual answer's stable namespaced provider origin, key, and revision;
  • evaluation-scope ownership of provider registrations and occurrence-settled competing claims;
  • structured cancellation and complete teardown.

Remove

  • Program and complete-program public types;
  • the program prop;
  • root parsing and expansion, root props, modes, returns, and independent Output behavior;
  • the parallel evaluate_program journal abstraction;
  • the workflow host's declared or replaceable <Evaluate> implementation.

Review guide

Start with the protected-name selection and host-profile boundary. Then review the two input forms, generated-XMD admission, Syntax narrowing, durable protocol, middleware identity, and cancellation teardown.

The next feedback commit must freeze and pass the complete acceptance matrix in amended #713. In addition to the fragment, replay, compatibility, and lifecycle rows already required, evidence must discriminate:

  • repository, workflow bundle, declaration, ordinary and reserved registration, middleware, context, and cross-copy replacement attempts;
  • honest protected-import delegation and deliberate middleware refusal;
  • a replacement that tries to ignore allow={["read"]} and write, proving the replacement never runs and no provider or file effect occurs;
  • the negative control that protection grants no authority;
  • structural dispatch remaining separate and File, Fetch, and Elicit remaining replaceable at ordinary authored sites;
  • protected Evaluate appearing in source, npm, and compiled symbols with the approved description;
  • one private host profile per execution, with missing, duplicate, and document-forgery refusals before producer or fragment work.

Run the smallest explicit cross-boundary command covering the protected resolver, core fragment evaluator, ordinary CLI integration, workflow integration, Plan syntax, continuation, middleware substitution, and cancellation. Commit promptly when it passes using the configured signing identity tarasm@gmail.com, then return the exact SHA and every focused command with its exact result. Do not wait for CI.

Scope

Included

  • Public protected <Evaluate> for constrained XMD fragment text.
  • Shared ordinary/workflow evaluation semantics and versioned replay.
  • The released workflow source compatibility alias.

Intentionally unchanged

  • <Plan> only produces text.
  • <Syntax> remains the public protected symbols component delivered by Add <Syntax> to list available XMD symbols (#758) #759.
  • Structural constructs use structural dispatch.
  • Ordinary component defaults remain replaceable.
  • There is no <Program>, <Source>, or <Execute> component.

Closes #713.

`<Plan>` produces a program and never runs it. `<Evaluate>` is now the
composition site where one runs: paired content renders a producer into a
private program buffer, `program={value}` supplies complete-program source
directly, and both admit a complete root and evaluate it in the current
execution — its lifecycle, journal, cancellation scope, providers, working
directory and the authority in force where the element was written.

The forms are disjoint and ambiguity refuses before program content is produced
and before any program effect runs. The root deciding what happens is the
program: its frontmatter, props schema, `returns` and `<Output>` selection all
apply, root props are the explicit `props` object rather than the caller's, and
a value root requires `as`.

Complete programs record their own `evaluate_program` durable event; the
restricted `generated_xmd` admission #369 delivered is unchanged and
complete-program support is not reachable through `source` or `allow`. A
partial continuation expands the retained source and restores completed nested
effects; a changed program at the same occurrence is stale input and neither
source runs.

Canonical execution answers the new `Component.expandProgram()` from the frame
it already holds, which is what makes site authority a fact about the frame
rather than something a prop, binding or middleware return value could supply —
and what keeps a producer's private closure from crossing into the program.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 6 redundant comments. Inline suggestions to remove them below.

"Component.expandProgram() has no provider: not inside a function component invocation.",
);
},
// deno-lint-ignore require-yield

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// deno-lint-ignore require-yield

yield* provideEnv(programEnvironment(site.callerValues, program.props));
if (program.returns !== undefined) {
// A value root has no rendered result to fall back on, so an undecided
// error is the evaluation's failure rather than text in the document.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// error is the evaluation's failure rather than text in the document.

}
const mode = definition.returns === undefined ? "text" : "value";
// Before the props are looked at, because a value root with nowhere to put
// its result is refused whatever its props would have validated to.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// its result is refused whatever its props would have validated to.

// Which grammar this element is written in, decided from the props alone.
// Neither half of it reads the authored form, so both are settled before
// the durable name is claimed: a combination this host does not have is not
// a fragment or a program being refused.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// a fragment or a program being refused.


// After the claim, so the shape read here is the one the claim proved this
// element was written in. A borrowed invocation reports somebody else's
// element, and refusing it is the claimant's answer rather than this one.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// element, and refusing it is the claimant's answer rather than this one.

origin: ORIGIN,
// The run profile's sentence plus the one form only this profile has.
// Stated here rather than in core because a catalog must not advertise a
// prop the profile it describes would refuse.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// prop the profile it describes would refuse.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

PR #756: ✨ Make <Evaluate> evaluate complete XMD programs (#713)

23 files, +4782 / -223

Scope

🔴 PR has 5005 lines changed. Split into focused PRs.

🟡 5005 lines changed. PRs under 400 receive more thorough review.

🟡 23 files changed. Are all changes related?

🟡 Changes span 8 directories.

Structural

Oxlint structural signals:

  • no-unused-vars ×10: packages/cli/src/cli.ts, packages/core/src/execute.ts, packages/core/src/expand.ts
  • no-unnecessary-type-assertion ×8: packages/core/src/program-identity.ts, packages/core/src/execute.ts, packages/core/src/expand.ts
  • no-empty-function ×1: packages/cli/src/cli.ts

Slop

  • packages/core/src/component-api.ts:287 (removed)
  • packages/core/src/expand.ts:4192 (removed)
  • packages/core/src/component-api.ts:304// deno-lint-ignore require-yield
  • packages/core/src/component-api.ts:312// deno-lint-ignore require-yield
  • packages/core/src/expand.ts:2427// deno-lint-ignore require-yield
  • packages/core/src/execute.ts:488// reads nothing and a replay reconstructs it without resolving a name.
  • packages/core/src/execute.ts:498// and a replay reconstructs the component without resolving a name.
  • packages/core/src/execute.ts:505// is exactly what it always was.
  • packages/core/src/execute.ts:693// type-checked on the way in.
  • packages/core/src/execute.ts:2501// describes the definition this import actually settled on.
  • packages/core/src/expand.ts:2493// answer describes itself.

Oxlint slop signals:

  • no-inferrable-types ×3: packages/core/src/components/Evaluate.ts, packages/core/src/expand.ts
  • no-console ×3: packages/cli/src/cli.ts

Static Analysis

Oxlint: 63 diagnostics across 6 files (16 rules)
Density: 0.013 violations/added-line

no-unsafe-type-assertion (14): packages/core/src/program-identity.ts, packages/core/src/program-evaluation.ts, packages/core/src/execute.ts (+2)
no-unused-vars (10): packages/cli/src/cli.ts, packages/core/src/execute.ts, packages/core/src/expand.ts
no-unnecessary-type-assertion (8): packages/core/src/program-identity.ts, packages/core/src/execute.ts, packages/core/src/expand.ts
no-base-to-string (5): packages/core/src/components/Evaluate.ts, packages/core/src/expand.ts
unbound-method (5): packages/core/src/execute.ts, packages/core/src/expand.ts, packages/cli/src/cli.ts
no-shadow (4): packages/core/src/execute.ts, packages/core/src/expand.ts
no-inferrable-types (3): packages/core/src/components/Evaluate.ts, packages/core/src/expand.ts
no-console (3): packages/cli/src/cli.ts
consistent-return (3): packages/core/src/execute.ts, packages/cli/src/cli.ts
no-floating-promises (2): packages/core/src/execute.ts, packages/cli/src/cli.ts
no-empty-function (1): packages/cli/src/cli.ts
no-unmodified-loop-condition (1): packages/cli/src/cli.ts
no-array-sort (1): packages/core/src/execute.ts
restrict-template-expressions (1): packages/core/src/expand.ts
no-duplicate-type-constituents (1): packages/core/src/execute.ts
no-implied-eval (1): packages/core/src/expand.ts

Correctness

FILE: packages/core/src/execute.ts, packages/core/src/expand.ts
PATTERN: no-unused-vars + no-unnecessary-type-assertion + no-base-to-string
CONCERN: Clusters of unused-vars and unnecessary-type-assertions in same files suggest unreviewed generated code
QUESTION: Are these violations from generated code or intentional implementation details?

FILE: packages/core/src/program-identity.ts
PATTERN: speculative abstraction
CONCERN: ProgramIdentity, ProgramSettlement, ProgramBody/ProgramOutcome may lack 3+ consumers
QUESTION: Are these abstractions used by >2 components as justified in the PR?

FILE: packages/core/src/execute.ts
PATTERN: no-unnecessary-type-assertion
CONCERN: Type assertions may hide missing props in program evaluation logic
QUESTION: Are these assertions required for type safety or masking incomplete data?

FILE: packages/core/src/expand.ts
PATTERN: no-base-to-string
CONCERN: Implicit string coercion in program expansion logic
QUESTION: Is this intentional or masking undefined values in resolution?

FILE: packages/core/src/program-evaluation.ts
PATTERN: no-unsafe-type-assertion
CONCERN: Unsafe type assertions in program admission logic
QUESTION: Are these assertions necessary for runtime validation or masking type gaps?

The `evaluate_program` record is hostile data and was read as though it were
not. It is now two closed shapes — admitted and refused — with every nested
record closed too, so a missing, additional or misspelled member at any depth
is a record this evaluation did not write.

Shape is not enough, because every member of the record is a claim about
another one. Before anything expands, the retained source must hash to the
retained digest, reparsing it must produce the retained root mode and a valid
body structure, the retained elements must be the ones that source writes in
that order and those forms, and the supplied props must validate to the
retained validated props. A record failing any of them is refused as unreadable
and neither the retained nor the current program performs an effect.

The admission also retains what each name the program writes resolved to at
this site, which restores the current-site compatibility contract: a
continuation whose site now answers one of those names with a different
identity, or admits it in a different form, refuses before either
implementation runs, while an unchanged site resumes.

Resolution stays behind canonical execution. The execution builds a resolver,
carries it on the expansion authority, and settles the comparison itself before
the first program effect. `Component.resolveProgramSite()` lets the admission
retain what the site answered; nothing rests on that answer, because the
canonical comparison is what decides — so short-circuiting it refuses the
evaluation rather than widening it. `ExpansionAuthority` is still reachable from
no component, and no prop, binding, middleware result or public context state
supplies authority.
#713)

The retained identity came from an independent `selectComponent()` call, which
is not what runs. `Component.importComponent` middleware may answer without
delegating or replace what came back, so a second resolution described a
definition nobody invokes: two different middleware answers retained one
identity, compared equal, and a continuation ran the other one.

Resolution now goes through the ordinary chain and takes the identity from the
final answer. A canonical tier keeps its canonical identity. An answer an
identified provider supplied keeps that provider's own — a stable origin, its
key for the name, and a revision that changes with the implementation — stated
at the installation boundary through `useImportProvider()`, where canonical
execution mints a claimant for that execution and binds the terms to the exact
answer in execution-private state. Never on the definition, which an answer can
copy; never through a replaceable Context answer.

An answer nobody identified still works for ordinary expansion and cannot back
a durable grant: a continuation would have nothing to compare. Two live
providers under one origin refuse, and so does a second claim on one answer.

Identities are closed tagged records now, so a missing, empty, additional or
mis-tagged member is unreadable like every other corrupted member.

The comparison and the invocation are one decision: canonical execution keeps
its own copy of each witnessed answer and authorizes the program's imports
against it, so an answer that changed between the check and the use is refused
where it would be invoked rather than silently preferred.
…ts import (#713)

Three corrections.

**Closed authority was overwritten.** The program authority replaced the site's
`imports` with one that forgot its tiers, and resolution asked the chain without
applying them, so an identified provider could replace a bundled or declared
component and be admitted as its identity. Resolution now applies the site's
closed authority exactly as ordinary expansion does, and the program's expansion
keeps the tiers it already had. A provider-supplied answer is witnessed rather
than issued, so it authorizes nothing for a name a tier closed — the guarantee
that sharing one witness table had quietly broken.

**Resolution now journals nothing.** The selection half of an import and the
definition it produces are separated from the durable operation, so a
resolution-only path settles the site without recording anything.
`evaluate_program` commits before the program's own ordinary import.

**Expansion no longer asks again.** The answers that passed reconciliation reach
expansion as settled answers: an element whose name is among them does not enter
`Component.importComponent` at all. The chain is entered twice for one
evaluation, never a third time. The authored element still records one ordinary
import after the admission, restored from the already-authorized answer with
identity-domain and form selection intact.

Provider identity is read exactly once at registration and closed over as copied
primitives, so a getter cannot answer the duplicate check and the claim
differently and a later edit changes nothing. Structural syntax resolves
directly to its structural identity: no lookup, no provider, no import record.
The settlement map was keyed by name, so a program writing `<Open /><Open />`
collapsed two independently resolved answers into one and invoked the first
twice. Each occurrence now carries its own settlement, keyed by where the
element was written and paired with the admission's retained order, so two
elements resolved to two implementations invoke those two in order.

An unresolved occurrence is a settled outcome as well. It was absent from the
map, so the element fell through to the ordinary open chain and could be
answered by a lookup reconciliation never made. It now reports the ordinary
unresolved failure without consulting anybody, and the chain is entered exactly
twice for one evaluation whatever an occurrence settled to.

Settlements belong to the program's own parsed body. A component the program
invokes expands its own bytes at its own offsets, which nothing reconciled, so
carrying them in would have made a settlement a name-wide override of somebody
else's element.

The nested durable record is a protocol rather than a marker. A settled
occurrence records exactly `settled` and `name`, and a continuation parses that
as the hostile replay data it is before invoking anything: a missing,
additional, mistyped or unknown member, and a record naming another component,
each refuse.

A refusal this boundary raises during resolution — a second provider claiming
one answer, an answer changed after it was claimed — now reaches the caller
instead of being read as "this name resolves to nothing".
`readSettledImport()` cast the restored value and inspected it directly, so a
value that answers differently on a second read decided what a continuation
invoked. It now detaches the value into plain JSON under a failure boundary and
inspects only that copy: a member read once cannot answer twice, and a value
that will not detach is simply not the record. The admission's own restored
result is detached under the same boundary for the same reason.

The prose said one settled `import_component` per settled occurrence. It is one
per *resolved* occurrence: an unresolved one loads no component and records no
such event, which PE41 now asserts.

A retained value that refuses to be read at all — a Proxy trapping `ownKeys` or
a descriptor, a throwing accessor, a cycle — never reaches this parser. The
run's own retention check reads every retained result before the document body
starts and refuses there, in the journal's own words. That is a persistence
boundary rather than this one, so the evidence proves what this boundary can
promise: the component is never invoked.
…mand (#713)

EP9 proves a workflow run is given one `<Evaluate>` and not two, and it proves
it by starting a real run. `xmd workflow` exists on the Deno entrypoints alone,
so under Node and Bun the command refused before a run existed and the case
asserted nothing — which is why `test-node (2/7)` and `test-bun (3/4)` failed
while the same file passed locally under Deno.

The case moves to its own file and joins the Deno-only exclusions with its
reason and issue, the way every other test of a workflow command does. Tier EP's
portable half stays where it was and still runs on all three runtimes.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 9 redundant comments. Inline suggestions to remove them below.

"Component.expandProgram() has no provider: not inside a function component invocation.",
);
},
// deno-lint-ignore require-yield

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// deno-lint-ignore require-yield

"Component.resolveProgramSite() has no provider: not inside a function component invocation.",
);
},
// deno-lint-ignore require-yield

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// deno-lint-ignore require-yield

offered?.close();
record = yield createDurableOperation<Json>(
{ type: "import_component", name, ...sourceDescription(position) },
// deno-lint-ignore require-yield

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// deno-lint-ignore require-yield

case "workflow":
// The exact pinned source, already in hand: the bundle was read from
// the definition's own commit before this run existed, so recording it
// reads nothing and a replay reconstructs it without resolving a name.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// reads nothing and a replay reconstructs it without resolving a name.

case "declared-markdown":
// The exact declared bytes, already in hand: they were admitted
// before this run imported a root, so recording them reads nothing
// and a replay reconstructs the component without resolving a name.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// and a replay reconstructs the component without resolving a name.

digest: selected.digest,
content: selected.source,
// Recorded only when it holds, so an ordinary declaration's record
// is exactly what it always was.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// is exactly what it always was.


// Parsed rather than asserted: a replay hands back whatever the journal holds,
// and a history somebody else wrote is not a `DurableSelection` because it
// type-checked on the way in.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// type-checked on the way in.

}
// Canonical execution's own answer keeps its canonical identity. The
// selection that produced it is what names it, and asking for it here
// describes the definition this import actually settled on.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// describes the definition this import actually settled on.

// This import is canonical execution's own answer for a name this
// execution closed, which is the only provenance exact source is read
// from. An open import — one no tier claims — never sets it, however its
// answer describes itself.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// answer describes itself.

@taras taras changed the title ✨ Make <Evaluate> evaluate complete XMD programs (#713) ✨ Make <Evaluate> evaluate program text (#713) Sep 4, 2026
@taras

taras commented Sep 4, 2026

Copy link
Copy Markdown
Owner Author

The author contract for #713 has been superseded and the issue/PR handoff is now amended. Please do not continue or merge the current complete-program implementation.

Correction is sequenced after #759: use its exact merged result as the base, retain the durable replay/isolation work named in this PR body, remove the complete-root machinery, and implement the unified fragment-text contract. The next review requires a new signed feedback commit and the focused evidence listed here; the current 9a522a3d8a196ec501088d98cc61882e05426ebb is not a verdict candidate under the amended contract.

@taras taras changed the title ✨ Make <Evaluate> evaluate program text (#713) ✨ Evaluate generated XMD text with constrained authority (#713) Sep 6, 2026
@taras

taras commented Sep 6, 2026

Copy link
Copy Markdown
Owner Author

Architecture amendment: <Evaluate> is now a public engine-owned member of #758’s protected component tier. Protection fixes which policy interpreter runs; the trusted host profile supplies the ceiling; allow only narrows it. The PR body and #713 now freeze every Syntax replacement boundary plus a replacement-that-ignores-allow negative control. Restart from a clean worktree at latest main containing merged #759; do not continue from the current complete-program head. Request the next verdict only with a new signed feedback commit and the focused evidence, without waiting for CI.

@taras
taras enabled auto-merge (squash) September 6, 2026 09:10
@taras
taras disabled auto-merge September 6, 2026 10:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Evaluate generated XMD text with constrained authority

1 participant