Address the verifier's residual on the macro-loss fix: the guard was raw-count
based, so a body that DROPPED the real Mermaid macro while ADDING an unrelated
macro (equal count) could slip through. Replace count_storage_macros in the
guard with storage_macro_signature (per-ac:name multiset) and refuse if ANY
macro identity loses occurrences. +2 tests.
Resolve the security-review BLOCKER and the confirmed authz/info findings on
the Confluence-writer node:
- BLOCKER (data-loss): _page_has_macros fail-OPENed (real ConfluenceClient has
no page_has_macros/ADF methods) so every live write fell through to a
wholesale storage-body PUT that drops Mermaid macros — the page-1540098
diagram-loss class. Add count_storage_macros + a real ConfluenceClient
.page_has_macros (storage-body detection); make _page_has_macros FAIL CLOSED;
and add _assert_macros_preserved as the final backstop: refuse any storage
write whose body carries fewer macros than the live page.
- AUTHZ-CONF-01: add an opt-in AGENT_TEAM_CONFLUENCE_ALLOWED_PAGE_IDS allowlist
enforced server-side before a live update (model-derived page_id).
- AUTHZ-CONF-02: stop silently picking the first accessible Confluence site;
require CONFLUENCE_CLOUD_ID when multiple resolve.
- INFO: 'applied' now fail-honest (defaults False, not True) on a missing attr.
+10 regression tests; full suite 1612 passed; ruff clean.
Apply review findings from mining PR #61/#63/#64 and the recent merged PRs:
- conf_draft_node: drop the agentic invoker config (max_turns=8 + Read/Grep/Glob
+ budget) that merged #61 reverted live (#60); use max_turns=4 tools-off like
the planner. The draft is a reasoning->JSON node — repo context is folded into
the prompt, never fetched via Claude tools (feedback_claude_sdk_single_shot).
Invert the test that pinned the old tools-on contract.
- confluence_writer: record the dedicated Phase.CONF_DRAFT/CONF_GATE/CONF_WRITE
values instead of borrowing VERIFY/REVIEW/BUILD, so the ledger/transitions/
dashboard show the real lane.
- invoker: note the allowed_tools seam is replicated from merged #61 (drop on a
future rebase; byte-equivalent default None->[]).
- dashboard: document that conf_* vertices need no _NODE_TO_STAGE remap (node id
== stage key, identity fallback resolves them).
Verified (no change needed): coordinator confluence gate shares the plan gate's
crash isolation (_emit never raises, ledger write fail-soft); confluence_* state
channels persist via declared PipelineState channels + checkpointer; Flow B edge
hooks VERIFY's approved terminus, orthogonal to #61's plan-gate-approve routing.
Full suite 1564 passed; ruff + format clean.