Repository navigation
feat(runtime): derive operator-local graph readiness - #1446
Conversation
|
The authority boundary and sealed-activation model look good, but I found two identity blockers before this is safe to merge. [P1] Do not make every intent depend on the entire graph topology
I reproduced this with a That becomes a correctness problem once the next slice adds durable claims. If the original intent has already been claimed/executed, an ordinary supervisor Please keep the global topology fingerprint on the snapshot/supervisor view as provenance, but bind intent identity to an operator-local readiness context instead: the target operator/Session binding, its direct incoming edge identities, the normalized policy, and the trigger route/record identities. The existing route IDs already bind graph, edge endpoints, and source records, so an unrelated topology addition should leave an existing local intent byte-stable. Add a regression that adds a disconnected or downstream-only operator and asserts that existing local intents remain unchanged. [P1] Make the topology fingerprint actually canonical
Please use one locale-independent raw/code-unit total comparator for graph identities (or normalize and reject aliases at validation), audit the graph/readiness identity sorts, and add reversed-input regressions for distinct Unicode IDs that The focused 25-test suite, typecheck, and CI are green; these failures are in the identity contract rather than the current ASCII happy paths. |
|
Addressed both identity blockers in
Validation:
This feedback was posted as a top-level PR conversation comment, so GitHub does not expose a review-thread “Resolve conversation” action for it; the implementation and this response close the loop. 中文说明两个 identity blocker 都已在
验证结果:graph 聚焦测试 28/28、全仓 typecheck、Biome lint/format 与 这条反馈属于 PR 顶层 conversation comment,不是 review thread,因此 GitHub 没有可点击的 “Resolve conversation” 状态;代码与本回复已完成闭环。 |
Summary
This is the third implementation slice of #1341, building on the committed-event projection in #1442 and trace topology in #1443.
mappolicy that produces one stable candidate intent per direct incoming route.all_settledpolicy that waits for one exact activation from every direct upstream operator.Why the activation frontier is explicit
A Session-backed operator can have multiple session-inline AgentRun activations over time. An all-settled join over "the latest activation" would be unstable: a later follow-up in the same child Session could silently turn an already-runnable join back into waiting or change its trigger identity.
This slice therefore requires the join policy to seal one exact
operatorId / activationIdinput for every direct upstream. A later follow-up activation remains observable in the trace but cannot rewrite the already-derived join intent.All terminal outcomes settle an all-settled input: completed, failed, aborted, or cancelled. Failure policy remains a later operator/control-plane concern.
Authority boundary
A runnable intent is a deterministic candidate, not execution authority.
Recomputing this projection never creates, starts, resumes, sends to, pauses, or cancels an AgentRun. A later control-plane slice must durably and idempotently claim an intent before invoking existing child-session runtime APIs. That future claim will also provide consumption/acknowledgement and recovery semantics; this PR deliberately does not infer intent consumption from unrelated target Session activity.
Structural readiness also remains separate from resource admission. A runnable intent may still wait for concurrency, provider, budget, fairness, or workspace permits.
The main-agent supervisor is structurally beside the graph. It observes every waiting/runnable state and candidate intent through
supervisorView, but is not a serial gate in deriving or routing normal work.Identity boundary
The full topology fingerprint is graph-level provenance only. It intentionally does not participate in
intentId: adding a disconnected observer or a downstream-only operator cannot reissue historical local work under a new identity.Instead, each intent carries a
readinessContextFingerprintderived from the graph identity, target operator/Session binding, schema-defined direct incoming edges, and normalized policy fingerprint. Trigger route/record identities complete the candidate identity.Topology validation projects operators to
{ operatorId, sessionId }and edges to{ edgeId, fromOperatorId, toOperatorId }, so undeclared diagnostic/UI fields cannot affect identity. Projection, trace, topology, policy, and sealed-input ordering share a strict raw string comparator rather than locale-sensitive collation.Failure semantics
Readiness derivation fails closed for:
Deliberate non-goals
Validation
npm run typecheck/usr/localexecutable-root ordering assertionrgcannot load PCRE2 inside the operation-scoped Seatbelt sandboxgit diff --checkRefs #1341
中文说明
这是 #1341 的第三个实现切片,建立在 #1442 的 committed-event projection 与 #1443 的 trace topology 之上。
mappolicy 为每条 direct incoming route 生成一个稳定的 candidate intent。all_settledpolicy 等待每个 direct upstream 的一个精确 activation。é/e\u0301这类 locale-equivalent Unicode identity 时,仍能确定、幂等地重建。一个 Session-backed operator 可以持续产生多个 session-inline AgentRun activation。如果 all-settled 依赖“最新 activation”,同一 child Session 后续出现 follow-up run 时,已经 runnable 的 join 可能重新变回 waiting,或者触发 identity 被改写。
因此本切片要求 join policy 为每个 direct upstream 显式封口一个精确的
operatorId / activationId。后续 follow-up activation 仍会进入 trace,但不能改写已经推导出的 join intent。completed、failed、aborted、cancelled 都属于 settled;如何处理失败留给后续 operator/control-plane policy。全图 topology fingerprint 只负责 graph-level provenance,不再参与
intentId。增加 disconnected observer 或 downstream-only operator,不会把历史局部工作换一个 ID 后重新发放。每个 intent 改为携带
readinessContextFingerprint,其来源是 graph identity、目标 operator/Session binding、schema-defined direct incoming edges 与 normalized policy fingerprint;再结合 trigger route/record identity 构成完整 candidate identity。Topology validation 只保留 operator 的
{ operatorId, sessionId }与 edge 的{ edgeId, fromOperatorId, toOperatorId },因此未声明的调试/UI 字段不会污染 identity。Projection、trace、topology、policy 与 sealed input 排序统一使用 raw string comparator,不依赖 locale collation。Runnable intent 只是确定性的候选,不是执行权威。重新计算 projection 不会创建、启动、恢复、发消息、暂停或取消 AgentRun。后续 control-plane 切片必须先持久、幂等地 claim intent,再调用现有 child-session runtime API;consumption/acknowledgement 与 recovery 语义也由那一层建立。
结构 readiness 与资源 admission 继续分离。Intent 即使 runnable,也可能等待 concurrency、provider、budget、fairness 或 workspace permit。
主 Agent supervisor 始终站在图旁边,通过
supervisorView观察全部 waiting/runnable state 与 candidate intent,但不会成为正常 readiness 或 record routing 的串行门禁。本 PR 不执行任何 Agent runtime action,不引入 durable intent claim/ack、resource permits、quorum/early-exit、graph-wide completion/closing、supervisor control record 或 Desktop/TUI renderer。