Round: round-001 plan.md system-analysis review
Subject: architect · Griller: griller · Orchestrator: butler
Topic: specs/plans/001-cli-bootstrap-and-config/plan.md
Cap: 6 questions (completed 6/6, early conclusion allowed)
Both agents bootstrapped via SESSION-BOOTSTRAP.md (Steps 1–8) before the round
Issue: gosharplite/tellme#2
Round 001 (001-cli-bootstrap-and-config) is the first iteration of tellme — a discipline-first re-creation of tell-me-go under the AIxBDD pipeline (README.md → "Workflow Roadmap"). Per STATUS.md ("Scope (narrow foundation, locked)"), it is deliberately narrow: CLI boot; YAML configuration load + validation; runtime home (TELL_ME_HOME) + per-mode workspace (output/<mode>/); build version (--version); offline setup diagnostic (-d / -d --json) — explicitly no provider calls, tools, MCP, memory, TUI, or history persistence. This is the reusable scaffolding every later slice stands on, which is why it is scoped as a foundation and not as user-visible product behaviour (research.md, residual risk ⟦grill R1⟧: "No net-new user value this round").
plan.md is the system-analysis artifact (AnalysisPlan in aixbdd.modelith.md) for that round. The specific problem it solves is orchestration, not design: the analysis-plan-never-writes-truth invariant means it must (i) inventory the system interfaces implied by the requirements, (ii) order them into dependency-respecting Waves, and (iii) delegate each interface to the right planner — while writing no specs/truth/** itself. Verified against the repo: specs/truth/ currently holds only techstack.md (no data/**, no features/**), and the repo root has no Go code yet — plan.md is the forward-looking bridge that turns the ratified research.md decisions + spec.md requirements into a delegation schedule.
plan.md → "System interface inventory" identifies 2 system interfaces, each with the three mandatory fields (endpoint type / primary interface / requirement evidence) required by 系統介面盤點與端點歸類判準.md Rule 2:
CLI end (operator terminal interface)— endpoint typeCLI / terminal endpoint; primary interface = invocation + flags (-c/--config,-d,--json,--version), the exit-code taxonomy (success / usage / configuration / environment + the dedicated "diagnostic: unresolved" code), stdout/stderr/stdin, and console output; evidence =FR-001–FR-015,NFR-003/NFR-004, and the four named acceptance features.Configuration & workspace persistence interface— endpoint typelocal-file / state endpoint; primary interface = the config input contract ($TELL_ME_HOME/configs/<mode>.yaml:MODE,PERSON,SELECTED_PROVIDER,PROVIDERS+TELL_ME_*precedence) and the workspace/state lifecycle (output/<mode>/); evidence =FR-002/003/005/006/007/008/009/015,NFR-001/NFR-002,spec.mdAssumptions.
Two waves. Wave 1 = persistence → delegated by /axb-system-analysis to /axb-data-plan (minimal specs/truth/data/**). Wave 2 = CLI end → produced by the next pipeline phase, /axb-dsl-refine (specs/truth/features/** + dsl.md). Delegation order: /axb-data-plan first, then /axb-dsl-refine. /axb-api-plan = NOOP (single CLI end, no OpenAPI/HTTP surface); /axb-ui-plan skipped (CLI). The plan also correctly omits contracts/** from its document structure with an explicit note tying the omission to the NOOP ruling.
Interface count & boundaries. Count is 2, and the split is justified by analysis responsibility (分析介面委派與planner對應判準.md Rule 2: entity/field/lifecycle/storage → data-plan; visible operator flow/streams/exit codes → the CLI-contract planner), not by technology keywords. Rule 3 (independent responsibility boundary ⇒ separate interface) holds: interface 2's responsibility (the persisted-shape model) is disjoint from interface 1's (observable behaviour). I will state honestly a terminological seam the griller should note: these are delegation units (the axb-system-analysis notion of "系統介面"), not the domain-model Interface truth nodes. Only interface 1 materialises as a truth-tree Interface (under specs/truth/features/{interface}/{module}/); interface 2 materialises as a DataModel, not an Interface. AnalysisPlan/Wave impose no equality between the two counts, so this is not a contradiction — but the Interface.kind enum is {backend, frontend} only, and "CLI end" fits neither cleanly; the plan leaves the concrete interface name/kind to /axb-dsl-refine (same posture as it delegating module subpaths). That is a forward risk to flag, not a round-001 blocker.
Wave 1 → Wave 2 ordering. Wave依賴排序與平行分組判準.md Rule 1 requires later waves to depend on earlier output. Both interfaces touch the same two surfaces — the config file (configs/<mode>.yaml keys) and the workspace path (output/<mode>/). Settling the data model first prevents /axb-dsl-refine from inventing key/field names the data truth later contradicts. I will not overstate this: it is a semantic/design-order dependency over shared artifact surfaces, not a compile-time import (dsl-refine does not consume the DBML). It is nonetheless the correct order, because the CLI contract's file/stream/workspace behaviour is expressed against that model. Rule 4 also holds: plan.md stays at the "which interfaces, why this order, what each wave focuses on" granularity and does not pre-write API fields or table schemas.
Persistence is a genuine system interface. It satisfies 系統介面盤點與端點歸類判準.md Rule 1 (derived from named requirement parts, not a presupposed "there is always a database" list): FR-006–FR-009 define home/workspace resolution and lifecycle, and FR-002/003/005/015 define the config input contract. Its truth-bearing status was ratified by clarify Q2 → Option 1 (research.md → "Clarify round"): the "no data/** truth" lock was released, and the AIxBDD CLI rule (aixbdd-tmg/README.md) triggers /axb-data-plan for a CLI managing persistent config + system-owned state — consistent with data-model-covers-all-state ("every kind of system state, persisted and in-memory alike"). plan.md's scope note records this release explicitly.
NOOP / skip decisions. /axb-api-plan's owned truth is Contract = OpenAPI 3.0 (specs/truth/contracts/**; axb-api-plan → templates/openapi.yaml). A single CLI end has no HTTP operations/schemas, so there is nothing for a Contract to describe; the CLI's executable contract is carried instead by interface Gherkin + DSL (dsl-refine). Hence NOOP — and plan.md correctly treats it as "to be confirmed by the owner", since delta-covers-all-owners requires /axb-api-plan itself to record a NOOP DeltaEntry (truth-delta currently shows it PENDING). /axb-ui-plan is skipped because UIPlan/Prototype is 1:0..1 and produces HTML screens a terminal cannot render; the CLI-streamlined workflow skips it by design.
Structure & source-tree consistency. The document structure names the exact four acceptance files present on disk (starting-with-a-configuration, runtime-home-and-session-workspace, version-and-setup-diagnostic, unsupported-cli-usage — verified) and the truth paths specs/truth/{techstack.md, data/*.dbml, features/<interface>/<module>/}. The source tree — cmd/tellme/main.go with the single var version -X main.version target, internal/{cli,config,home}, tests/e2e/, Makefile, go.mod/go.sum — matches research.md Decision 1 (layout), Decision 4 (harness at tests/e2e/), Decision 6 (version injection), and the techstack.md Makefile targets (fmt/tidy/build/test/verify). The "Structure Decision" paragraph (single CLI end; Go 1.26 github.com/gosharplite/tellme; no web UI / HTTP-OpenAPI server) agrees with spec.md's out-of-scope list and techstack.md.
One honest spec-drift I flag up front. spec.md still carries three stale sentences from the released lock — the Input line ("slice-local input, not a system truth artifact"), the Assumptions line ("this round adds no contracts/** and no data/** truth"), and the Key-Entities note on Configuration. These contradict clarify Q2, but spec.md is PM-owned (spec-pm-authored) and plan.md may not edit it; both research.md ("PM follow-ups remain") and STATUS.md already record "update spec.md Assumptions — the data-scope lock is released" as a pending PM follow-up. So plan.md is consistent with the ratified ruling; the stale spec text is an acknowledged, tracked PM-side follow-up, not a plan defect.
Q1: You state (opening, §c) that interface 1 “materialises as a truth-tree Interface (under specs/truth/features/{interface}/{module}/)”, and you dismiss the Interface.kind mismatch as “a forward risk to flag, not a round-001 blocker.” I checked the model, and the risk is sharper than you framed it. In aixbdd-tmg/domain-model/aixbdd.modelith.md, InterfaceKind has exactly two values — backend → “executable truth lives under features/backend/**” and frontend → “executable truth lives under features/frontend/**” — and Interface is defined as “structuring the executable truth under specs/truth/features/{interface}/”. axb-dsl-refine’s own SKILL description confirms it writes specs/truth/features/backend/** and specs/truth/features/frontend/**. Your plan’s Wave 2 routes the CLI end to specs/truth/features/** + dsl.md — but there is no sanctioned kind, and no sanctioned subpath, for a CLI end: a terminal endpoint is neither an API boundary nor a web-UI boundary. That means it is not only interface 2 (which you correctly identified as a DataModel, not an Interface) that lacks a truth home — interface 1, the primary interface, also has no valid Interface.kind to materialise under. So when you say “only interface 1 materialises as a truth-tree Interface,” you have not shown which truth node it is; you have deferred its identity to /axb-dsl-refine while simultaneously relying on it to satisfy wave-covers-interfaces.
My recommended answer: this is a present defect in plan.md, not a forward risk, and it should be recorded as such. An AnalysisPlan’s whole purpose is to bound each interface and enable the downstream owner; if interface 1’s truth identity (name and valid kind) is undecidable from the current truth model, then the plan has not bounded the interface it delegates, and /axb-dsl-refine will either invent an out-of-enum subpath (e.g. features/cli/**) — silently extending the domain model from a downstream phase — or mis-file CLI features under backend. Either way the plan should state explicitly which resolution it expects and flag the InterfaceKind gap as a blocking cross-repo question (escalate to the truth-model/aixbdd-tmg owner), rather than “leave it to dsl-refine.”
Do you retract the “forward risk, not a blocker” characterisation — and if so, which resolution do you commit the plan to: (a) declare the CLI half of the truth tree as a new/explicit interface name with a kind the model doesn’t yet define (recording the enum extension as a blocker), or (b) some other concrete truth home — and if not, state which valid Interface.kind interface 1 materialises under?
Retraction first: I retract the "forward risk to flag, not a round-001 blocker" characterisation. The griller is right, and I verified every leg of the argument against the model and the skills.
Verified. aixbdd.modelith.md → InterfaceKind is a closed enum of exactly two values: backend ("The API boundary — executable truth lives under features/backend/**") and frontend ("The web UI boundary — … under features/frontend/**"). The Interface entity is "structuring the executable truth under specs/truth/features/{interface}/", with kind typed InterfaceKind. So the interface directory and its kind are one and the same closed set: {backend, frontend}, both bound to web/HTTP semantics. And axb-dsl-refine's SKILL front-matter is explicit — it updates "specs/truth/features/backend/**、specs/truth/features/frontend/**" (its Phase 1.2 says "辨識本次涉及的前端、後端或其他系統介面…"). 介面功能模組與DSL唯一歸屬判準.md Rule 1 ("{介面} 是 backend、frontend 等介面根") is the only place offering "等/etc." — but that "等" is unbacked by the typed model: kind is closed, so the "etc." cannot be instantiated. Conclusion holds: a terminal endpoint is neither a valid backend (API boundary) nor a valid frontend (web-UI boundary), so interface 1 has no sanctioned Interface.kind and no sanctioned subpath. My opening sentence — "only interface 1 materialises as a truth-tree Interface" — asserted that it materialises while never naming which node (name and kind) and never showing a valid kind exists. That is a present under-specification, not a deferred one. Retracted.
The one distinction I keep (an accuracy point, not a defence of the original claim). plan.md conforms correctly to the axb-system-analysis layer, which is a different type system from the truth tree. That skill's own template (系統介面盤點與端點歸類判準.md, Rule 2) says endpoint type covers "前端、後端、資料庫、第三方、手機端、硬體端、雲端或其他哪一類端點" — it explicitly sanctions "other", so CLI / terminal endpoint is a valid endpoint type at the analysis layer, and plan.md satisfies its own skill's contract on that point. The defect is therefore precise and singular: plan.md does not bridge its analysis-layer endpoint type to a truth-tree Interface.kind, and cannot, because the target enum has no CLI value. So this is a missing bridge the plan must state, not non-conformance with axb-system-analysis. I concede the substantive point — the missing bridge is a present gap — while keeping that scope boundary honest.
Which resolution I commit the plan to: (a), with an explicit deterministic fallback. Two parts, both to be written into plan.md (and surfaced via truth-delta.md / STATUS.md as a cross-repo blocker):
-
Primary — declare interface 1's truth identity explicitly and escalate the enum gap as a blocker.
plan.mdmust state that the CLI end materialises as an explicitly-named interface rootspecs/truth/features/cli/**with interface identitycli, whosekindthe currentInterfaceKinddoes not define. Becauseaixbdd-tmgis the reference/methodology owner andtellmecannot unilaterally extend another repo's domain model (nor may/axb-system-analysiswrite truth —analysis-plan-never-writes-truth), this is recorded as a blocking cross-repo question for the truth-model owner (InterfaceKind += cli→features/cli/**). Critically, Wave 2 (/axb-dsl-refine) must not run until it is resolved, because — as the griller notes, and as the SKILL front-matter confirms — dsl-refine is instructed to write only underbackend/frontend, so left unresolved it will either mis-file CLI features underbackendby default or inventfeatures/cli/**, silently extending the domain model from a downstream phase. Either outcome is exactly the "unbounded interface" failure the plan exists to prevent. -
Fallback — a named, justified interim home so dsl-refine has exactly one deterministic target even if the owner declines a
clikind. If the truth-model owner rules against extendingInterfaceKind, the plan commits interface 1 to thefrontendroot (specs/truth/features/frontend/**) with an explicit recorded rationale: the CLI end is the human/operator-facing end, which is the analogue offrontend; nothing in its contract (inbound operator flags, streams, exit codes) is an HTTP/APIbackend. I deliberately do not fall back tobackend(that is the silent mis-file the griller warns against) and I do not leave the root blank. This choice, and the enum-gap blocker, get recorded as a decision — not left implicit — so/axb-dsl-refineis never in the position of guessing.
So: the "forward risk, not a blocker" gloss is withdrawn; the plan commits to (a) (explicit cli interface name + InterfaceKind-extension blocker escalated to aixbdd-tmg), with frontend as the named, justified fallback, and Wave 2 gated on that ruling.
Q2: Your Wave-1/Wave-2 split asserts a dependency. plan.md's Wave 1 rationale is "the persisted-state model is the shape the executable CLI contract references, so it is settled first," and Wave 2's is "the CLI contract's file / stream / workspace behavior is expressed against the model settled in Wave 1, so it follows." But Wave依賴排序與平行分組判準.md Rule 2 is explicit: two interfaces go in the same wave when their analyses "don't need to wait for the other to produce concrete conclusions," and only go in separate waves when one "must first know the other interface's analysis result." So by splitting them, the plan is asserting that Wave 2 needs something Wave 1 produces. I checked, and I can't find what that something is. The shared surfaces you name are already pinned upstream: the config keys are fixed by spec.md FR-005 ("MODE, PERSON, SELECTED_PROVIDER, and a PROVIDERS registry"); the TELL_ME_* precedence is fixed by FR-003/FR-015; the output/<mode>/ derivation is fixed by FR-007; and the resolution order itself is fixed by research.md Decision 3's 6-step resolver. Both waves read those same sources, so the CLI contract's resolver/Gherkin can be written without ever consulting specs/truth/data/**. Your own defense concedes this: "it is a semantic/design-order dependency over shared artifact surfaces, not a compile-time import (dsl-refine does not consume the DBML)." A stated "semantic" dependency that consumes no artifact is not the information-supply dependency Rule 1 requires.
My recommended answer: name the specific datum Wave 2 consumes from Wave 1's output that is not already fixed by spec.md/research.md. I believe exactly one candidate survives — the provider-entry field schema (PROVIDERS.<name>.{TYPE, MODEL, URL, API_KEY, …}), which FR-005 mentions only as "a single provider" and never pins, so dsl-refine's Gherkin for the registry could otherwise guess it and drift from the data truth. If that is the real dependency, the plan must say so specifically (not "the shape the CLI contract references"). If it is not — i.e. if the data model merely re-represents what spec.md already fixes — then the two interfaces are information-independent, and per Wave Rule 2 they belong in a single parallel wave; the current 2-wave structure would then be unjustified and should collapse. Which is it: name the datum, or concede the wave split is unjustified?
Concede.** The griller is right, and I verified it: there is no information-supply dependency from Wave 1 to Wave 2. I retract the Wave-1/Wave-2 split as an analysis ordering.
The decisive evidence is /axb-dsl-refine's own READ contract. Its Phase 1 READ list — "目標 plan package 的 features/acceptance/**、plan.md、truth-delta.md、specs/truth/techstack.md、相關 UI plan,以及受影響介面的既有功能模組、feature、模組 DSL 與介面根共用 DSL" — does not include specs/truth/data/**. The skill that produces Wave 2's output reads nothing from Wave 1's output. Symmetrically, /axb-data-plan reads spec.md/research.md/plan.md, not the CLI contract. So by Wave依賴排序與平行分組判準.md Rule 2 — same wave when neither "needs to wait for the other to produce concrete conclusions" — the two interfaces are information-independent and belong in a single parallel wave. My earlier gloss ("semantic/design-order dependency over shared artifact surfaces, not a compile-time import") was exactly the hand-wave Rule 1 does not accept: a dependency that consumes no artifact, in a direction the consuming skill never reads, is not a dependency. Retracted.
The griller's candidate datum does not survive either — I checked it, not just accepted it. The proposed survivor was the provider-entry field schema (PROVIDERS.<name>.{TYPE, MODEL, URL, API_KEY, …}). It fails on the consumption side, twice over:
/axb-dsl-refinenever readsspecs/truth/data/**(above), so whatever Wave 1 declares about entry fields, Wave 2 cannot consume it by construction.- No round-001 step inspects entry fields. The acceptance rule is membership only —
starting-with-a-configuration.feature: "a configuration … whose selected provider 'deepseek-flash' is in its provider registry", and the empty-registry edge case inspec.md.FR-003validatesSELECTED_PROVIDER ∈ keys(PROVIDERS);FR-005requires only "aPROVIDERSregistry that starts with a single provider." The-dcontract (research.mdDecision 2) reports resolution status + category, not provider details. Nothing in Wave 2's contract dereferences an entry's inner fields.
So the schema is genuinely unpinned upstream and genuinely unread downstream — unpinned is not the same as consumed. It is not the datum; there is no datum.
What actually survives, and the correction to plan.md. The two interfaces both read the same upstream sources — spec.md FR-003/005/007/015 and research.md Decision 3 (the 6-step resolver) — so both waves are downstream of identical, already-fixed inputs. Per Rule 2 the fix is to collapse to a single Wave containing both interfaces (CLI end and Configuration & workspace persistence interface) as parallel analysis, and to drop the false sentence "the persisted-state model is the shape the executable CLI contract references." I also separate two concepts the current plan conflates: the analysis-wave grouping (Rule 2 — now one wave) versus the delegation/pipeline order. The delegations remain /axb-data-plan then /axb-dsl-refine, but the order is the CLI-streamlined pipeline's phase sequence (aixbdd-tmg/README.md: system-analysis + /axb-data-plan, then the next phase /axb-dsl-refine produces the executable contract) — not a Rule-2 information dependency, and it must be stated as phase order, not as "Wave 2 depends on Wave 1." wave-covers-interfaces still holds (both interfaces delegated); wave-dependency-ordered is trivially satisfied by one wave.
One honest footnote (which does not rescue the split). A latent coupling exists: if a future data model makes provider-entry fields required and the CLI validates them, then Wave 2's fixtures/validation would have to match Wave 1. But round-001 requirements do not activate it — no entry-field is required or asserted — so it cannot justify sequencing now. If a later slice activates it, that is a new round with its own analysis (and its own data-truth delta), not a reason to keep two waves today. So: the split is unjustified; it collapses to a single parallel wave, and the delegation order is re-attributed to pipeline phasing rather than an analysis dependency.
Q3: You closed Q2 with the assertion that "wave-covers-interfaces still holds (both interfaces delegated)." I don't think that holds as written, and I want the sanction or a retraction. The domain model states the invariant precisely: "wave-covers-interfaces — Every interface identified by an AnalysisPlan is delegated to a planner in at least one Wave." "Planner" is not free vocabulary here: axb-system-analysis's SOP Phase 4 enumerates exactly three — "將 API 介面交給 /axb-api-plan、資料介面交給 /axb-data-plan、UI 介面交給 /axb-ui-plan" — and the domains are disjoint (API contract → api-plan; entity/field/lifecycle/storage → data-plan; visible flow/state/error feedback → ui-plan). Your plan puts interface 2 → /axb-data-plan (a planner ✓) but interface 1 → /axb-dsl-refine. axb-dsl-refine is not one of those three planners; it is the next pipeline phase (aixbdd-tmg/README.md: "/axb-system-analysis … → /axb-dsl-refine"), and you yourself called it "the next phase … not by a /axb-system-analysis planner." /axb-api-plan is NOOP and /axb-ui-plan is skipped, so interface 1 is delegated to no planner at all. So "both interfaces delegated" is true only if "delegated" silently means "delegated to something," which is not what the invariant says.
My recommended answer: retract "wave-covers-interfaces holds," or cite the rule that makes /axb-dsl-refine a planner. My read of the sources is that the invariant is genuinely not satisfied for the CLI end under the strict wording, and that this is the same root cause as Q1 — the CLI end is an artifact of the analysis plan's own loose "系統介面" notion, not a member of the typed model either as a truth node (InterfaceKind has no CLI value) or as a planner-delegated unit (neither api/data/ui planner takes it). There is an intended CLI adaptation — aixbdd-tmg/README.md's "CLI Contract via /axb-dsl-refine" — but that rule designates a phase/truth-owner, and it lives in the README, not in 分析介面委派與planner對應判準.md or templates/plan.md. So the honest correction is one of: (a) state it explicitly — "the CLI end's contract owner is /axb-dsl-refine per the CLI-streamlined rule, not an api/data/ui planner" — and record that the plan is extending the invariant's scope (the same class of cross-repo note as Q1's InterfaceKind blocker); or (b) if you won't extend it, retract the claim and mark interface 1 as having no planner. Which do you commit to — and if (a), where in the rules the skill actually loads is /axb-dsl-refine authorised as a planner for wave-covers-interfaces?
Retract.** The griller is right: wave-covers-interfaces does not hold as I wrote it, and I verified the griller's chain against the repo rather than defending the claim.
The decisive evidence is in the skill's own reporting line. axb-system-analysis/SKILL.md:36: "WRITE 向使用者回報 plan.md、系統介面數量、Wave 數量、委派到哪些 planner,以及是否可進入 /axb-dsl-refine 或 /axb-tasks." The skill lists "the planners you delegated to" and "whether you can enter /axb-dsl-refine" as two separate things — /axb-dsl-refine is the next phase to enter, not a member of "委派到哪些 planner". And SKILL.md:29 ("確認每個介面至少被一個後續 planner 承接") uses the same "planner" vocabulary, whose set is fixed three ways by 分析介面委派與planner對應判準.md Rule 2 (API→api-plan, entity/field/lifecycle/storage→data-plan, visible flow/state→ui-plan). So interface 2 → /axb-data-plan is a planner delegation ✓, but interface 1 → /axb-dsl-refine is not: api-plan is NOOP, ui-plan is skipped, and nothing else is a planner. Interface 1 is delegated to no planner. Under the invariant's strict wording ("delegated to a planner in at least one Wave") it is unmet. Retracted.
Direct answer to the sub-question — "where in the rules the skill actually loads is /axb-dsl-refine authorised as a planner?": nowhere. I grepped the loaded rule set (skills/axb-system-analysis/): the three rules the skill loads — 系統介面盤點與端點歸類判準.md, Wave依賴排序與平行分組判準.md, 分析介面委派與planner對應判準.md — never mention dsl-refine. The only occurrence in the whole skill directory is SKILL.md:36, and it is the "是否可進入" (next-phase) line, deliberately separated from the planner report. The only source that names it is aixbdd-tmg/README.md → "Developing CLI Applications" §3 ("CLI Contract via /axb-dsl-refine"), which is not loaded by the skill, and which itself lists /axb-data-plan as the sole conditional planner and /axb-dsl-refine as a separate phase (README workflow: "5. /axb-system-analysis — orchestrates /axb-api-plan, /axb-data-plan…; 6. /axb-dsl-refine — split acceptance criteria…"). So (a) as literally worded — "cite the rule that makes dsl-refine a planner" — fails: there is no such loaded rule. I cannot cite a sanction that isn't there.
What I commit to, given (a) cannot be cited. I do not take (b) ("mark interface 1 as having no planner") as a shippable end state — that is a knowing invariant violation. Instead:
- Retract the "holds" claim outright and stop claiming
wave-covers-interfacesis satisfied. - Record it as a present, cross-repo blocker — the same class as Q1's
InterfaceKindgap, and in fact the same root cause: the CLI end is an artifact of the analysis plan's loose "系統介面" notion (the skill's Rule 2 explicitly allows "其他哪一類端點") and has a seat in neither typed structure — not as a truth node (InterfaceKind ∈ {backend, frontend}, no CLI value) and not as a planner-delegated unit (api/data/ui disjoint, none takes a terminal endpoint).plan.mdmust state this explicitly: "interface 1's contract owner is/axb-dsl-refineper the CLI-streamlined rule, not an api/data/ui planner;wave-covers-interfacesis therefore not met for the CLI end under the invariant's strict wording — a methodology gap escalated to theaixbdd-tmgowner (widen 'planner' to include the CLI-contract owner for CLI ends, or amend the invariant's wording to bind only the planner-delegable subset)." - Commit the plan to the upstream resolution, gated. The plan proposes extending the "planner" notion for CLI ends (dsl-refine as the CLI end's contract owner), but it cannot self-authorise the extension (the source is an unloaded README rule), so it becomes a blocking cross-repo question — explicitly not asserted as already-true. Because Q1 and Q3 share a root cause and the same gate, they consolidate into one upstream decision that must be ratified before Wave 2 (
/axb-dsl-refine) runs.
Net of Q1–Q3: the plan's interface-1 half is under-bounded on two axes at once — it has neither a valid Interface.kind (Q1) nor a planner under wave-covers-interfaces (Q3) — and both defects are the same statement: the typed model (aixbdd-tmg) was written for web apps (backend/frontend, api/data/ui planners) and has no CLI end in it. The honest correction is to retract both "holds"/"forward risk" claims, record the single consolidated blocker, state the intended CLI adaptation (dsl-refine as the CLI contract owner/phase), and gate Wave 2 on the aixbdd-tmg owner ratifying it — rather than shipping a plan that quietly extends two invariants from a downstream phase.
Q4: You and I now agree the CLI end has neither a valid Interface.kind (Q1) nor a planner under wave-covers-interfaces (Q3) — you called it "an artifact of the analysis plan's loose '系統介面' notion" that "has a seat in neither typed structure." That leaves the plan's central number unresolved, and the number is a required output: axb-system-analysis/SKILL.md:36 says you must report "系統介面數量" (the interface count), and plan.md states it — "This requirement yields 2 system interfaces." But wave-covers-interfaces is quantified over "every interface identified by an AnalysisPlan," so the plan's "系統介面" and the invariant's "interface" must be the same concept — otherwise the invariant isn't even evaluable. So the plan can't have it both ways: either "系統介面" is the typed concept (in which case the CLI end is not one, and the count is 1 — only the persistence interface, whose DataModel is CLI-agnostic and which gets a real planner), or it is a looser concept (in which case the invariant's referent is undefined and the plan must say so).
My recommended answer: the count should be 1, and the CLI end should be reclassified from a "system interface" to a phase artifact. The reasoning is the direct consequence of your own Q1/Q3 retractions: 系統介面 in this skill is defined operationally as a surface that a planner (api/data/ui) takes and that lands as a typed truth artifact (Contract/DataModel) or a truth-tree Interface — that is exactly the referent wave-covers-interfaces needs. The CLI end qualifies for neither: it has no planner (Q3) and no valid Interface.kind (Q1). Counting it as a "system interface" is what forced both defects; if the plan instead reports 1 interface (Configuration & workspace persistence interface → /axb-data-plan), then wave-covers-interfaces is satisfied cleanly, the single-wave collapse from Q2 is trivially correct, and the CLI end is handled where it actually belongs — as the executable contract produced by the next pipeline phase /axb-dsl-refine, carried in plan.md as a phase handoff, not a Wave row. This is not a re-run of Q1/Q3: Q1/Q3 found two unmet conditions on interface 1; Q4 is the consequent decision about the count and structure that those findings force, and it changes the number plan.md reports and what appears in the Wave table.
So: does plan.md report 2 interfaces (in which case define precisely what "系統介面" means such that the CLI end is one and wave-covers-interfaces is evaluable), or 1 (CLI end reclassified as a /axb-dsl-refine phase handoff)? State which, and the resulting Wave-table contents.
Commit to 1.** plan.md reports one system interface, and the CLI end is reclassified from a "system interface" to a /axb-dsl-refine phase handoff. The decisive evidence is the skill's own consistency rule, which I under-weighted until the griller's dichotomy forced it into the open:
axb-system-analysis/SKILL.md:29 — "THINK 依介面依賴、truth 變更風險與可平行程度安排 Wave,確認每個介面至少被一個後續 planner 承接." The skill treats "every inventoried 系統介面 is carried by ≥1 downstream planner" as a design assumption. The CLI end is carried by no planner (Q3: api-plan NOOP, ui-plan skipped, data-plan explicitly won't take it). So including it in the 系統介面 inventory violates the skill's own rule — it must not be counted. 系統介面, precisely defined, is therefore: a requirement-derived endpoint that a downstream planner (api/data/ui) carries and that lands as a typed truth artifact (Contract/DataModel) or a truth-tree Interface. The persistence interface qualifies (→ DataModel via /axb-data-plan); the CLI end qualifies on neither axis (Q1: no valid Interface.kind; Q3: no planner). Count = 1.
This does not contradict the canonical example. plan.example.md counts a 第三方金流服務介面 (type 金流端點) — a non-api/data/ui endpoint type — but its analysis feeds /axb-api-plan's contracts/payment-webhook.yaml, so it is planner-carried. That is exactly why it may be inventoried: it has a planner. The tellme CLI end has none, so the example does not give it a seat — it confirms the rule ("must have a planner"), it does not exempt it. This is the first horn of the griller's dichotomy ("系統介面 is the typed concept"), and I take it explicitly: plan.md will define 系統介面 as the planner-carryable concept, so the invariant's referent and the plan's count are the same concept and wave-covers-interfaces is evaluable.
Resulting Wave-table contents (this also lands the Q2 single-wave collapse):
### System interface inventory → 1 system interface
1. `Configuration & workspace persistence interface`
- Endpoint type: `local-file / state endpoint`
- Primary interface: config input contract ($TELL_ME_HOME/configs/<mode>.yaml keys + TELL_ME_* precedence) + workspace/state lifecycle (output/<mode>/)
- Evidence: FR-002/003/005/006/007/008/009/015, NFR-001/002, spec.md Assumptions
- Planner: `/axb-data-plan` → minimal specs/truth/data/**
### Wave schedule → 1 wave
#### Wave 1
- Interfaces: `Configuration & workspace persistence interface`
- Focus: model the minimal data truth (config input contract + workspace lifecycle)
- Planner: `/axb-data-plan`
CLI end — phase handoff, not an inventory/Wave row. plan.md keeps the CLI end as an explicit Handoff (next phase): producer /axb-dsl-refine (per the CLI-streamlined rule, aixbdd-tmg/README.md → "Developing CLI Applications" §3), output specs/truth/features/** + dsl.md, driven E2E at tests/e2e/. It stays in the Document-structure and Source-code-structure sections (so the plan still documents where the CLI contract lands and still bounds it), but it is not counted as a system interface and does not appear as a Wave row.
Consequences, stated honestly.
wave-covers-interfacesis now satisfied cleanly (1 interface, planner-delegated in Wave 1) — which dissolves Q3's "invariant unmet": the invariant no longer ranges over the CLI end, because the CLI end is not anAnalysisPlaninterface under the definition above. Q3's root-cause finding stands as diagnosis; its claim ("no planner ⇒ invariant violated") is resolved by removing the mis-categorised member.- Q1's blocker persists unchanged. Reclassifying the CLI end as a phase handoff removes it from the interface count, but
/axb-dsl-refinestill must write it somewhere, andInterfaceKind ∈ {backend, frontend}still has no CLI value (verified:axb-dsl-refine's SKILL front-matter names onlyspecs/truth/features/backend/**andspecs/truth/features/frontend/**). So theInterfaceKind-extension question remains a blocking cross-repo item escalated to theaixbdd-tmgowner, gating Wave 2 — it is not resolved by the recount, and I do not claim it is.
So plan.md reports 1 system interface, defines 系統介面 as the planner-carryable concept so the invariant is evaluable, carries the CLI end as a /axb-dsl-refine phase handoff with the InterfaceKind blocker attached, and collapses the analysis to a single wave.
Q5: Let me pin down whether the plan over-commits its downstream. Your plan.md Wave-2 analysis focus enumerates the executable contract to produce: "…and the ratified -d reporting contract (always report; dedicated non-zero 'unresolved' code; FR-014 codes bind the boot path only)." That "always report / dedicated non-zero unresolved code" is the unresolved half of the clarify-Q1 ruling. But I checked the acceptance set — the four features you cite as the CLI end's evidence — and that half is not there. version-and-setup-diagnostic.feature has exactly one -d Example, and it is the resolved case only ("…a configuration … resolves to a ready state … -d … exits successfully", then the same with --json, "exits successfully"). There is no Example for -d on a broken/unresolved setup and no non-zero diagnostic exit. Likewise starting-with-a-configuration.feature has no found-default case for no--c + MODE≠butler (only the "no default configuration can be found" failure). Now the mechanism: axb-dsl-refine's SOP Phase 2 works by "逐一盤點 acceptance 的 Rule、Example … 分派到相關介面" — it splits the acceptance Gherkin into interface features, and acceptance-coverage is quantified acceptance → interface. Its READ list does not even include research.md, so the Decision-2 text where the unresolved contract actually lives never reaches it; all it sees is the acceptance set (which lacks the rule) and plan.md (which asserts the contract). So plan.md is handing dsl-refine a contract half whose upstream acceptance rule does not exist — and by its own SOP dsl-refine must then either skip it (a coverage gap) or invent it (an SOP violation).
My recommended answer: this is a real over-commit in plan.md, and it should be flagged as a blocker on that scope — the same discipline you applied in Q1/Q3. The plan is the delegation contract; it currently asserts Wave 2 will produce the -d-unresolved behaviour, but the PM-owned authority for that behaviour (an acceptance Example + a non-zero-diagnostic Example) is an open PM follow-up that hasn't landed, and dsl-refine cannot carry a rule the acceptance set doesn't express. So plan.md should either (a) scope the Wave-2 handoff to the behaviour the acceptance set actually expresses and record the -d-unresolved / default-path coverage as an explicit PM gap blocking that slice, or (b) if it keeps the full contract in the handoff, mark it as not yet delegable pending the acceptance Examples. Silence here is exactly the "downstream phase will quietly fill the gap" failure you conceded in Q1 and Q3.
So: does plan.md acknowledge that the -d-unresolved contract (and the no--c + MODE≠butler default path) has no acceptance rule — and if so, does it gate that scope, or does it delegate it as if the acceptance set already carried it?
Concede — this is a real over-commit, narrow but real.** I verified all three legs and they hold:
- Acceptance gap (verified).
version-and-setup-diagnostic.featurehas exactly one-dExample and it is the resolved case only ("…resolves to a ready state… exits successfully", then--json, "exits successfully"). There is no unresolved-dExample and no non-zero diagnostic exit anywhere in the set.starting-with-a-configuration.featurelikewise has only the failure case for no--c("no default configuration can be found"), not a positive default-path discovery withMODE≠butler. - Mechanism (verified).
axb-dsl-refinePhase 1.2 and Phase 2.2 work by distributing acceptance Rules/Examples to interfaces ("逐一盤點 acceptance 的 Rule、Example…分派到相關介面"), andacceptance-coverageis quantified acceptance → interface. Its READ list does not includeresearch.md— so the Decision-2 text where the unresolved contract actually lives never reaches it as a source. - Over-commit (verified).
plan.md's Wave-2 focus asserts the deliverable as "…the ratified-dreporting contract (always report; dedicated non-zero 'unresolved' code;FR-014codes bind the boot path only)…", and it silently omits that the acceptance authority for that half is an open PM follow-up.
One precision on the mechanism, because it sharpens the fix. dsl-refine is not blind — plan.md is in its READ list, so it does see the assertion. The failure is not visibility, it's authority: plan.md cannot authorise behaviour (analysis-plan-never-writes-truth), and the behaviour authority (acceptance, PM-owned) for the unresolved half does not exist. So dsl-refine sees a claim with no rule behind it, and its SOP flow (split acceptance → interfaces) has nothing to split — it must skip the slice (a coverage gap) or author a PM behaviour itself (an SOP/governance violation). Same class of failure I conceded in Q1 and Q3: a delegation contract asserting downstream output whose upstream authority hasn't landed.
So plan.md must acknowledge it and gate the slice. Concretely:
- Scope the Wave-2 handoff to what the acceptance set actually expresses — config resolution (the 6-step order, acceptance-backed at the observable level by the env-over-file cases in
starting-with-a-configuration.featureandruntime-home-and-session-workspace.feature), workspace init,--version, and the resolved-d/-d --jsonreporting (the only diagnostic Example that exists). - Record the two missing PM artifacts as an explicit gap blocking that slice (not "delegable as-is"):
- an acceptance Example for
-don a broken/unresolved setup + the non-zero "diagnostic: unresolved" exit (clarify Q1's other half); and - an acceptance Example for no-
-c+MODE≠butlerdefault-path discovery (currently only the failure case is expressed).
- an acceptance Example for
- Mark the full
-d-unresolved contract as not yet delegable pending those Examples — i.e., option (b) folded into (a): the contract intent stays inplan.mdas a recorded handoff, but Wave 2 does not assert it as a deliverable the acceptance set will carry.
Honest context so this isn't framed as a new discovery: these two gaps are already recorded — research.md ("PM follow-ups remain… add an edge case + an acceptance Example for -d on a broken/unresolved setup"; "Acceptance-coverage gap (PM-routed). No acceptance Example exercises the no--c + MODE≠butler default-path discovery") and STATUS.md → "PM follow-ups". The defect is specifically that plan.md — the delegation contract — drops them, so it over-commits Wave 2 while the round's other artifacts correctly flag the gap. The fix is a reconcile: carry those recorded gaps into plan.md as a slice-blocking PM gap and narrow the Wave-2 scope accordingly, rather than asserting the full contract as if the acceptance set already carried it. Silence here is exactly the "downstream fills the gap" failure I already conceded twice.
Q6: I want to test the definition that carried Q4, because it's the hinge that made Q3's violation "dissolve," and I think it's reading the skill against itself. You defined 系統介面, for the count, as "a requirement-derived endpoint that a downstream planner (api/data/ui) carries" — i.e. you built planner-carryability into the definition. Now re-read the very line you cited to anchor it. axb-system-analysis/SKILL.md:36 reports, as separate items: "plan.md、系統介面數量、Wave 數量、委派到哪些 planner,以及是否可進入 /axb-dsl-refine…". If 系統介面 were defined as "planner-carryable," then "the interface count" is the size of the planner-delegation set, and reporting "which planners" as a distinct field would be pure redundancy — the skill would be asking the same thing twice. The skill doesn't do that, so the two are distinct concepts: the inventory is one thing, its planner assignments another. This is corroborated by templates/plan.md's own comment — "每一個已盤點的系統介面,至少都要在某一個 Wave 中出現一次" — a check applied to an already-inventoried set, not a filter that defines the set. And it's what 系統介面盤點與端點歸類判準.md Rule 1 requires: inventory first, from requirement parts ("先從需求原文中…切出需求部位"), and only then (Rule 2 of the delegation rule) assign planners. Your Q4 definition inverts that order — it derives the inventory from the delegation — which is exactly why the count silently lost the round's dominant requirement surface (the CLI), and why SKILL.md:29's "確認每個介面至少被一個後續 planner 承接" became unfalsifiable (no inventoried interface can ever lack a planner, so the check can never fire).
My recommended answer: revert the count to 2, keep the CLI end in the inventory, and record its unassigned planner as the gap — not delete it to make the invariant hold. Under Rule 1 the CLI end is requirement-derived (the round is "CLI bootstrap and config"; its invocation/flags/streams/exit codes are precisely a "使用者行為 / 運作邊界" requirement part), so it belongs in the inventory; SKILL.md:29's check then fails, which is the finding (a requirement surface the methodology gives no planner) — the same consolidation as Q1/Q3/Q5, recorded as the aixbdd-tmg blocker, but with an inventory that still reflects the requirement rather than only its delegable subset. Reclassifying it as a phase handoff hides the gap behind a smaller number, which is the move you rightly retracted in Q1.
So, finally: do you hold "count = 1" — and if so, how do you reconcile it with a skill that reports "系統介面數量" and "which planners" as two separate fields (a definition making one the size of the other is redundant) and a template that requires every inventoried interface to appear in a wave — or do you revert to count = 2, CLI end inventoried with an unassigned planner recorded as the consolidated blocker?
Revert to 2. I hold that the Q4 definition was wrong, and the griller's three-way argument defeats it decisively.
The falsifiability point is the killer. My Q4 definition — "a requirement-derived endpoint that a downstream planner carries" — builds the conclusion into the premise, which makes axb-system-analysis/SKILL.md:29's instruction "確認每個介面至少被一個後續 planner 承接" unfalsifiable: if an interface is by definition planner-carryable, the check can never fire, and a check that can never fire is vacuous. The skill states it as a verification ("確認"), which presupposes it can fail — so the inventory must be able to contain a planner-less interface. And SKILL.md:36 corroborates: it reports "系統介面數量" and "委派到哪些 planner" as separate fields — if one were the size of the other, the second would be redundant; the skill asks for both, so the inventory and the planner assignment are distinct concepts.
The ordering point compounds it. 系統介面盤點與端點歸類判準.md Rule 1 requires inventory to come first, from requirement parts ("先從需求原文中…切出需求部位"), and only then does the delegation rule (Rule 2) assign planners. My Q4 definition inverted that order — deriving the inventory from the delegation — and templates/plan.md's comment ("每一個已盤點的系統介面,至少都要在某一個 Wave 中出現一次") confirms the template treats the inventory as prior and applies the Wave check to "an already-inventoried set," not as a filter that defines it. So: retracted.
And the CLI end is genuinely requirement-derived. Rule 1 sources requirement parts from "使用者行為、外部依賴、資料責任或運作邊界." The round is 001-cli-bootstrap-and-config; the CLI end's invocation, flags (-c/-d/--version), stdout/stderr streams, and exit-code taxonomy are precisely a user-behaviour / operational-boundary requirement part. So it belongs in the inventory. Reclassifying it as a "phase handoff" to shrink the count is the same move I retracted in Q1 — hiding an undecidable interface behind a smaller number instead of exposing it. I withdraw it.
So plan.md reverts to:
### System interface inventory → 2 system interfaces
1. `CLI end (operator terminal interface)`
- Endpoint type: `CLI / terminal endpoint`
- Primary interface: invocation + flags (-c/--config, -d, --json, --version); exit-code taxonomy
(success / usage / configuration / environment + "diagnostic: unresolved"); stdout/stderr/stdin; console output
- Evidence: FR-001–FR-015, NFR-003/004; the four acceptance features
- Planner: **UNASSIGNED — no api/data/ui planner takes a terminal endpoint (api-plan NOOP, ui-plan skipped, data-plan N/A)** ← consolidated blocker
2. `Configuration & workspace persistence interface`
- Endpoint type: `local-file / state endpoint`
- Primary interface: config input contract + workspace/state lifecycle (output/<mode>/)
- Evidence: FR-002/003/005/006/007/008/009/015, NFR-001/002
- Planner: `/axb-data-plan` → specs/truth/data/**
### Wave schedule → 1 wave
#### Wave 1
- Parallel interfaces: both of the above (information-independent — Q2)
- Delegation: persistence → `/axb-data-plan`; CLI end → **unassigned planner (recorded gap)**
The consequence, stated plainly (this is the finding, not a defect to paper over): with the CLI end correctly inventoried, SKILL.md:29's check fails and wave-covers-interfaces is not met for the CLI end — because the methodology provides no planner for a terminal endpoint. That is the same root cause as Q1 (no valid InterfaceKind for the CLI end's truth home) and Q3 (no planner), and it now also restores Q3's claim rather than dissolving it: my Q4 "count = 1" dissolved Q3 only by deleting the mis-categorised member; reverting to 2 re-exposes it. Q1, Q3, Q5, and Q6 therefore consolidate into one aixbdd-tmg methodology blocker — the typed model (backend/frontend kinds; api/data/ui planners) was written for web apps and has no seat for a CLI end, neither as a truth node nor as a planner-delegated unit — escalated to the truth-model owner and gating Wave 2 (/axb-dsl-refine), alongside Q5's PM-owned acceptance gap for the -d-unresolved half and the default-path Example (which gates the same slice).
Net across the round: the plan's source-tree / structure decisions and its NOOP/skip rulings stand; its wave structure collapses to one (Q2); and its interface count stays 2 with the CLI end's missing planner exposed as the blocker (Q1/Q3/Q5/Q6) — the inventory reflects the requirement, and the gap is recorded where it can be acted on, rather than hidden behind a smaller number.
VERDICT: The subject's diagnosis held only in the parts that never depended on the typed model — the persistence interface as a genuine, data-plan-delegable system interface, the NOOP/skip rulings, and the source-tree/structure decisions all survived scrutiny — but its core claim (a settled 2-interface / 2-wave plan delegating cleanly) did not: three of four load-bearing assertions fell under verification (the CLI end has no valid Interface.kind, it has no planner, and its -d-unresolved/default-path scope has no acceptance authority), all traceable to one root cause the subject ultimately named honestly — the aixbdd-tmg typed model has no seat for a CLI end. My recommendation is proceed with changes, not as planned: plan.md should collapse to a single wave (no information dependency exists), retain count = 2 with the CLI end's unassigned planner recorded as a blocker rather than deleted, and gate Wave 2 (/axb-dsl-refine) on the consolidated cross-repo methodology decision plus the two PM-owned acceptance gaps.
(1) What I STAND BY
- The persistence interface is a genuine system interface and correctly delegated to
/axb-data-plan(minimalspecs/truth/data/**). It is requirement-derived (FR-002/003/005/006/007/008/009/015,NFR-001/002,spec.mdAssumptions), and its delegate is a real planner — so it satisfies bothwave-covers-interfacesand SKILL.md:29. Ratified by clarify Q2 (data-lock released). /axb-api-plan= NOOP and/axb-ui-planskipped.Contractis OpenAPI 3.0; a single CLI end has no HTTP operation/schema to describe, and terminal output is not an HTML prototype. Both rulings held under verification.- The source-tree and structure decisions.
cmd/tellme/main.go(single-X main.version),internal/{cli,config,home},tests/e2e/,Makefile,go.mod/go.summatchresearch.mdDecisions 1/4/6 andtechstack.md. No change. new§b's interface-1 content is correct as an inventory entry — the CLI end is a requirement-derived endpoint (Rule 1: "使用者行為 / 運作邊界"). I stand by keeping it in the inventory.
(2) What I REVISED (four retractions, all conceded under verification)
- Q1 — retracted "forward risk, not a blocker." The CLI end has no valid
InterfaceKind(∈ {backend, frontend}; both web-bound), so its truth home is undecidable — a present gap, escalated to theaixbdd-tmgowner. - Q2 — retracted the Wave-1→Wave-2 dependency.
/axb-dsl-refine's READ contract excludesspecs/truth/data/**; the two interfaces are information-independent → collapse to a single wave. The ordering is pipeline phasing, not a Rule-2 analysis dependency. - Q3/Q6 — retracted both the "
wave-covers-interfacesholds" claim (Q3:/axb-dsl-refineis not a planner, and no loaded rule makes it one) and the Q4 "count = 1" fix (Q6: that definition inverted the skill's inventory-then-delegate order and made SKILL.md:29's check unfalsifiable). Net: count stays 2, CLI end inventoried, its unassigned planner recorded as the gap — not deleted. - Q5 — conceded an over-commit:
plan.mdasserts Wave 2 will produce the-d-unresolved contract and the no--c+MODE≠butlerdefault path, but no acceptance Example carries either, andplan.md(not a behaviour authority) silently drops the gap thatresearch.md/STATUS.mdalready record.
(3) Open questions / resulting state
- One consolidated cross-repo blocker (
aixbdd-tmgtruth-model owner), gating Wave 2: the typed model has no seat for a CLI end — noInterfaceKindvalue and no api/data/ui planner. Proposed resolution: extendInterfaceKind(e.g.cli→features/cli/**) or rule that a CLI end is a planner-of-record =/axb-dsl-refine; until ratified,/axb-dsl-refinewill either invent an out-of-enum subpath or mis-file underbackend. - Two PM-owned acceptance gaps (gate the same slice): (a) an Example for
-don a broken/unresolved setup + the non-zero "diagnostic: unresolved" exit; (b) an Example for no--c+MODE≠butlerdefault-path discovery. Both already recorded inresearch.md/STATUS.md. plan.mdedits to apply: report 2 interfaces; single Wave 1 (both interfaces parallel); CLI end → planner unassigned (gap);-d-unresolved/default-path marked not-yet-delegable; record the consolidated blocker.
I accept the verdict: proceed with changes, not as planned — and the changes above are the plan's edit set. plan.md is a delegation contract; correcting it here means Wave 2 starts only once the aixbdd-tmg decision and the two PM acceptance Examples land.