Skip to content

M1-03: Implement fail-closed decision engine #6

Closed

Description

@pillowtalk-Qy

Fallback owner: Qy

Maintainer contract:

  • ADR 0001 and ADR 0002 fix the PreflightReport v0.1 evidence contract.
  • ADR 0003 fixes the Decision Engine v0.1 module, input, output, STOP reason-code, SourceReference, determinism, and test contracts.
  • PR feat: add PreflightReport v0.1 runtime schema #15 is a delivery dependency only and is not a contract source.

Delivery dependency:

  • Architecture planning and contract review are complete.
  • Decision Engine business implementation must not begin until M1-02: Define PreflightReport v0.1 runtime schema #5 and its implementation PR feat: add PreflightReport v0.1 runtime schema #15 are merged to main and that main head passes quality-gate.
  • After the dependency merges, implementation starts from latest main and the implementation PR remains Draft until its current-head quality-gate and Maintainer Review pass.
  • Merge order remains controlled by Qy through the Merge Gate.

Scope:

  • Create only @moss-mini-demo/decision-engine under the ADR 0003 package and public-entry boundary.
  • Evaluate the validated DecisionInputV0_1 projection.
  • Output only MANUAL_REVIEW or STOP with canonical structured reasons.
  • Return all mandatory STOP reasons using the fixed code order and relevant raw SourceReferences.
  • Remain pure, synchronous, deterministic, offline, and free of input mutation.

Acceptance:

  • Implement the exhaustive ADR 0003 StopReasonCodeV0_1 table without additions or aliases.
  • Every reason code has a positive trigger test.
  • Every reason code rejects missing, dangling, unrelated, metadata-targeting, and circular references.
  • Multiple reasons are complete, deduplicated, and ordered by canonical rank.
  • Repeated triggers aggregate sorted unique SourceReferences.
  • Invalid schema, unknown version, and invalid SourceReference reject before evaluation and emit no Decision.
  • The exact MANUAL_REVIEW boundary passes only with all mandatory evidence available and favorable and all critical Alignment checks PASS.
  • Any Warning, rollback, Receipt or Outcome failure, incomplete critical set, coverage failure, ordering failure, state interruption, critical Alignment FAIL/REVIEW, or missing/unprovable evidence produces STOP.
  • Node 22 package-name import and complete offline Vitest matrix pass through the sole public entry.
  • No test uses a network, real address, real protocol, or real-chain evidence.

Non-goals:

  • No UI, protocol adapter, Moss, RPC, wallet, signing, transaction submission, persistence, risk score, natural-language safety claim, Fixture, or real-chain integration.
  • No safe, approved, signable, or executable output.
  • No change to MANUAL_REVIEW meaning, mandatory STOP conditions, raw-evidence ownership, or Capability integrity.

This Issue remains Open and Project Ready until actual dependency-cleared implementation begins.

Activity

  1. 13 remaining items

  2. pillowtalk-Qy commented on Jul 31, 2026

    @pillowtalk-Qy
    ContributorAuthor

    Dependency gate cleared - 2026-07-31

    Current implementation baseline: main@27a9bc66f483a25d6602fdac2748099bfb32d67e.

    Evidence:

    Control decision:

    Next required action:

    1. Start from the exact current main baseline in an isolated worktree.
    2. Submit a closed Work Plan and exact writable file list for Maintainer scope confirmation.
    3. Implement only @moss-mini-demo/decision-engine and the minimal approved stable-fact documentation updates.
    4. Do not open M1-05: Add tokenOut mismatch STOP fixture #8 or M1-09: Add amountIn mismatch STOP fixture #20 for implementation until M1-03: Implement fail-closed decision engine #6 is merged and merged-main CI succeeds.

    This record authorizes Ready status only. It does not approve an implementation diff or a Merge Gate conclusion.

  3. added and removed
    status:blockedBlocked by an unresolved dependency
    on Jul 31, 2026
  4. pillowtalk-Qy commented on Aug 2, 2026

    @pillowtalk-Qy
    ContributorAuthor

    Final Implementation Work Plan - Awaiting Maintainer Scope Confirmation

    1. Planning authority, dependency gate, and exact baseline

    This is a planning-only record for Issue #6. It does not start implementation.

    Authoritative records checked:

    Planning baseline: main@7bbbc8bb9b4acb859bc73ba2b861f657864cce5c

    The exact baseline has a successful merged-main quality-gate:
    https://github.com/Moss-Mini-Demo/moss-mini-demo/actions/runs/30752494660

    Suggested future implementation branch:

    codex/issue-6-decision-engine-v0-1
    

    No branch, worktree, file, commit, or PR was created for this planning task. Implementation may begin only after the Maintainer confirms this closed scope.

    2. Closed future writable file list

    The proposed implementation surface is exactly these 14 paths. There are no wildcard paths or open-ended directories.

    Path Operation Why it is necessary
    package.json Modify Extend the root build script to build report-schema before decision-engine, and extend test:package-import to run both public package smoke tests. This keeps pnpm test and pnpm check valid from a clean checkout with no dist. No dependency or unrelated script change is planned.
    pnpm-lock.yaml Modify Record the new packages/decision-engine workspace importer and its workspace link to report-schema. No new third-party package is planned. This lockfile change requires separate Maintainer confirmation.
    packages/decision-engine/package.json Add Define the private ESM workspace package @moss-mini-demo/decision-engine, its sole export at dist/index.js, its declaration entry, build script, and workspace dependency on @moss-mini-demo/report-schema.
    packages/decision-engine/tsconfig.build.json Add Build only src TypeScript to dist with declarations, NodeNext module resolution, and the root strict settings; exclude tests and generated output.
    packages/decision-engine/src/index.ts Add Sole public entry. Export only evaluateDecisionV0_1, DecisionInputErrorV0_1, and the type-only DecisionV0_1 and StopReasonCodeV0_1 aliases.
    packages/decision-engine/src/input-boundary.ts Add Keep the staged schemaVersion check, public DecisionInputV0_1Schema parse, stable error classification, and DecisionInputErrorV0_1 implementation internal except for the exported error class.
    packages/decision-engine/src/evaluate.ts Add Implement the private 22-rule evaluation, code-owned canonical references, all-reason aggregation, UTF-8 reference sorting, rank ordering, and exact Decision return. No rule helper is exported.
    packages/decision-engine/test/synthetic.ts Add Provide test-only inline synthetic constructors for valid DecisionInput and controlled mutations. This is not a Fixture file and contains no real chain, protocol, address, secret, RPC, wallet, or transaction data.
    packages/decision-engine/test/input-boundary.test.ts Add Test strict input parsing, the three public error codes and precedence, complete-report rejection, and the invalid SourceReference matrix through the package public API.
    packages/decision-engine/test/stop-reason-matrix.test.ts Add Parameterize all 22 STOP codes, all canonical references, per-code report association failures, availability distinctions, and the empty-only Receipt/Outcome boundary.
    packages/decision-engine/test/evaluate.test.ts Add Test exact MANUAL_REVIEW, multi-reason behavior, aggregation, deduplication, rank/reference ordering, STOP precedence, determinism, deep-frozen input, and no mutation through the public package entry.
    packages/decision-engine/test/public-entry.smoke.mjs Add Under Node 22, resolve @moss-mini-demo/decision-engine to dist and verify only the two runtime exports are present and callable; exercise exact MANUAL_REVIEW and a STOP result by package name.
    README.md Modify After implementation, add the decision-engine package to the stable repository structure/current-state facts and remove only the obsolete claim that no Decision Engine exists.
    docs/real-vs-mock.md Modify After implementation, record the pure offline fail-closed Decision Engine as actually completed and remove only obsolete no-Decision-Engine/no-decision-logic claims while preserving all product and real-evidence exclusions.

    No file below packages/report-schema is writable. No ADR, STOP presentation, Fixture, workflow, architecture, governance, security, UI, wallet, RPC, Moss, or Monad file is writable.

    Separate Maintainer confirmation is requested for both root metadata files: package.json and pnpm-lock.yaml.

    3. Package boundary and sole public API

    Package identity:

    @moss-mini-demo/decision-engine
    

    Sole source entry:

    packages/decision-engine/src/index.ts
    

    Dependency direction:

    @moss-mini-demo/decision-engine
      -> @moss-mini-demo/report-schema
    

    Production code imports DecisionInputV0_1Schema and required TypeScript types only from the @moss-mini-demo/report-schema public package name. It will not import packages/report-schema/src or any private path.

    The complete decision-engine public surface is limited to:

    • evaluateDecisionV0_1(input: unknown): DecisionV0_1
    • DecisionInputErrorV0_1 with a readonly code
    • type DecisionV0_1
    • type StopReasonCodeV0_1

    DecisionV0_1 and StopReasonCodeV0_1 are type-only aliases of the report-schema public types. The package will not export an internal rule, rank table, comparator, aggregation helper, parser helper, runtime Decision Schema, debug state, Result envelope, or report-schema runtime re-export.

    No report-schema change is planned. Its existing public DecisionInputV0_1Schema and DecisionInputV0_1 type remain the sole runtime/type input contract.

    4. Deterministic evaluation data flow

    The evaluator will use this fixed synchronous flow:

    unknown input
    -> inspect schemaVersion before all other classification
    -> require schemaVersion exactly "0.1"
    -> call public DecisionInputV0_1Schema.safeParse
    -> classify any schema-owned SourceReference issue before other schema issues
    -> reject malformed, dangling, metadata-targeting, cyclic, owner-unrelated, or otherwise invalid references
    -> pass only the successful parsed DecisionInputV0_1 to rule evaluation
    -> execute all 22 STOP rules without an early return
    -> aggregate all triggering canonical references by code
    -> deduplicate each code's references by exact complete JSON Pointer string
    -> sort references by ascending UTF-8 byte order
    -> sort reasons by the fixed ADR rank
    -> return STOP when one or more reasons exist
    -> otherwise return exactly { "status": "MANUAL_REVIEW" }
    

    A complete PreflightReport is rejected because decision and limitations are forbidden input fields. Invalid input produces no Decision and is never downgraded to STOP.

    The Engine derives code-owned references only from the accepted ADR 0004 paths and validated alignment underlying references. It does not accept caller-authored Decision reasons and does not copy or repair invalid pointers.

    5. Error classification and precedence

    All boundary failures throw DecisionInputErrorV0_1. Its public readonly code is exactly one of:

    1. UNSUPPORTED_SCHEMA_VERSION
    2. INVALID_SOURCE_REFERENCE
    3. INVALID_DECISION_INPUT

    Staged classification:

    1. Before Schema evaluation, a non-object input, absent schemaVersion, or schemaVersion not exactly "0.1" throws UNSUPPORTED_SCHEMA_VERSION.
    2. With schemaVersion "0.1", run DecisionInputV0_1Schema.safeParse once. If the parse fails and any issue path identifies a schema-owned sourceReferences occurrence, classify the input as INVALID_SOURCE_REFERENCE.
    3. Otherwise classify the failed strict/cross-field parse as INVALID_DECISION_INPUT.
    4. If multiple classes occur, stages 1-3 enforce the fixed precedence above.

    Classification uses structured issue paths, not Zod message text. DecisionInputErrorV0_1 exposes a stable code and stable code-derived message only; Zod text is not public contract data. No Result envelope, parser text, partial Decision, fallback Decision, or STOP is returned on an input error.

    Tests will combine all class pairs and all three classes to prove precedence.

    6. Exhaustive 22-code implementation and acceptance table

    For every row, the positive test evaluates a valid synthetic input through @moss-mini-demo/decision-engine, asserts the exact code and references, assembles a synthetic report, and validates the association through the public PreflightReportSchema. The association-failure matrix described after the table runs for every code.

    Rank Code Exact trigger after valid input Canonical SourceReference Positive test
    10 NO_VALID_SELECTION selection.status is NOT_SELECTED /selection/status One NOT_SELECTED input emits this code and exact pointer.
    20 CAPABILITY_FAILED capability.availability is FAILED /capability/availability FAILED Capability emits rank 20 only for this fact.
    21 CAPABILITY_MISSING capability.availability is MISSING /capability/availability MISSING Capability emits rank 21.
    22 CAPABILITY_UNPROVABLE capability.availability is UNPROVABLE /capability/availability UNPROVABLE Capability emits rank 22.
    30 SIMULATION_ACQUISITION_FAILED simulation.availability is FAILED /simulation/availability FAILED simulation acquisition emits rank 30.
    31 SIMULATION_MISSING simulation.availability is MISSING /simulation/availability MISSING simulation emits rank 31.
    32 SIMULATION_UNPROVABLE simulation.availability is UNPROVABLE /simulation/availability UNPROVABLE simulation emits rank 32.
    40 SIMULATION_EXECUTION_FAILED available simulation has executionStatus FAILED /simulation/executionStatus FAILED execution emits rank 40 without obsolete raw collection paths.
    41 SIMULATION_INTERRUPTED available simulation has executionStatus INTERRUPTED /simulation/executionStatus INTERRUPTED execution emits rank 41.
    50 WARNING_PRESENT available warnings.items has one or more entries Every triggering /simulation/warnings/items/ Multiple warnings aggregate all item pointers.
    60 RECEIPT_FAILED any available receipt item has status FAILED Every triggering /simulation/receipts/items/ Multiple failed Receipts aggregate only failed item pointers.
    61 RECEIPT_SET_INCOMPLETE receipts is AVAILABLE and receipts.items is empty /simulation/receipts/items Empty items emits rank 61; a non-empty collection does not.
    70 OUTCOME_FAILED any available outcome item has status FAILED Every triggering /simulation/outcomes/items/ Multiple failed Outcomes aggregate only failed item pointers.
    71 OUTCOME_SET_INCOMPLETE outcomes is AVAILABLE and outcomes.items is empty /simulation/outcomes/items Empty items emits rank 71; a non-empty collection does not.
    80 COVERAGE_INCOMPLETE coverage is AVAILABLE and complete is false /simulation/coverage Available negative coverage emits semantic rank 80.
    90 ORDERING_INVALID ordering is AVAILABLE and valid is false /simulation/ordering Available negative ordering emits semantic rank 90.
    100 STATE_CONTINUITY_INTERRUPTED stateContinuity is AVAILABLE and continuous is false /simulation/stateContinuity Available interrupted continuity emits rank 100.
    110 CRITICAL_ALIGNMENT_FAIL one or more critical checks have status FAIL Union of each triggering check's validated underlying input references Multiple FAIL checks aggregate their underlying refs; no /alignment path is emitted.
    111 CRITICAL_ALIGNMENT_REVIEW one or more critical checks have status REVIEW Union of each triggering check's validated underlying input references Multiple REVIEW checks aggregate their underlying refs; no /alignment path is emitted.
    120 REQUIRED_EVIDENCE_FAILED any of the six components has availability FAILED Each triggering /simulation//availability Parameterize warnings, receipts, outcomes, coverage, ordering, and stateContinuity; aggregate every FAILED component.
    121 REQUIRED_EVIDENCE_MISSING any of the six components has availability MISSING Each triggering /simulation//availability Parameterize all six components; aggregate every MISSING component.
    122 REQUIRED_EVIDENCE_UNPROVABLE any of the six components has availability UNPROVABLE Each triggering /simulation//availability Parameterize all six components; aggregate every UNPROVABLE component.

    For ranks 120-122, component is exactly warnings, receipts, outcomes, coverage, ordering, or stateContinuity.

    Available adverse evidence uses its semantic code and does not also become an availability code. One source may still produce multiple independently applicable codes, and all such codes remain present.

    Per-code association-failure matrix:

    • omit sourceReferences from the assembled reason;
    • use an empty sourceReferences list;
    • add a syntactically valid dangling pointer;
    • add a resolvable pointer unrelated to that code;
    • target schema-owned sourceReferences metadata;
    • target decision, limitations, or alignment output;
    • attempt self-reference to the Decision reason;
    • while that code trigger is active, add a source-metadata cycle elsewhere in DecisionInput.

    Every mutation must be rejected by the public report-schema or DecisionInput boundary. Because the evaluator owns output references, it must never generate any of these invalid forms.

    7. Aggregation, ordering, and no-mutation rules

    Implementation invariants:

    • Execute every rule; never return after the first STOP trigger.
    • Emit at most one reason object per code.
    • For one code, union references from every triggering fact.
    • Deduplicate exact complete JSON Pointer strings.
    • Sort references with a private bytewise comparator over UTF-8 bytes, not localeCompare and not object traversal order.
    • Sort reasons strictly by ADR rank 10 through 122.
    • STOP wins whenever any reason exists, even if all other evidence is favorable.
    • Object key insertion order, repeated triggers, duplicate references, and internal rule declaration order cannot affect output.
    • evaluateDecisionV0_1 is pure and synchronous.
    • It reads no time, environment variable, network, file system, random source, mutable global, RPC, Moss, Monad, wallet, or external service.
    • It does not modify the original unknown input or the parsed value.

    Tests deep-freeze input, take a deep copy before evaluation, compare after evaluation, repeat evaluation, reconstruct equivalent objects with different key insertion order, and assert deeply identical canonical output.

    8. SourceReference rejection boundary

    DecisionInputV0_1Schema remains the only runtime authority for pointer syntax, resolution, ownership, metadata exclusion, self-reference, and cycles. The Engine will not copy that Schema or implement a competing pointer validator.

    Before rules run, tests must prove rejection of:

    • omitted and empty schema-owned reference arrays;
    • malformed JSON Pointer syntax;
    • dangling paths;
    • owner-unrelated paths;
    • report-owned sourceReferences, display, prose, extension, or extensions metadata outside raw;
    • decision, limitations, or alignment-result targets;
    • self-reference;
    • metadata cycles;
    • unknown schemaVersion;
    • unknown fields;
    • complete PreflightReport input;
    • any other strict Schema or cross-field failure.

    Raw payload keys whose names are sourceReferences, display, prose, extension, or extensions remain valid when structurally inside an accepted raw subtree. Natural language, metadata, an output Decision, limitations, or another reason can never prove a safety or STOP conclusion.

    9. Exact MANUAL_REVIEW boundary

    The only successful no-STOP output is exactly:

    { "status": "MANUAL_REVIEW" }
    

    It has no reasons or other property.

    The positive boundary requires all of the following:

    • strict DecisionInput validation succeeds;
    • selection.status is SELECTED and the selected protocol/Quote association is valid;
    • capability is AVAILABLE;
    • simulation is AVAILABLE with executionStatus SUCCESS;
    • warnings is AVAILABLE with empty items;
    • receipts and outcomes are AVAILABLE, non-empty, and contain no FAILED item;
    • coverage is AVAILABLE with complete true;
    • ordering is AVAILABLE with valid true;
    • stateContinuity is AVAILABLE with continuous true;
    • at least one critical alignment check exists and every critical check is PASS;
    • all 22 STOP rules produce no reason.

    Non-critical FAIL or REVIEW is not promoted into a new STOP semantic. MANUAL_REVIEW is human inspection only. It is not safety, approval, authorization, execution guarantee, signability, or permission to transact.

    10. Closed test matrix

    All decision-engine TypeScript tests import @moss-mini-demo/decision-engine by its public package name. Tests may use the public @moss-mini-demo/report-schema entry to construct types and validate assembled reports, but never import either package's private source.

    Planned coverage:

    • stop-reason-matrix.test.ts: 22 independent positive code cases, exact canonical references, every six-component availability permutation, valid assembled-report association, obsolete raw/ rejection, empty-only Receipt/Outcome completeness, and the per-code invalid association matrix.
    • input-boundary.test.ts: unsupported version, invalid SourceReference, invalid DecisionInput, all precedence combinations, missing/empty/dangling/unrelated/metadata/self/cycle cases, strict unknown fields, complete-report rejection, and raw-owned metadata-like key acceptance.
    • evaluate.test.ts: exact MANUAL_REVIEW shape and every success prerequisite; STOP-over-success; multiple reasons; duplicate code and reference aggregation; UTF-8 reference order; ADR rank order; repeated evaluation; different property insertion order; deep-freeze; before/after deep comparison; no input mutation; no I/O surface.
    • public-entry.smoke.mjs: clean-build Node 22 resolution to dist, expected runtime export names only, callable evaluator/error class, one exact MANUAL_REVIEW result, and one STOP result.
    • Existing report-schema tests: run unchanged as regression coverage.
    • Boundary scan: no network calls, real addresses, private keys, API keys, wallets, signing, transaction submission, live protocol data, or real-chain evidence.

    Test data is synthetic and inline/test-constructor based. No Fixture file is added.

    11. Minimal stable documentation update

    README.md after implementation:

    • state that the pure offline Decision Engine package now exists;
    • add packages/decision-engine to repository structure;
    • remove only the obsolete current-state claim that no Decision Engine exists;
    • retain that there is no runnable demo, frontend, backend, Moss/Monad integration, wallet, signing, transaction, or real-chain evidence;
    • state that MANUAL_REVIEW and green tooling/CI are not safety guarantees.

    docs/real-vs-mock.md after implementation:

    • add the completed pure, synchronous, deterministic, offline, fail-closed Decision Engine to Actually completed;
    • remove only the obsolete no Decision Engine and no decision logic statements;
    • retain the absence of STOP Fixture, UI, backend, RPC, wallet, signing, transaction, Moss/Monad integration, and real chain data;
    • contain no PR number, Draft state, review state, or other lifecycle wording.

    12. Future implementation verification

    Required environment:

    • Node 22, with the project constraint and expected local version checked explicitly
    • pnpm 11
    • public package-name import must succeed under Node 22

    Commands:

    node --version
    pnpm --version
    pnpm install --frozen-lockfile
    pnpm --filter @moss-mini-demo/decision-engine build
    pnpm format:check
    pnpm lint
    pnpm typecheck
    pnpm build
    pnpm test:package-import
    pnpm test
    pnpm check
    git diff --check origin/main...HEAD
    git status --short
    

    The implementation PR must also obtain quality-gate SUCCESS for its exact current Head before Pre-PR QA or any Maintainer gate.

    13. Explicit non-goals

    14. Risks, rollback, and requested Maintainer confirmation

    Risks to review before implementation:

    • Error classification could drift if source-reference failures are identified from unstable text instead of structured issue paths; this plan forbids message matching.
    • A code could borrow another code's evidence or omit one of several triggers; the per-code assembled-report matrix and all-trigger aggregation tests address this.
    • All-reason aggregation, UTF-8 sorting, or rank order could drift through traversal or declaration order; deterministic permutation tests address this.
    • Package exports could work in TypeScript but fail as a Node package from clean dist; the Node 22 package-name smoke test addresses this.
    • Root build/test scripts and the new workspace importer require package.json and pnpm-lock.yaml changes; both need explicit approval and frozen-install verification.
    • Documentation could overstate the offline Engine as an application, chain evidence, or safety capability, or record transient PR state; the two-file stable-fact boundary prevents that.
    • v0.1 cannot detect arbitrary non-empty partially omitted Receipt/Outcome sets; implementation and docs must retain the empty-only limitation.

    Rollback is limited to the Maintainer reverting the future #6 independent implementation commit or squash merge. Schema or ADR changes are not a compensating rollback mechanism.

    Maintainer scope confirmation is requested for:

    • the exact 14-file writable list;
    • the sole public API;
    • root package.json modification;
    • pnpm-lock.yaml workspace importer modification;
    • the 22-code trigger/reference table;
    • error classification and fixed precedence;
    • aggregation, UTF-8 ordering, and rank rules;
    • the full test matrix;
    • the minimal README.md and docs/real-vs-mock.md updates.

    Until that confirmation is recorded, no implementation branch, file, commit, or PR may be created.

    15. Planning outcome

    Requested status after this comment:

    WORK_PLAN_SUBMITTED / AWAITING_MAINTAINER_SCOPE_CONFIRMATION
    

    This comment does not enter Maintainer Review, Merge Gate, or implementation. Qy stops Builder activity after publishing and returns this plan to the independent Maintainer window.

  5. pillowtalk-Qy commented on Aug 2, 2026

    @pillowtalk-Qy
    ContributorAuthor

    SCOPE_CHANGES_REQUESTED

    Scope Gate reviewed the fixed Final Work Plan at #6 (comment) against exact baseline main@7bbbc8bb9b4acb859bc73ba2b861f657864cce5c, Accepted ADR 0003, and the corrections in Accepted ADR 0004. The baseline quality-gate is SUCCESS: https://github.com/Moss-Mini-Demo/moss-mini-demo/actions/runs/30752494660

    Contract result

    The proposed pure, synchronous, offline, deterministic and fail-closed evaluator; strict public DecisionInputV0_1Schema boundary; three input error classes and precedence; exhaustive 22-code/rank/reference table; all-rule aggregation; UTF-8 reference ordering; exact { "status": "MANUAL_REVIEW" } result; SourceReference ownership; public package dependency; 14-path boundary; runtime/type-only export boundary; and documentation/non-goal boundaries are consistent with ADR 0003 as corrected by ADR 0004. ADR 0004 correctly takes precedence for the MANUAL_REVIEW shape, canonical items/<i> paths, and empty-only Receipt/Outcome incompleteness.

    Blocking plan inconsistency

    The closed plan does not yet provide an executable clean-checkout build/typecheck order for its required public package import:

    • Current .github/workflows/quality-gate.yml performs only pnpm install --frozen-lockfile and then pnpm check.
    • Current root check runs typecheck before build.
    • @moss-mini-demo/report-schema publishes its public type/runtime entry from dist/index.d.ts and dist/index.js; dist is not committed.
    • The plan requires Decision Engine production TypeScript to import that public package, but authorizes the root package.json change only to extend build and test:package-import. Extending build cannot make report-schema dist exist before the earlier clean-checkout typecheck.
    • The proposed verification also runs pnpm --filter @moss-mini-demo/decision-engine build before any explicit report-schema/root build, without defining how the public dependency has first been built.

    As written, the plan can therefore pass after a prior local build while still fail the required fresh-run quality-gate. Scope confirmation cannot rely on generated state left by an earlier command.

    Required Work Plan revision

    1. Specify one clean-checkout ordering that makes the report-schema public entry available before Decision Engine typechecking/building and that also matches the actual GitHub quality-gate entry point.
    2. Preserve the public @moss-mini-demo/report-schema import. Do not import src, commit dist, build from test code, duplicate Schema validation, or add a third-party dependency.
    3. Reconcile or remove the standalone Decision Engine build command that currently precedes its dependency build.
    4. If the resolution changes root typecheck/check semantics, adds a lifecycle script, changes workflow/config, or needs any path/operation beyond the fixed authorization request, state that expansion explicitly and request a new Maintainer Scope Gate. Do not hide it inside the existing build/smoke wording.
    5. Publish a replacement Final Work Plan bound to the then-current exact main. No implementation branch, file, commit, or PR may be created before that replacement is confirmed.

    Issue #6 remains Open / Qy assigned / status:ready / Project Ready / M1. Issues #8 and #20 remain Blocked.

    This is a planning Scope Gate only. It is not QA PASS, GitHub Review, Approval, Merge Gate, implementation authorization, or merge authorization.

  6. pillowtalk-Qy commented on Aug 2, 2026

    @pillowtalk-Qy
    ContributorAuthor

    Final Implementation Work Plan v2 - Clean Checkout Ordering Fixed - Awaiting Maintainer Scope Confirmation

    1. Planning authority, dependency gate, and exact baseline

    This is a planning-only record for Issue #6. It does not start implementation.

    This v2 plan fully supersedes the earlier Work Plan at
    #6 (comment)
    without deleting or editing that historical comment. It resolves the
    SCOPE_CHANGES_REQUESTED record at
    #6 (comment)
    and requests a new Maintainer Scope Gate.

    Authoritative records checked:

    Planning baseline: main@7bbbc8bb9b4acb859bc73ba2b861f657864cce5c

    The exact baseline has a successful merged-main quality-gate:
    https://github.com/Moss-Mini-Demo/moss-mini-demo/actions/runs/30752494660

    Suggested future implementation branch:

    codex/issue-6-decision-engine-v0-1
    

    No branch, worktree, file, commit, or PR was created for this planning task. Implementation may begin only after the Maintainer confirms this closed scope.

    2. Closed future writable file list

    The proposed implementation surface remains exactly the same 14 paths as v1: no path is added or removed. There are no wildcard paths or open-ended directories.

    Path Operation Why it is necessary
    package.json Modify Explicitly fix clean-checkout ordering in the existing scripts: typecheck first builds report-schema before root tsc; build runs report-schema then decision-engine; test:package-import runs both public package smoke tests after build. Keep test beginning with root build and keep check as the sole quality-gate sequence. Add no dependency, lifecycle script, or unrelated script change. This expanded operation requires a new Maintainer Scope Gate.
    pnpm-lock.yaml Modify Record the new packages/decision-engine workspace importer and its workspace link to report-schema. No new third-party package is planned. This lockfile change requires separate Maintainer confirmation.
    packages/decision-engine/package.json Add Define the private ESM workspace package @moss-mini-demo/decision-engine, its sole export at dist/index.js, its declaration entry, build script, and workspace dependency on @moss-mini-demo/report-schema.
    packages/decision-engine/tsconfig.build.json Add Build only src TypeScript to dist with declarations, NodeNext module resolution, and the root strict settings; exclude tests and generated output.
    packages/decision-engine/src/index.ts Add Sole public entry. Export only evaluateDecisionV0_1, DecisionInputErrorV0_1, and the type-only DecisionV0_1 and StopReasonCodeV0_1 aliases.
    packages/decision-engine/src/input-boundary.ts Add Keep the staged schemaVersion check, public DecisionInputV0_1Schema parse, stable error classification, and DecisionInputErrorV0_1 implementation internal except for the exported error class.
    packages/decision-engine/src/evaluate.ts Add Implement the private 22-rule evaluation, code-owned canonical references, all-reason aggregation, UTF-8 reference sorting, rank ordering, and exact Decision return. No rule helper is exported.
    packages/decision-engine/test/synthetic.ts Add Provide test-only inline synthetic constructors for valid DecisionInput and controlled mutations. This is not a Fixture file and contains no real chain, protocol, address, secret, RPC, wallet, or transaction data.
    packages/decision-engine/test/input-boundary.test.ts Add Test strict input parsing, the three public error codes and precedence, complete-report rejection, and the invalid SourceReference matrix through the package public API.
    packages/decision-engine/test/stop-reason-matrix.test.ts Add Parameterize all 22 STOP codes, all canonical references, per-code report association failures, availability distinctions, and the empty-only Receipt/Outcome boundary.
    packages/decision-engine/test/evaluate.test.ts Add Test exact MANUAL_REVIEW, multi-reason behavior, aggregation, deduplication, rank/reference ordering, STOP precedence, determinism, deep-frozen input, and no mutation through the public package entry.
    packages/decision-engine/test/public-entry.smoke.mjs Add Under Node 22, resolve @moss-mini-demo/decision-engine to dist and verify only the two runtime exports are present and callable; exercise exact MANUAL_REVIEW and a STOP result by package name.
    README.md Modify After implementation, add the decision-engine package to the stable repository structure/current-state facts and remove only the obsolete claim that no Decision Engine exists.
    docs/real-vs-mock.md Modify After implementation, record the pure offline fail-closed Decision Engine as actually completed and remove only obsolete no-Decision-Engine/no-decision-logic claims while preserving all product and real-evidence exclusions.

    No file below packages/report-schema is writable. No ADR, STOP presentation, Fixture, workflow, architecture, governance, security, UI, wallet, RPC, Moss, or Monad file is writable.

    Separate Maintainer confirmation is requested for both root metadata files: package.json and pnpm-lock.yaml.

    3. Clean-checkout build and quality-gate ordering

    The implementation must be verified from a newly created isolated worktree with
    node_modules absent and every dist directory absent before installation. No
    generated output from this planning workspace or another worktree may be reused.

    The future root package.json script semantics are fixed as follows:

    "typecheck":
      pnpm --filter @moss-mini-demo/report-schema build
      then tsc --noEmit
    
    "build":
      pnpm --filter @moss-mini-demo/report-schema build
      then pnpm --filter @moss-mini-demo/decision-engine build
    
    "test:package-import":
      node packages/report-schema/test/public-entry.smoke.mjs
      then node packages/decision-engine/test/public-entry.smoke.mjs
    
    "test":
      pnpm build
      then vitest run --passWithNoTests
    
    "check":
      pnpm format:check
      then pnpm lint
      then pnpm typecheck
      then pnpm build
      then pnpm test:package-import
      then pnpm test
    

    The executable one-line script values will use && between these steps so any
    failure stops the quality gate. The current check order remains unchanged;
    typecheck itself becomes responsible for preparing the report-schema public
    types before root tsc runs. Root build then deterministically rebuilds
    report-schema and builds decision-engine. test:package-import runs only after
    both packages have been built by the preceding root build. test retains its
    existing root-build precondition before Vitest.

    The GitHub Actions workflow remains unchanged. Its only quality command remains:

    pnpm check
    

    The job name remains quality-gate, and its install step remains:

    pnpm install --frozen-lockfile
    

    No prebuild, pretypecheck, prepare, postinstall, or other lifecycle script is
    added. No TypeScript paths alias, committed dist, build invoked from test code,
    third-party dependency, report-schema private import, or duplicated Schema is
    allowed.

    A clean checkout must not begin package verification with:

    pnpm --filter @moss-mini-demo/decision-engine build
    

    The normal clean-checkout command is pnpm build. If package-specific build
    diagnosis is needed, the only valid explicit order is:

    pnpm --filter @moss-mini-demo/report-schema build
    pnpm --filter @moss-mini-demo/decision-engine build
    

    Production decision-engine TypeScript imports @moss-mini-demo/report-schema by
    its public package name. Decision-engine Vitest files import only their package's
    sole source entry, ../src/index.js, so root tsc does not require decision-engine
    dist before the later build step. The Node 22 smoke test imports
    @moss-mini-demo/decision-engine by package name only after root build has
    created dist. No test imports input-boundary.ts or evaluate.ts directly.

    4. Package boundary and sole public API

    Package identity:

    @moss-mini-demo/decision-engine
    

    Sole source entry:

    packages/decision-engine/src/index.ts
    

    Dependency direction:

    @moss-mini-demo/decision-engine
      -> @moss-mini-demo/report-schema
    

    Production code imports DecisionInputV0_1Schema and required TypeScript types only from the @moss-mini-demo/report-schema public package name. It will not import packages/report-schema/src or any private path.

    The complete decision-engine public surface is limited to:

    • evaluateDecisionV0_1(input: unknown): DecisionV0_1
    • DecisionInputErrorV0_1 with a readonly code
    • type DecisionV0_1
    • type StopReasonCodeV0_1

    DecisionV0_1 and StopReasonCodeV0_1 are type-only aliases of the report-schema public types. The package will not export an internal rule, rank table, comparator, aggregation helper, parser helper, runtime Decision Schema, debug state, Result envelope, or report-schema runtime re-export.

    No report-schema change is planned. Its existing public DecisionInputV0_1Schema and DecisionInputV0_1 type remain the sole runtime/type input contract.

    5. Deterministic evaluation data flow

    The evaluator will use this fixed synchronous flow:

    unknown input
    -> inspect schemaVersion before all other classification
    -> require schemaVersion exactly "0.1"
    -> call public DecisionInputV0_1Schema.safeParse
    -> classify any schema-owned SourceReference issue before other schema issues
    -> reject malformed, dangling, metadata-targeting, cyclic, owner-unrelated, or otherwise invalid references
    -> pass only the successful parsed DecisionInputV0_1 to rule evaluation
    -> execute all 22 STOP rules without an early return
    -> aggregate all triggering canonical references by code
    -> deduplicate each code's references by exact complete JSON Pointer string
    -> sort references by ascending UTF-8 byte order
    -> sort reasons by the fixed ADR rank
    -> return STOP when one or more reasons exist
    -> otherwise return exactly { "status": "MANUAL_REVIEW" }
    

    A complete PreflightReport is rejected because decision and limitations are forbidden input fields. Invalid input produces no Decision and is never downgraded to STOP.

    The Engine derives code-owned references only from the accepted ADR 0004 paths and validated alignment underlying references. It does not accept caller-authored Decision reasons and does not copy or repair invalid pointers.

    6. Error classification and precedence

    All boundary failures throw DecisionInputErrorV0_1. Its public readonly code is exactly one of:

    1. UNSUPPORTED_SCHEMA_VERSION
    2. INVALID_SOURCE_REFERENCE
    3. INVALID_DECISION_INPUT

    Staged classification:

    1. Before Schema evaluation, a non-object input, absent schemaVersion, or schemaVersion not exactly "0.1" throws UNSUPPORTED_SCHEMA_VERSION.
    2. With schemaVersion "0.1", run DecisionInputV0_1Schema.safeParse once. If the parse fails and any issue path identifies a schema-owned sourceReferences occurrence, classify the input as INVALID_SOURCE_REFERENCE.
    3. Otherwise classify the failed strict/cross-field parse as INVALID_DECISION_INPUT.
    4. If multiple classes occur, stages 1-3 enforce the fixed precedence above.

    Classification uses structured issue paths, not Zod message text. DecisionInputErrorV0_1 exposes a stable code and stable code-derived message only; Zod text is not public contract data. No Result envelope, parser text, partial Decision, fallback Decision, or STOP is returned on an input error.

    Tests will combine all class pairs and all three classes to prove precedence.

    7. Exhaustive 22-code implementation and acceptance table

    For every row, the positive test evaluates a valid synthetic input through the decision-engine sole public entry, asserts the exact code and references, assembles a synthetic report, and validates the association through the public PreflightReportSchema. The association-failure matrix described after the table runs for every code.

    Rank Code Exact trigger after valid input Canonical SourceReference Positive test
    10 NO_VALID_SELECTION selection.status is NOT_SELECTED /selection/status One NOT_SELECTED input emits this code and exact pointer.
    20 CAPABILITY_FAILED capability.availability is FAILED /capability/availability FAILED Capability emits rank 20 only for this fact.
    21 CAPABILITY_MISSING capability.availability is MISSING /capability/availability MISSING Capability emits rank 21.
    22 CAPABILITY_UNPROVABLE capability.availability is UNPROVABLE /capability/availability UNPROVABLE Capability emits rank 22.
    30 SIMULATION_ACQUISITION_FAILED simulation.availability is FAILED /simulation/availability FAILED simulation acquisition emits rank 30.
    31 SIMULATION_MISSING simulation.availability is MISSING /simulation/availability MISSING simulation emits rank 31.
    32 SIMULATION_UNPROVABLE simulation.availability is UNPROVABLE /simulation/availability UNPROVABLE simulation emits rank 32.
    40 SIMULATION_EXECUTION_FAILED available simulation has executionStatus FAILED /simulation/executionStatus FAILED execution emits rank 40 without obsolete raw collection paths.
    41 SIMULATION_INTERRUPTED available simulation has executionStatus INTERRUPTED /simulation/executionStatus INTERRUPTED execution emits rank 41.
    50 WARNING_PRESENT available warnings.items has one or more entries Every triggering /simulation/warnings/items/ Multiple warnings aggregate all item pointers.
    60 RECEIPT_FAILED any available receipt item has status FAILED Every triggering /simulation/receipts/items/ Multiple failed Receipts aggregate only failed item pointers.
    61 RECEIPT_SET_INCOMPLETE receipts is AVAILABLE and receipts.items is empty /simulation/receipts/items Empty items emits rank 61; a non-empty collection does not.
    70 OUTCOME_FAILED any available outcome item has status FAILED Every triggering /simulation/outcomes/items/ Multiple failed Outcomes aggregate only failed item pointers.
    71 OUTCOME_SET_INCOMPLETE outcomes is AVAILABLE and outcomes.items is empty /simulation/outcomes/items Empty items emits rank 71; a non-empty collection does not.
    80 COVERAGE_INCOMPLETE coverage is AVAILABLE and complete is false /simulation/coverage Available negative coverage emits semantic rank 80.
    90 ORDERING_INVALID ordering is AVAILABLE and valid is false /simulation/ordering Available negative ordering emits semantic rank 90.
    100 STATE_CONTINUITY_INTERRUPTED stateContinuity is AVAILABLE and continuous is false /simulation/stateContinuity Available interrupted continuity emits rank 100.
    110 CRITICAL_ALIGNMENT_FAIL one or more critical checks have status FAIL Union of each triggering check's validated underlying input references Multiple FAIL checks aggregate their underlying refs; no /alignment path is emitted.
    111 CRITICAL_ALIGNMENT_REVIEW one or more critical checks have status REVIEW Union of each triggering check's validated underlying input references Multiple REVIEW checks aggregate their underlying refs; no /alignment path is emitted.
    120 REQUIRED_EVIDENCE_FAILED any of the six components has availability FAILED Each triggering /simulation//availability Parameterize warnings, receipts, outcomes, coverage, ordering, and stateContinuity; aggregate every FAILED component.
    121 REQUIRED_EVIDENCE_MISSING any of the six components has availability MISSING Each triggering /simulation//availability Parameterize all six components; aggregate every MISSING component.
    122 REQUIRED_EVIDENCE_UNPROVABLE any of the six components has availability UNPROVABLE Each triggering /simulation//availability Parameterize all six components; aggregate every UNPROVABLE component.

    For ranks 120-122, component is exactly warnings, receipts, outcomes, coverage, ordering, or stateContinuity.

    Available adverse evidence uses its semantic code and does not also become an availability code. One source may still produce multiple independently applicable codes, and all such codes remain present.

    Per-code association-failure matrix:

    • omit sourceReferences from the assembled reason;
    • use an empty sourceReferences list;
    • add a syntactically valid dangling pointer;
    • add a resolvable pointer unrelated to that code;
    • target schema-owned sourceReferences metadata;
    • target decision, limitations, or alignment output;
    • attempt self-reference to the Decision reason;
    • while that code trigger is active, add a source-metadata cycle elsewhere in DecisionInput.

    Every mutation must be rejected by the public report-schema or DecisionInput boundary. Because the evaluator owns output references, it must never generate any of these invalid forms.

    8. Aggregation, ordering, and no-mutation rules

    Implementation invariants:

    • Execute every rule; never return after the first STOP trigger.
    • Emit at most one reason object per code.
    • For one code, union references from every triggering fact.
    • Deduplicate exact complete JSON Pointer strings.
    • Sort references with a private bytewise comparator over UTF-8 bytes, not localeCompare and not object traversal order.
    • Sort reasons strictly by ADR rank 10 through 122.
    • STOP wins whenever any reason exists, even if all other evidence is favorable.
    • Object key insertion order, repeated triggers, duplicate references, and internal rule declaration order cannot affect output.
    • evaluateDecisionV0_1 is pure and synchronous.
    • It reads no time, environment variable, network, file system, random source, mutable global, RPC, Moss, Monad, wallet, or external service.
    • It does not modify the original unknown input or the parsed value.

    Tests deep-freeze input, take a deep copy before evaluation, compare after evaluation, repeat evaluation, reconstruct equivalent objects with different key insertion order, and assert deeply identical canonical output.

    9. SourceReference rejection boundary

    DecisionInputV0_1Schema remains the only runtime authority for pointer syntax, resolution, ownership, metadata exclusion, self-reference, and cycles. The Engine will not copy that Schema or implement a competing pointer validator.

    Before rules run, tests must prove rejection of:

    • omitted and empty schema-owned reference arrays;
    • malformed JSON Pointer syntax;
    • dangling paths;
    • owner-unrelated paths;
    • report-owned sourceReferences, display, prose, extension, or extensions metadata outside raw;
    • decision, limitations, or alignment-result targets;
    • self-reference;
    • metadata cycles;
    • unknown schemaVersion;
    • unknown fields;
    • complete PreflightReport input;
    • any other strict Schema or cross-field failure.

    Raw payload keys whose names are sourceReferences, display, prose, extension, or extensions remain valid when structurally inside an accepted raw subtree. Natural language, metadata, an output Decision, limitations, or another reason can never prove a safety or STOP conclusion.

    10. Exact MANUAL_REVIEW boundary

    The only successful no-STOP output is exactly:

    { "status": "MANUAL_REVIEW" }
    

    It has no reasons or other property.

    The positive boundary requires all of the following:

    • strict DecisionInput validation succeeds;
    • selection.status is SELECTED and the selected protocol/Quote association is valid;
    • capability is AVAILABLE;
    • simulation is AVAILABLE with executionStatus SUCCESS;
    • warnings is AVAILABLE with empty items;
    • receipts and outcomes are AVAILABLE, non-empty, and contain no FAILED item;
    • coverage is AVAILABLE with complete true;
    • ordering is AVAILABLE with valid true;
    • stateContinuity is AVAILABLE with continuous true;
    • at least one critical alignment check exists and every critical check is PASS;
    • all 22 STOP rules produce no reason.

    Non-critical FAIL or REVIEW is not promoted into a new STOP semantic. MANUAL_REVIEW is human inspection only. It is not safety, approval, authorization, execution guarantee, signability, or permission to transact.

    11. Closed test matrix

    All decision-engine Vitest files import only the sole public source entry at ../src/index.js; they never import input-boundary.ts, evaluate.ts, or report-schema private source. Tests may use the public @moss-mini-demo/report-schema package entry to construct types and validate assembled reports. After root build, public-entry.smoke.mjs separately proves Node 22 package-name resolution for @moss-mini-demo/decision-engine.

    Planned coverage:

    • stop-reason-matrix.test.ts: 22 independent positive code cases, exact canonical references, every six-component availability permutation, valid assembled-report association, obsolete raw/ rejection, empty-only Receipt/Outcome completeness, and the per-code invalid association matrix.
    • input-boundary.test.ts: unsupported version, invalid SourceReference, invalid DecisionInput, all precedence combinations, missing/empty/dangling/unrelated/metadata/self/cycle cases, strict unknown fields, complete-report rejection, and raw-owned metadata-like key acceptance.
    • evaluate.test.ts: exact MANUAL_REVIEW shape and every success prerequisite; STOP-over-success; multiple reasons; duplicate code and reference aggregation; UTF-8 reference order; ADR rank order; repeated evaluation; different property insertion order; deep-freeze; before/after deep comparison; no input mutation; no I/O surface.
    • public-entry.smoke.mjs: after explicit root build, clean-checkout Node 22 package-name resolution to dist, expected runtime export names only, callable evaluator/error class, one exact MANUAL_REVIEW result, and one STOP result.
    • Existing report-schema tests: run unchanged as regression coverage.
    • Boundary scan: no network calls, real addresses, private keys, API keys, wallets, signing, transaction submission, live protocol data, or real-chain evidence.

    Test data is synthetic and inline/test-constructor based. No Fixture file is added.

    12. Minimal stable documentation update

    README.md after implementation:

    • state that the pure offline Decision Engine package now exists;
    • add packages/decision-engine to repository structure;
    • remove only the obsolete current-state claim that no Decision Engine exists;
    • retain that there is no runnable demo, frontend, backend, Moss/Monad integration, wallet, signing, transaction, or real-chain evidence;
    • state that MANUAL_REVIEW and green tooling/CI are not safety guarantees.

    docs/real-vs-mock.md after implementation:

    • add the completed pure, synchronous, deterministic, offline, fail-closed Decision Engine to Actually completed;
    • remove only the obsolete no Decision Engine and no decision logic statements;
    • retain the absence of STOP Fixture, UI, backend, RPC, wallet, signing, transaction, Moss/Monad integration, and real chain data;
    • contain no PR number, Draft state, review state, or other lifecycle wording.

    13. Future implementation verification

    Required environment:

    • Node 22, with the project constraint and expected local version checked explicitly
    • pnpm 11
    • public package-name import must succeed under Node 22

    The verification must start in a new isolated worktree with no node_modules and
    no dist directories. Record that precondition, then run exactly:

    node --version
    pnpm --version
    pnpm install --frozen-lockfile
    pnpm typecheck
    pnpm build
    pnpm test:package-import
    pnpm test
    pnpm check
    git diff --check origin/main...HEAD
    git status --short
    

    A standalone pnpm typecheck must pass immediately after frozen install because
    it builds report-schema before root tsc. pnpm build must then build
    report-schema before decision-engine. Both Node 22 public package-name smoke
    tests must pass after that build. pnpm check is the same entry used by GitHub
    Actions and must pass from the same clean-checkout state.

    The implementation PR must also obtain quality-gate SUCCESS for its exact current Head before Pre-PR QA or any Maintainer gate.

    14. Explicit non-goals

    • No UI or frontend.
    • No backend, orchestration adapter, or RPC.
    • No wallet, private key, API key, signing, or transaction behavior.
    • No mainnet or testnet transaction.
    • No Moss or Monad integration.
    • No Fixture, including no Issue M1-05: Add tokenOut mismatch STOP fixture #8 work.
    • No real address, real protocol data, or real-chain evidence.
    • No risk score or natural-language safety conclusion.
    • No report generator or presentation model.
    • No runtime Schema, ADR, STOP vocabulary, MANUAL_REVIEW, or evidence-ownership redesign.
    • No report-schema source or test change.
    • No docs/stop-presentation.md change.
    • No workflow, branch protection, required check, permission, Issue, Project, Milestone, or label change.
    • No new third-party dependency.
    • No prebuild, pretypecheck, prepare, postinstall, or other lifecycle script.
    • No committed dist, TypeScript private-source paths alias, or build step hidden in test code.
    • No Issue M1-05: Add tokenOut mismatch STOP fixture #8, M1-06: Document M1 evidence boundary and completion criteria #9, or M1-09: Add amountIn mismatch STOP fixture #20 implementation.
    • MANUAL_REVIEW does not mean safe, approved, authorized, guaranteed, signable, or executable.

    15. Risks, rollback, and requested Maintainer confirmation

    Risks to review before implementation:

    • Error classification could drift if source-reference failures are identified from unstable text instead of structured issue paths; this plan forbids message matching.
    • A code could borrow another code's evidence or omit one of several triggers; the per-code assembled-report matrix and all-trigger aggregation tests address this.
    • All-reason aggregation, UTF-8 sorting, or rank order could drift through traversal or declaration order; deterministic permutation tests address this.
    • Package exports could work in TypeScript but fail as a Node package from clean dist; the Node 22 package-name smoke test addresses this.
    • Root typecheck/build/test:package-import ordering and the new workspace importer require package.json and pnpm-lock.yaml changes; both need explicit approval, zero-dist verification, and frozen-install validation.
    • Documentation could overstate the offline Engine as an application, chain evidence, or safety capability, or record transient PR state; the two-file stable-fact boundary prevents that.
    • v0.1 cannot detect arbitrary non-empty partially omitted Receipt/Outcome sets; implementation and docs must retain the empty-only limitation.

    Rollback is limited to the Maintainer reverting the future #6 independent implementation commit or squash merge. Schema or ADR changes are not a compensating rollback mechanism.

    Maintainer scope confirmation is requested for:

    • the exact 14-file writable list;
    • the sole public API;
    • root package.json modification covering the explicit typecheck, build, and test:package-import clean-checkout ordering;
    • pnpm-lock.yaml workspace importer modification;
    • the 22-code trigger/reference table;
    • error classification and fixed precedence;
    • aggregation, UTF-8 ordering, and rank rules;
    • the full test matrix;
    • the minimal README.md and docs/real-vs-mock.md updates.

    Until that confirmation is recorded, no implementation branch, file, commit, or PR may be created.

    16. Planning outcome

    Requested status after this comment:

    WORK_PLAN_V2_SUBMITTED / AWAITING_MAINTAINER_SCOPE_CONFIRMATION
    

    This v2 comment requests a new Maintainer Scope Gate. It does not claim SCOPE_CONFIRMED or IMPLEMENTATION_AUTHORIZED, and it does not enter Maintainer Review, Merge Gate, or implementation. Qy stops Builder activity after publishing and returns this plan to the independent Maintainer window.

  7. pillowtalk-Qy commented on Aug 2, 2026

    @pillowtalk-Qy
    ContributorAuthor

    SCOPE_CONFIRMED / IMPLEMENTATION_AUTHORIZED

    Reviewed Work Plan v2:
    #6 (comment)

    Implementation authorized from main@7bbbc8bb9b4acb859bc73ba2b861f657864cce5c.

    Approved:

    • exact 14-file writable scope;
    • root package.json clean-checkout typecheck/build/test ordering;
    • pnpm-lock.yaml workspace importer/link only;
    • evaluateDecisionV0_1 and DecisionInputErrorV0_1 runtime API;
    • DecisionV0_1 and StopReasonCodeV0_1 type-only exports;
    • complete 22-code trigger/rank/reference matrix;
    • fixed input-error classification precedence;
    • complete public-boundary and deterministic test matrix;
    • minimal README.md and docs/real-vs-mock.md stable-fact updates.

    Writable paths, exactly:

    1. package.json
    2. pnpm-lock.yaml
    3. packages/decision-engine/package.json
    4. packages/decision-engine/tsconfig.build.json
    5. packages/decision-engine/src/index.ts
    6. packages/decision-engine/src/input-boundary.ts
    7. packages/decision-engine/src/evaluate.ts
    8. packages/decision-engine/test/synthetic.ts
    9. packages/decision-engine/test/input-boundary.test.ts
    10. packages/decision-engine/test/stop-reason-matrix.test.ts
    11. packages/decision-engine/test/evaluate.test.ts
    12. packages/decision-engine/test/public-entry.smoke.mjs
    13. README.md
    14. docs/real-vs-mock.md

    package.json approval is limited to: build report-schema before root typecheck; build report-schema then decision-engine; run both public-entry smoke tests; retain root-build-before-Vitest; keep check as the sole unchanged-stage quality-gate entry. No lifecycle script, workflow change, private-source path alias, test-hidden build, committed dist, or dependency change is authorized.

    pnpm-lock.yaml approval is limited to the new packages/decision-engine workspace importer and its workspace link to @moss-mini-demo/report-schema; no third-party package or unrelated lockfile change is authorized.

    ADR 0004 governs its corrections to ADR 0003.

    Any additional file, dependency, export, Schema/ADR change, workflow change, Fixture, product integration, or trust-boundary change requires a new Maintainer Scope Gate.

    This is implementation-scope authorization only. It is not QA PASS, GitHub Approval, READY_TO_MERGE, Merge Gate, or merge authorization.

  8. pillowtalk-Qy commented on Aug 3, 2026

    @pillowtalk-Qy
    ContributorAuthor

    POST_MERGE_GATE_BLOCKED

    The post-merge dependency-release audit stopped. The required merged-main gate has not occurred.

    Required condition not met: PR #66 must first receive its exact-head Maintainer Merge Gate, be squash merged, and produce a SUCCESS quality-gate on the resulting main commit. Until then, #8 and #20 are not released and #9 remains blocked.

    Control-plane result: #8, #20, and #9 remain Open / status:blocked / Project Blocked. No downstream assignee, claim, branch, worktree, implementation, Review, Merge Gate, or merge is authorized by this record.

  9. added a commit that references this issue on Aug 3, 2026
    aa7ea76
  10. pillowtalk-Qy commented on Aug 3, 2026

    @pillowtalk-Qy
    ContributorAuthor

    POST_MERGE_AUDIT

    PR #66 and Issue #6 are archived as Project Done. The merge used the exact-head squash endpoint. No auto-merge or admin bypass was used, and no protection or permission setting was changed.

    This audit completes Issue #6 only. It does not authorize or start #8, #20, or #9.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:architectureArchitecture and module boundariesarea:qaQuality assurance and testingpriority:P0Critical priorityrisk:trust-boundaryChanges a trust or evidence boundarytype:featureNew product functionality

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions