Skip to content

FE-747: Declarative output routing for branching transitions#154

Open
kostandinang wants to merge 5 commits into
ka/fe-745-petri-epic-verification-mergefrom
ka/fe-747-petri-declarative-routing
Open

FE-747: Declarative output routing for branching transitions#154
kostandinang wants to merge 5 commits into
ka/fe-745-petri-epic-verification-mergefrom
ka/fe-747-petri-declarative-routing

Conversation

@kostandinang
Copy link
Copy Markdown
Contributor

@kostandinang kostandinang commented May 25, 2026

Summary

  • Replaces inline report-field branching inside transition fire closures with declarative RouteGuard predicates on HandlerDescriptor (always, reportFieldTruthy).
  • Exposes evalRouteGuard and enumerateCandidateOutputs so topology can be analyzed without instantiating handlers or running agents.
  • Records analyzable output arcs as SPEC invariant I125-K, separating “what the net could do” from closure-only behavior.

Context

  • FE-745 made epic verification correct under parallel slice sandboxes. Phase 3/4 goals (reachability, deadlock simulation, stale-graph routing) need routing rules on arcs, not logic hidden inside fire implementations.
  • This change is intentionally usable without FE-700 graph UI: it makes guards data the compiler and tests can read today.
  • Halt paths and some token transforms remain in closures; I125-K documents what is declarative now vs follow-on work.

What changed

  • RouteGuard on HandlerDescriptor with shared evaluation on the runtime fire path and the static analyzer.
  • topology.test.ts: twelve tests covering guard evaluation and candidate output enumeration, pinned with literal-fixture goldens.
  • Fail-fast when an unsupported guard kind is encountered at runtime, avoiding silent mis-routing during cook.

Verification

  • Existing engine contract suite behavior preserved; new topology module tests added.
  • npm run verify green.

Out of scope

  • Moving halt paths and token transforms fully onto declarative guards (tracked as follow-ons under I125-K).
  • End-to-end stale-graph routing wired through FE-700 graph compilation.

Traceability

  • Requirements 46–48; decision D155-K; invariant I125-K; frontier petri-declarative-routing in memory/PLAN.md; umbrella H-6476.

Copy link
Copy Markdown
Contributor Author

kostandinang commented May 25, 2026

@kostandinang kostandinang changed the title FE-747: Add petri-declarative-routing frontier to plan. FE-747: Declarative output arcs — topology-level routing for branching transitions May 25, 2026
@kostandinang kostandinang marked this pull request as ready for review May 26, 2026 07:52
@cursor
Copy link
Copy Markdown

cursor Bot commented May 26, 2026

PR Summary

Low Risk
Refactor preserves dual-engine contract behavior via existing tests plus new topology tests; scope is orchestrator/compiler only with no auth or product API changes.

Overview
FE-747 moves Petri branching from inline fire-closure logic onto declarative RouteGuard data on HandlerDescriptor (always, reportFieldTruthy), with evalRouteGuard shared at runtime and enumerateCandidateOutputs for topology-only output-place sets—no actions, reports, or test runner.

compileTopology now emits guards on evaluate, write-tests/code, run-tests, and assess-semantic; wireHandlers routes via evalRouteGuard instead of ad hoc payload reads. Retry/rework budget exhaustion, epic verify failure, and token side effects stay in closures (documented as out of scope for I125-K).

topology.test.ts adds guard and enumeration coverage with golden place sets. memory/PLAN.md and memory/SPEC.md record petri-declarative-routing done and invariant I125-K, and reframe Phase 3/4 sequencing (declarative routing unblocks simulation structurally; graph compilation still needs FE-700).

Reviewed by Cursor Bugbot for commit 578e7c9. Bugbot is set up for automated code reviews on this repo. Configure here.

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

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

