Skip to content

[engine-harness-v1] 7 — Every Log event records the process and the runner that produced it #1574

Closed

Description

@daniboomerang

Tier: 1
Project: vinaya
Type: feat

Objectives

O1. packages/aeg-core/src/log/schema.ts adds a schema: 4 header meta: every schema: 3 field unchanged (including runtime, still string | null), plus a new process object { id: string, version: string | null, digest: string | null } and a new runner object { id: string, version: string | null } (id a free string, not an enum); HeaderMetaSchema and the custom family accept schema: 4 as well as 1–3; KNOWN_SCHEMA_VERSIONS in packages/aeg-core/src/log/store.ts includes 4, and classifyStoredLine returns a validated record for a schema: 4 line; schema.test.ts asserts a schema: 4 line missing process or runner, or with a string runner, is rejected, and a schema: 3 line still parses.
O2. buildHeader writes schema: 4, and this task adds the environment variables VINAYA_PROCESS_ID, VINAYA_PROCESS_VERSION, VINAYA_PROCESS_DIGEST, VINAYA_RUNNER_ID and VINAYA_RUNNER_VERSION: the process id defaults to vinaya and the runner id to standalone when absent or empty, and every version and digest absent or empty reads null; apps/cli/src/lib/log-sink.ts passes all five to buildHeader; VINAYA_RUNTIME still fills runtime exactly as on schema 3; packages/aeg-core/src/log/fixtures/generator.ts sets work.revision for a schema: 4 header as it does for schema: 3.
O3. @attalabs/aeg-core exports processAndRunnerOf(meta), which this task adds, returning the header's process and runner for a schema: 4 header, and process { id: 'vinaya', version: null, digest: null } with runner { id: 'standalone', version: null } for schema 1, 2 and 3.
O4. One table-driven test, packages/aeg-core/src/log/process-runner.test.ts, which this task adds, builds each row's header with buildHeader from its environment, parses it with HeaderMetaSchema, and asserts processAndRunnerOf returns the expected pair for exactly these five rows: vinaya + standalone; vinaya + atta-engine with a version and a digest; a process id other than vinaya + atta-engine; vinaya + a third-party runner id; and a stored schema: 3 line (not built), which reads as vinaya + standalone.
O5. The Engine runner sets the five variables before it creates its Log sink, through an exported function in processes/vinaya/bin/engine-log-identity.ts, which this task adds: process id, version and digest from the loaded process (identity.id, identity.version, digest of the harness loader's result), VINAYA_RUNNER_ID=atta-engine, and VINAYA_RUNNER_VERSION the version field of the installed @atta/engine package's own package.json; processes/vinaya/tests/engine-log-identity.test.ts asserts those five values for processes/vinaya.
O6. apps/log-server/src/worker.test.ts asserts an ingested schema: 4 event with runner atta-engine and one with runner standalone are each stored as valid events, not unknown_version or rejected, and an ingested schema: 3 event is still stored as valid.

Documentation

  • apps/cli/specs/log.md — the header field list names the process and runner objects, the five environment variables, that runtime keeps its schema 3 meaning, and that a schema 1–3 line reads as process vinaya on runner standalone (O1, O2, O3)
  • apps/log-server/specs/server.md — a schema: 4 line is validated once the server is redeployed; until then it is stored as unknown_version; and the sentence "The sender writes schema: 3" now reads schema: 4 (O6)
  • processes/vinaya/README.md — the Engine runner stamps its Log events with the loaded process identity and runner atta-engine with its version (O5)

Planner's rationale

Boundary — A new header schema version carrying the process (id, version, digest) and the runner (id, version) that produced each event, its producer wiring on both paths, a reader helper, and the server's acceptance test. Pinned files: packages/aeg-core/src/log/schema.ts, packages/aeg-core/src/log/store.ts, packages/aeg-core/src/log/fixtures/generator.ts, packages/aeg-core/src/log/envelope.ts, packages/aeg-core/src/log/schema.test.ts, packages/aeg-core/src/log/envelope.test.ts, packages/aeg-core/src/log/process-runner.test.ts, apps/cli/src/lib/log-sink.ts, apps/log-server/src/worker.test.ts, processes/vinaya/bin/engine-log-identity.ts, processes/vinaya/tests/engine-log-identity.test.ts, processes/vinaya/bin/run-engine.ts, apps/cli/specs/log.md, apps/log-server/specs/server.md. Out: deploying the Worker (a Principal step below), changing meta.flow or meta.source, any reader UI or Studio change, rewriting lines already on disk, any change to the standalone loop driver beyond the sink, the public portal's event-contract page (it still says schema 3; left for a later docs change).

doc-claims: the two specs' new sentences name only symbols this change adds or that exist on main (buildHeader, processAndRunnerOf, the five VINAYA_PROCESS_*/VINAYA_RUNNER_* variables, logEventSchemaDigest); no claim names a removed symbol.

reader-resolvable-prose: specs, READMEs and comments carry no Issue or pull-request numbers and no tranche slugs.

Sizing — One story: an event says which process and which runner wrote it. Schema, header, both producers and the server test fail together if split; the field is useless until both paths set it.

Project(s) + blast radius — Project: vinaya. @attalabs/aeg-core changes its exported schema and buildHeader; consumers: apps/cli (the sink, log cache and sync readers), apps/log-server (bundles the validator, so its schema_digest changes), processes/vinaya and harness (build headers in tests). Every test that asserts schema: 3 on a freshly built header moves to schema: 4; tests that parse stored schema 3 lines keep them. Both published packages need a changeset.

blast-radius-ack: aeg-core consumers enumerated above; the Worker needs a redeploy after merge.

Dependency rationale — Depends-on: #1564 — the Engine runner processes/vinaya/bin/run-engine.ts, where the sink is created, does not exist on main until that task merges; O5 edits it. Only that one file is shared with that task (below the collision threshold of three), but it cannot be edited before it exists.

Traps to avoid — Do NOT add process or runner to the schema: 3 meta, and do NOT change runtime on any version: that meta is strict, so an older server would reject such a line as invalid instead of keeping it as unknown_version; a new version is the only lossless path (the HeaderMetaV3Schema doc comment states the same rule for 2 → 3). Do NOT make the runner id an enum: a third-party runner names itself. Do NOT read process from meta.flow; flow stays as on schema 3. Do NOT read the Engine version from a hard-coded string or the tarball file name; read the installed package's package.json. Do NOT hand-edit a digest constant: logEventSchemaDigest derives itself.

Suggested agent-class — mid: an additive schema version plus mechanical test updates across known files.

Stop-and-escalate — Escalate when processes/vinaya/tests/engine-log-identity.test.ts cannot resolve a version for the installed Engine package; name the path it tried.

Docs to keep coherent — apps/cli/specs/log.md, apps/log-server/specs/server.md, processes/vinaya/README.md. Doc-owners derivation: apps/log-server/src/** binds apps/log-server/specs/server.md; packages/aeg-core/src/log and apps/cli/src/lib/log-sink.ts are documented by apps/cli/specs/log.md.

Principal step after merge — the Log server validates against the schema it bundled, so redeploy it or every schema: 4 event is stored as unknown_version:
[principal] cd apps/log-server && bunx wrangler deploy, then vinaya doctor shows the [logs] schema digest matching. No replay is needed: schema 4 lines that reached the old server are stored as unknown_version events, not rejected, and the redeployed server validates them. Deploy the Worker before any CLI release that writes schema 4.

Premises

  • packages/aeg-core/src/log/schema.ts contains const HeaderMetaSchema = z.discriminatedUnion('schema', [HeaderMetaV1Schema, HeaderMetaV2Schema, HeaderMetaV3Schema])
  • packages/aeg-core/src/log/schema.ts contains meta: HeaderMetaV3Schema,
  • packages/aeg-core/src/log/envelope.ts contains export function buildHeader(input: HeaderInput): Header {
  • packages/aeg-core/src/log/envelope.ts contains schema: 3,
  • apps/cli/src/lib/log-sink.ts contains runtime: env.VINAYA_RUNTIME,
  • processes/vinaya/package.json contains "@atta/engine": "file:../../apps/cli/tests/fixtures/atta-engine/atta-engine-0.0.1.tgz",
  • apps/log-server/package.json contains "deploy": "wrangler deploy",

Surface

in: packages/aeg-core/src, apps/cli/src, apps/cli/specs, apps/cli/tests, apps/log-server, processes, harness, .changeset
out: aeg-root

Parts

Part 1 (O1, O3, O4) — The schema 4 meta, the custom family, the store versions, processAndRunnerOf and the table test.
Part 2 (O2) — buildHeader, the sink, and moving fresh-header test assertions to schema 4.
Part 3 (O5) — The Engine log identity function, its test, and the runner call.
Part 4 (O6) — The Worker ingest test, specs and the changeset.

Test plan

cd packages/aeg-core && bunx vitest run src/log/schema.test.ts src/log/envelope.test.ts src/log/store.test.ts src/log/process-runner.test.ts src/log/schema-digest.test.ts → 0 fail
cd apps/cli && bun test tests/lib/log-sink.test.ts → 0 fail
cd apps/log-server && bunx vitest run src/worker.test.ts → 0 fail
cd processes/vinaya && bun test tests/engine-log-identity.test.ts → 0 fail
bunx turbo typecheck --affected → exits 0

Stop conditions

  • processes/vinaya/tests/engine-log-identity.test.ts cannot resolve a version for the installed Engine package.

Origin

Principal rule, 2026-10-22: Engine test runs must never mix with standalone-loop data in the Vinaya Log; every event records the process and the runtime (with versions) that produced it, as two independent objects (field runner; runtime already holds the agent vendor).

Activity

  1. changed the title [-][engine-harness-v1] 7 — Every Log event records which backend produced it and the Engine version[/-] [+][engine-harness-v1] 7 — Every Log event records the process and the runner that produced it[/+] on Oct 22, 2026
  2. daniboomerang commented on Oct 22, 2026

    @daniboomerang
    MemberAuthor

    Brief hash: 819b4c50b71ced0abb03d86fca37e27557c11dbbbc29251a0c38880d5467eb1e
    For: [model] (coding-agent CLI on a dev machine, dispatched locally, unattended)
    Reason: Suggested agent-class — mid: an additive schema version plus mechanical test updates across known files.
    Owner: the Principal
    Goal: Every Log event records the process and the runner that produced it
    Project: vinaya
    Tier: 1

    Closes #1574

    You are the AEG Developer. Run bun apps/cli/src/index.ts doctrine --role developer --print and read its output first. Mandatory.

    Objectives

    O1. packages/aeg-core/src/log/schema.ts adds a schema: 4 header meta: every schema: 3 field unchanged (including runtime, still string | null), plus a new process object { id: string, version: string | null, digest: string | null } and a new runner object { id: string, version: string | null } (id a free string, not an enum); HeaderMetaSchema and the custom family accept schema: 4 as well as 1–3; KNOWN_SCHEMA_VERSIONS in packages/aeg-core/src/log/store.ts includes 4, and classifyStoredLine returns a validated record for a schema: 4 line; schema.test.ts asserts a schema: 4 line missing process or runner, or with a string runner, is rejected, and a schema: 3 line still parses.
    O2. buildHeader writes schema: 4, and this task adds the environment variables VINAYA_PROCESS_ID, VINAYA_PROCESS_VERSION, VINAYA_PROCESS_DIGEST, VINAYA_RUNNER_ID and VINAYA_RUNNER_VERSION: the process id defaults to vinaya and the runner id to standalone when absent or empty, and every version and digest absent or empty reads null; apps/cli/src/lib/log-sink.ts passes all five to buildHeader; VINAYA_RUNTIME still fills runtime exactly as on schema 3; packages/aeg-core/src/log/fixtures/generator.ts sets work.revision for a schema: 4 header as it does for schema: 3.
    O3. @attalabs/aeg-core exports processAndRunnerOf(meta), which this task adds, returning the header's process and runner for a schema: 4 header, and process { id: 'vinaya', version: null, digest: null } with runner { id: 'standalone', version: null } for schema 1, 2 and 3.
    O4. One table-driven test, packages/aeg-core/src/log/process-runner.test.ts, which this task adds, builds each row's header with buildHeader from its environment, parses it with HeaderMetaSchema, and asserts processAndRunnerOf returns the expected pair for exactly these five rows: vinaya + standalone; vinaya + atta-engine with a version and a digest; a process id other than vinaya + atta-engine; vinaya + a third-party runner id; and a stored schema: 3 line (not built), which reads as vinaya + standalone.
    O5. The Engine runner sets the five variables before it creates its Log sink, through an exported function in processes/vinaya/bin/engine-log-identity.ts, which this task adds: process id, version and digest from the loaded process (identity.id, identity.version, digest of the harness loader's result), VINAYA_RUNNER_ID=atta-engine, and VINAYA_RUNNER_VERSION the version field of the installed @atta/engine package's own package.json; processes/vinaya/tests/engine-log-identity.test.ts asserts those five values for processes/vinaya.
    O6. apps/log-server/src/worker.test.ts asserts an ingested schema: 4 event with runner atta-engine and one with runner standalone are each stored as valid events, not unknown_version or rejected, and an ingested schema: 3 event is still stored as valid.

    Documentation

    • apps/cli/specs/log.md — the header field list names the process and runner objects, the five environment variables, that runtime keeps its schema 3 meaning, and that a schema 1–3 line reads as process vinaya on runner standalone (O1, O2, O3)
    • apps/log-server/specs/server.md — a schema: 4 line is validated once the server is redeployed; until then it is stored as unknown_version; and the sentence "The sender writes schema: 3" now reads schema: 4 (O6)
    • processes/vinaya/README.md — the Engine runner stamps its Log events with the loaded process identity and runner atta-engine with its version (O5)

    Premises

    Checked against the code when this task Issue was cut, and again against the default branch at dispatch — facts, not claims.

    • packages/aeg-core/src/log/schema.ts contains const HeaderMetaSchema = z.discriminatedUnion('schema', [HeaderMetaV1Schema, HeaderMetaV2Schema, HeaderMetaV3Schema])
    • packages/aeg-core/src/log/schema.ts contains meta: HeaderMetaV3Schema,
    • packages/aeg-core/src/log/envelope.ts contains export function buildHeader(input: HeaderInput): Header {
    • packages/aeg-core/src/log/envelope.ts contains schema: 3,
    • apps/cli/src/lib/log-sink.ts contains runtime: env.VINAYA_RUNTIME,
    • processes/vinaya/package.json contains "@atta/engine": "file:../../apps/cli/tests/fixtures/atta-engine/atta-engine-0.0.1.tgz",
    • apps/log-server/package.json contains "deploy": "wrangler deploy",

    2. Context — read before doing anything

    • Tranche: engine-harness-v1, task 7, Issue [engine-harness-v1] 7 — Every Log event records the process and the runner that produced it #1574. Branch task/engine-harness-v1/7. Depends-on: #1564, Conflicts-with: —.
    • Read Issue [engine-harness-v1] 7 — Every Log event records the process and the runner that produced it #1574 in full for the complete rationale — do not re-derive it.
    • Revision: rendered at c9cd70aec33e92de7430ddd1c7db2f35f41aa28a — the checkout's HEAD equaled the remote default branch, and no pinned file below carried an uncommitted change, when these facts were read.
    • Boundary — A new header schema version carrying the process (id, version, digest) and the runner (id, version) that produced each event, its producer wiring on both paths, a reader helper, and the server's acceptance test. Pinned files: packages/aeg-core/src/log/schema.ts, packages/aeg-core/src/log/store.ts, packages/aeg-core/src/log/fixtures/generator.ts, packages/aeg-core/src/log/envelope.ts, packages/aeg-core/src/log/schema.test.ts, packages/aeg-core/src/log/envelope.test.ts, packages/aeg-core/src/log/process-runner.test.ts, apps/cli/src/lib/log-sink.ts, apps/log-server/src/worker.test.ts, processes/vinaya/bin/engine-log-identity.ts, processes/vinaya/tests/engine-log-identity.test.ts, processes/vinaya/bin/run-engine.ts, apps/cli/specs/log.md, apps/log-server/specs/server.md. Out: deploying the Worker (a Principal step below), changing meta.flow or meta.source, any reader UI or Studio change, rewriting lines already on disk, any change to the standalone loop driver beyond the sink, the public portal's event-contract page (it still says schema 3; left for a later docs change).

    doc-claims: the two specs' new sentences name only symbols this change adds or that exist on main (buildHeader, processAndRunnerOf, the five VINAYA_PROCESS_*/VINAYA_RUNNER_* variables, logEventSchemaDigest); no claim names a removed symbol.

    reader-resolvable-prose: specs, READMEs and comments carry no Issue or pull-request numbers and no tranche slugs.

    • Traps to avoid — Do NOT add process or runner to the schema: 3 meta, and do NOT change runtime on any version: that meta is strict, so an older server would reject such a line as invalid instead of keeping it as unknown_version; a new version is the only lossless path (the HeaderMetaV3Schema doc comment states the same rule for 2 → 3). Do NOT make the runner id an enum: a third-party runner names itself. Do NOT read process from meta.flow; flow stays as on schema 3. Do NOT read the Engine version from a hard-coded string or the tarball file name; read the installed package's package.json. Do NOT hand-edit a digest constant: logEventSchemaDigest derives itself.

    3. Technical dependencies

    Dependency rationale — Depends-on: #1564 — the Engine runner processes/vinaya/bin/run-engine.ts, where the sink is created, does not exist on main until that task merges; O5 edits it. Only that one file is shared with that task (below the collision threshold of three), but it cannot be edited before it exists.

    4. Technical surface map

    Create:

    • (none — every surface file already exists)

    Modify:

    • packages/aeg-core/src

    • apps/cli/src

    • apps/cli/specs

    • apps/cli/tests

    • apps/log-server

    • processes

    • harness

    • .changeset

    • consumer-tests: none — no consumer test path named yet for @attalabs/aeg-core (apps/cli), @attalabs/aeg-core (packages/sources), @attalabs/aeg-core (processes/vinaya); name one before dispatch, or confirm no consumer-facing behavior changed.

    • consumer-tests: apps/log-server/src/worker.test.ts (covers @attalabs/aeg-core)

    Out of surface: aeg-root — a change there, or to any path no Surface in: glob covers, is still published: the review-loop driver records each such path in the pull request body's beyond-Surface block, and the reviewers judge it like any change.

    Premise pins

    Premise:

    • apps/cli/specs/log.md sha256: 96f7e7488cdc7b9055ff0d3e8cc6fe0c06aa9f49ced89e6a155c4a2ee146a666
    • apps/cli/src/lib/log-sink.ts sha256: c29d7e0a4bf8a0b83ceb59173188996060032a71efdc3c8cd485f94ff48e8988
    • apps/log-server/specs/server.md sha256: d9dd34c4259dbdcc0bec7c20ed9aadfc054bd5137c53ca80cc20f2f5fc68364a
    • apps/log-server/src/worker.test.ts sha256: 62217ac209ea882e580a4484f24db82be2db08399851fc6a59ed8c102677c3cb
    • packages/aeg-core/src/log/envelope.test.ts sha256: 045f6bff173d1d679571b1245c5b1879a187971a38f5dc51c7a8940983e99565
    • packages/aeg-core/src/log/envelope.ts sha256: 33271a28e882c4b5786b71e73e91fc2403a40a681c55dc8e9a36af6673a84486
    • packages/aeg-core/src/log/fixtures/generator.ts sha256: 7c196a6ee55d19e2baa69b0701aed13cb7a32a38db24edb471de71ec272231b2
    • packages/aeg-core/src/log/schema.test.ts sha256: 5f95c5780966e40f8812c86c03bfa9a65a10f2a0027dc3c86f55105ec383f6bf
    • packages/aeg-core/src/log/schema.ts sha256: b287dad8eeec0ff611aba11fe951ef28ee5fb9b558087400ff6c2faca31d1466
    • packages/aeg-core/src/log/store.ts sha256: ef632d26cd9f62874dd971d2b2d8b1125717f0a241b86d6dcbdbd088d02d0275
    • processes/vinaya/bin/run-engine.ts sha256: 6a78eb025aaac3d2354395da513ea5d8e0395973441d2d7e99f72ca3db15fae0

    5. Pre-flight checks

    Step 0 (mandatory, verbatim):

    bun install --frozen-lockfile --silent
    
    1. Clean status; parent origin/main; branch suffix literal-matches the task id.
    2. Under the review loop (bun apps/cli/src/index.ts task run), the driver has already run the dispatch-readiness gate plus, on this repository toolchain, its own fuller derivation from its own unsandboxed process before dispatching you (re-derived at render time: it was ready), and dispatches you only when that verdict is READY — a NOT READY verdict refuses the turn before it starts, so being dispatched is the verdict: look for no file and run neither script, whose own gh call fails inside your sandbox. Working manually, with no driver behind you, fall back to roles/developer.md's own items 3/5/7 prose — each a complete, hand-run forge check in its own right.

    On any failure: STOP and report.

    6. Numbered parts — publish once with publish_changes when every Part is done, then open_pull_request

    1. Part 1 (O1, O3, O4): The schema 4 meta, the custom family, the store versions, processAndRunnerOf and the table test.

      Files (touches @attalabs/vinaya):

      • apps/cli/specs/log.md
      • apps/cli/src/lib/log-sink.ts

      The pre-push hook runs the affected suite on your one push and refuses it on failure — do not run it yourself per Part.

    2. Part 2 (O2): buildHeader, the sink, and moving fresh-header test assertions to schema 4.

      Files (touches @attalabs/log-server):

      • apps/log-server/specs/server.md
      • apps/log-server/src/worker.test.ts

      The pre-push hook runs the affected suite on your one push and refuses it on failure — do not run it yourself per Part.

    3. Part 3 (O5): The Engine log identity function, its test, and the runner call.

      Files (touches @attalabs/aeg-core):

      • packages/aeg-core/src/log/envelope.test.ts
      • packages/aeg-core/src/log/envelope.ts
      • packages/aeg-core/src/log/fixtures/generator.ts
      • packages/aeg-core/src/log/schema.test.ts
      • packages/aeg-core/src/log/schema.ts
      • packages/aeg-core/src/log/store.ts

      The pre-push hook runs the affected suite on your one push and refuses it on failure — do not run it yourself per Part.

    4. Part 4 (O6): The Worker ingest test, specs and the changeset.

      Files (touches the repo root):

      • processes/vinaya/bin/run-engine.ts

      The pre-push hook runs the affected suite on your one push and refuses it on failure — do not run it yourself per Part.

    7. Documentation-update list

    • apps/cli/specs/log.md
    • apps/log-server/specs/server.md

    8. Verification before claiming done

    • Under the review loop, the controller runs the static gates: the commit hook applies safe format and lint fixes to staged files, typechecks affected packages, and runs the Vinaya checks; the pre-push hook runs the affected suite; run_checks and CI provide the authoritative results. Do not hand-run or paste static-gate commands. Working manually, run this repository's declared typecheck, lint/format, build, and documentation-gate commands yourself.
    • The pre-push hook runs the affected suite once, on your one push, and refuses it on failure; CI runs the full suite.
    • Every blast-radius consumer named in §4, re-verified by name.
    • The tier checklist in bun apps/cli/src/index.ts doctrine --role developer --print genuinely satisfied; use the controller's run_checks result, hooks, and CI as gate evidence.

    9. Test Plan

    cd packages/aeg-core && bunx vitest run src/log/schema.test.ts src/log/envelope.test.ts src/log/store.test.ts src/log/process-runner.test.ts src/log/schema-digest.test.ts → 0 fail
    cd apps/cli && bun test tests/lib/log-sink.test.ts → 0 fail
    cd apps/log-server && bunx vitest run src/worker.test.ts → 0 fail
    cd processes/vinaya && bun test tests/engine-log-identity.test.ts → 0 fail
    bunx turbo typecheck --affected → exits 0
    

    10. Stop conditions

    • processes/vinaya/tests/engine-log-identity.test.ts cannot resolve a version for the installed Engine package.

    Stop-and-escalate — Escalate when processes/vinaya/tests/engine-log-identity.test.ts cannot resolve a version for the installed Engine package; name the path it tried.

    11. Constraints

    Autonomy: Do not stop to ask clarifying questions. For any ambiguity not covered by a Section 10 stop condition, choose the most reasonable option consistent with this brief, record the choice in the PR body at open, or in a PR comment after open, and continue. Halt only for the explicit Section 10 stop conditions — and when you halt, record the blocker in a PR comment or an Issue comment rather than waiting interactively for input.

    12. Deliverable

    • PR title (exact): [engine-harness-v1] 7 — Every Log event records the process and the runner that produced it
    • Open the PR only via the open_pull_request tool (title and body); publish your commits with publish_changes and update the body with update_pull_request_body/refresh_evidence — you hold no gh/git push credential.
    • Publish once, with publish_changes, when every Part is done; then open the pull request with open_pull_request. Publish again only to answer review findings or a red gate — a refused hook, a failing check, a merge conflict.
    • PR body = the Developer's PR report (print it with bun apps/cli/src/index.ts doctrine --template pr-report --print), with Closes #1574 at the top of the header block. This brief stays frozen on the task Issue and never rides in the body.
    • Pre-open: tier checklist satisfied. The documentation gate is the controller's — run_checks and CI run it.
    • Include git diff origin/main...HEAD --stat as context only; Surface is judged by the driver's surface-scope check, never by this hand-run diff. Token use needs no report — the Vinaya log records it.
    • Then STOP. Review and Verification are separate invocations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions