feat(hooks): P55 kernel hook system slices A-D with slice C closure (scope B) - #34
Open
hellochica wants to merge 18 commits into
Open
feat(hooks): P55 kernel hook system slices A-D with slice C closure (scope B)#34hellochica wants to merge 18 commits into
hellochica wants to merge 18 commits into
Conversation
build.rs panicked with 'windres: program not found': the MinGW tool is gone from this machine and the MSVC-only toolchain decision leaves no reason to keep it. Route resource compilation through embed_resource (already a build-dependency), which locates Windows SDK rc.exe the same way tauri-winres does, and emit a plain rustc-link-arg so bins, tests, examples and benches all keep the comctl32 v6 manifest. icons/icon.rc becomes icons/manifest.rc carrying the manifest only: with the SDK present tauri-winres embeds the window icon (id 32512), and a second .rc holding an .ico collides on the internal RT_ICON entries rc.exe numbers from 1 (CVT1100 duplicate resource, observed). Ledger: docs Pylon-co-works issue AlchemistCxC#1. cargo build --release and bun run build:release (exit 0, twice) verified; pylon.exe carries RT_MANIFEST and the icon group.
D2 code surface ~90%: hook_bridge gains HOOK_PERMISSION_REQUEST / HOOK_INTERACTION_REQUEST anchors, permission_request_hook_outcome and interaction_request_hook_outcome seam dispatchers (fail-open to the legacy flow), dispatcher gains permission_post_normalize_flow / handle_interaction_request extraction with spawn-off hook tasks (main loop never awaits the bridge), AppStateHandles carries the bridge Arc, frontend HOOK_NAMES extends the two anchor names. tsc -b green. Remaining: 1-2 closure-ownership compile errors in dispatcher/mod.rs (handle_crash closure moving hook_bridge), D2 tests (auto-allow skip pending table, no-answer byte-identical regression, interaction respond/cancel), gates, then slices C/E/F. Not pushed yet (network down); resume point documented in spec §9.2.
Three repairs to the committed D1 slice, without which no Rust or boundary gate can run: 1. prompt.rs before_send_hook_transform test deadlocked the whole test binary: the responder task blocked on std mpsc recv and pinned the single-threaded current_thread runtime, so the ACP reader was never polled (session/new response never read) and even the RPC timeout timer could not fire. Convert the responder channel to a tokio unbounded_channel so recv actually awaits. 2. hookBridgeDispatcher fail-closed test used 'agent.chunk' as the out-of-vocabulary example, but D4 (7472b73) added that anchor to HOOK_NAMES; the premise is stale. Use a genuinely unknown name. 3. check-runtime-boundaries failed: the D1 bridge dispatcher performs direct invoke by design (same pattern as pylonCliBridge) but was never allowlisted. Register it with a P55-D1 comment. Gates after repair: cargo test --lib 914 passed / 0 failed / 4 ignored (first fully green run since D1 landed); dispatcher hooks suite 6/6.
P55-D2 (spec slice B). Kernel hook coverage for the two gating anchors:
- hook_bridge: HOOK_PERMISSION_REQUEST / HOOK_INTERACTION_REQUEST
constants, permission_request_hook_outcome and
interaction_request_hook_outcome seam dispatchers with fail-open
mapping back to the legacy flow. Permission envelope per contract
10.2 ({provider, agentId, requestId, payload{title,prompt,options}});
interaction receives the raw JSON-RPC envelope per 10.3.
- dispatcher: permission.request hook inserted before the bypass/auto
mode check (hooks must see auto-mode requests); allow/deny pick the
allow/deny-semantic option and answer via send_agent_response without
entering the pending table - the hook answer IS the permission
answer, no second pending map. Legacy flow extracted unchanged into
permission_post_normalize_flow for the continue/no-answer fallback.
interaction.request hook runs before the legacy reject: respond
writes the result with the original request id, cancel maps to a
JSON-RPC -32600 error, continue keeps the byte-identical reject.
Both seams spawn off the hook task; the dispatcher main loop never
awaits the bridge (B1).
- AppStateHandles carries the hook_bridge Arc (dispatcher + crash
closure paths); frontend HOOK_NAMES extends permission.request /
interaction.request.
- E0283 in trigger-depth test fixed by typing the None emitter.
- Remaining spawned responders converted from blocking std mpsc recv to
tokio unbounded channels (same deadlock class as the D1 repair).
- 8 dispatcher d2_hooks tests: allow/deny skip the pending table,
continue falls back byte-identically, zero registration takes the
direct legacy path, interaction respond/cancel/continue, missing id
never reaches the bridge. Verified via python trace-agent roundtrip.
Spec: docs Pylon-co-works P55 slice B (D2). Full gates: cargo test --lib
914/0/4; vitest plugin-runtime 286, hooks 6, application+workbench 491;
tsc 0; eslint 0; check:boundaries green.
…xits P55 slice C (D3) part 1: turn.cancelled event chain. - error.rs: add PylonError::PromptCancelled structured variant so stop reason cancelled no longer hides inside Protocol prose. - prompt.rs: PromptFailureMetadata gains outcome (Failed/Cancelled); exit 1 (finalize_response stopReason=cancelled) raises PromptCancelled, exit 2 (CancelledAfterTimeout) marks failure Cancelled; publish_prompt_failure commits sessionUpdate:cancelled instead of error when outcome is Cancelled (SESSION_ERROR frame and channel terminal unchanged). - event_repo.rs: normalize sessionUpdate:cancelled -> turn.cancelled; code/error extracted for cancelled like error (diagnostics parity). - frontend: eventSchema CANONICAL_EVENT_TYPES gains turn.cancelled; canonicalTurnDuration treats cancelled as terminal (3-state); canonicalNormalizer maps wire cancelled -> turn.cancelled. Tests: event_repo cancelled normalization; prompt exit-1 cross-layer (fake ACP stopReason=cancelled -> journal turn.cancelled row); failure metadata outcome serialization; frontend duration/terminal + normalizer table. Gate: cargo lib 916/0/4, events 98, workbench/hooks/app 783, tsc 0, lint 0 errors, boundaries green.
Slice C round 2 (D3-2/3/4): wire kernel observe anchors fire-and-forget. - hook_bridge: six anchor consts (turn.completed/failed/cancelled, tool.beforeCall/afterCall/failed) + dispatch_observe helper (result discarded; callers spawn, B1 keeps dispatcher main loop await-free) - prompt.rs: turn.completed spawned after done journal row in finalize_response; turn.failed/turn.cancelled spawned from publish_prompt_failure keyed on the same outcome discriminator as the journal row (mutually exclusive, no double dispatch); profile sessions only, matching journal persistence semantics - dispatcher: tool_call -> tool.beforeCall + startedAt memory record; tool_call_update completed/failed -> tool.afterCall/tool.failed with startedAtMs+elapsedMs payload (D3-4); replay events skipped (C11) - dispatcher: RunningSegment/segment_seal_signal/segment_advance - message.sealed segment boundary state machine (D3-3), pure functions with four-signal unit tests; wire wiring deferred pending frontend HOOK_NAMES adjudication (message.sealed absent from the vocabulary, see ledger upgrade entry) - tests: 10 new (2 turn observe cross-layer in prompt.rs, 3 tool observe + 1 slow-hook backpressure + 5 segment-state in dispatcher) Gates: cargo lib 926/0/4, vitest six domains 881, tsc 0, lint 0 errors, check:boundaries green.
…contact onward)
This was referenced Sep 9, 2026
Owner
冲突分析结论:需 rebase 重做(不直接合并)经完整三方分析(main / Chica/p55 / merge-base f679f81),本 PR 不能直接合并——不是普通文件冲突,而是架构代差: 根本问题:分支落后 main 260 commits,基于 P60 改造前的旧 ACP 架构
P55 的功能增量(observe spawn 派发、tool.afterCall 耗时载荷、段状态机契约件)全部写在旧 ACP 骨架(write_tx / channel bridge)上,而 main 已整体切换 SDK 引擎。强行解冲突 = 产出引用已删模块的代码,cargo 无法编译。 语义裁决(用户拍板 2026-09-10):canonical 保持单终态失败族冲突中最关键的语义分歧已裁决——cancelled → turn.failed + stopReason=cancelled(main/P60 方向),不引入第二终态 turn.cancelled:
建议路线(主任 21:40 板报选项①,现为唯一可行项)以最新 main 为基底 cherry-pick / 重写 P55 增量,产出干净 PR:
已确认可保留的设计(避免重做时返工)
关联:台账 #6(三选项分析)已登记同结论。此 PR 保持 open 标记 needs-rebase,由后续移植 PR 承接。 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
P55 kernel hook system — slices A/B/C/D complete, slice C closed under scope B (core hook embedding done; E/F deferred to a follow-up task, per user decision 2026-09-09).
Branch:
Chica/p55(based onChica/dev, forkhellochica/Pylon-co-works). Build-resource files (build.rs,icons/manifest.rc) are content-identical to this repo'smain(merged via #33); their appearance in the three-dot diff is relative to the merge-base only and introduces no conflict.Delivered (vs
main)turn.completed/failed/cancelled+tool.beforeCall/afterCall/failedobserve dispatch (payloads carrystartedAtMs/elapsedMs), replay guarded (C11);RunningSegmentsegment-state machine kept as a contract-ready artifact (unit-tested)dangerousHooks+ trigger (depth-2 hard reject)message.sealed/agent.status/context.thresholddeferred by user decision (kept out of HOOK_NAMES vocabulary, same precedent as feat(gateway): [I12-A-BE-01] 冻结 adapter catalog/instance/route domain contract #14). The sealed-segment decision logic remains in-tree, unit-pinned, ready to wire without re-research.turn.cancelledtri-state; HOOK_NAMES extended for turn/tool anchors.Gates
cargo test --lib: 926 passed / 0 failed / 4 ignored (baseline 916 + 10 new; 3 transient wire-matrix flakes observed once in parallel mode — serial rerun 4/4 pass, second parallel run full green)tsc0 errors;lint0 errors;check:boundariesgreenFollow-ups (out of scope for this PR)
Notes for reviewers
dispatcher/mod.rsRunningSegment doc comment carries the final deferred-anchor decision and the future wiring path.