Review completed. 1 suggestion posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread src/orchestrator/src/net-blueprint.ts
@kostandinang kostandinang changed the base branch from ka/fe-745-petri-epic-verification-merge to graphite-base/154 May 26, 2026 08:21
@kostandinang kostandinang force-pushed the ka/fe-747-petri-declarative-routing branch from f9de408 to ee16289 Compare May 26, 2026 17:03
@kostandinang kostandinang changed the base branch from graphite-base/154 to ka/fe-745-petri-epic-verification-merge May 26, 2026 17:03
@kostandinang kostandinang force-pushed the ka/fe-747-petri-declarative-routing branch from ee16289 to eef2f05 Compare May 27, 2026 20:44
@kostandinang kostandinang changed the title FE-747: Declarative output arcs — topology-level routing for branching transitions FE-747: Declarative output routing for branching transitions May 27, 2026
kostandinang and others added 5 commits May 27, 2026 23:12
New TRACK F frontier between petri-epic-verification-merge (done) and
petri-graph-compilation (horizon, blocked on FE-700). Moves conditional
output routing from wireHandlers fire closures into typed Guard predicates
declared on HandlerDescriptor so a topology-only consumer can enumerate
reachable output places per transition without invoking actions, reports,
or the test runner — structural prerequisite for any static analysis
(simulation, reachability, deadlock detection) and FE-700-independent.

Retires the "Declarative output arcs" sub-bullet under petri-graph-compilation
since it's now its own frontier; keeps "Token state enrichment" there.

Co-Authored-By: Claude <noreply@anthropic.com>
Move conditional output routing from wireHandlers fire closures into typed
Guard predicates declared on HandlerDescriptor. ActionDescriptor gains a
required guard:Guard (replacing routeField); RunTestsDescriptor adds
passGuard; AssessSemanticDescriptor adds satisfiedGuard. wireHandlers
consumes them via a pure evalGuard(guard, report) helper.

Adds enumerateCandidateOutputs(transition) so static consumers can derive
the reachable output-place set per transition from topology alone, without
instantiating actions, reports, or the test runner. Halt paths (budget
exhaustion, verify-epic failure) and token transforms stay in fire closures
and remain follow-on slices.

New invariant I125-K. Engine contract suite unchanged (84 orchestrator
tests pass); npm run verify green.

Co-Authored-By: Claude <noreply@anthropic.com>
Disambiguates the typed routing predicate from TransitionContract.guard,
the pre-existing human-readable note string on the same record.
Pure rename across net-blueprint.ts (type + interpreter), net-compiler.ts
(consumer), and topology.test.ts. Descriptor field names (passGuard,
satisfiedGuard, ActionDescriptor.guard) keep their domain identifiers.
No behavior change; 84 orchestrator tests pass.

Co-Authored-By: Claude <noreply@anthropic.com>
The existing per-kind tests computed expected output sets from the same
descriptor fields the enumerator consumes, so they'd pass silently if both
the topology emitter and the enumerator dropped a branch in lockstep. Add
three goldens that pin literal expected place names for slice-1:evaluate,
slice-1:run-tests, and slice-1:assess-semantic against the simplePlan
fixture. Lockstep drift now surfaces immediately.

Retires memory/REFACTOR.md (FE-747 refactor pass complete).

Co-Authored-By: Claude <noreply@anthropic.com>
Unknown guard kinds now throw instead of falling through as false, so
deserialized or malformed routing data cannot silently misroute tokens.

Co-authored-by: Cursor <cursoragent@cursor.com>
@kostandinang kostandinang force-pushed the ka/fe-747-petri-declarative-routing branch from eef2f05 to 578e7c9 Compare May 27, 2026 21:16
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 578e7c9. Configure here.

for (const o of h.onPassOutputs) out.add(o.place);
return out;
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Missing default throw in enumerateCandidateOutputs switch

Medium Severity

enumerateCandidateOutputs lacks a default throw in its switch on h.kind, unlike the sibling evalRouteGuard function which explicitly throws on unsupported kinds. Since noImplicitReturns is not enabled in tsconfig.json, adding a new HandlerDescriptor variant without updating this function would silently return undefined (typed as Set<string>), causing a confusing runtime crash at the call site instead of a clear fail-fast error.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 578e7c9. Configure here.

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.

1 participant