APM规范审查_apm-spec-guardian

📅 2026/7/21 9:18:08 👁️ 阅读次数 📝 编程学习
APM规范审查_apm-spec-guardian

以下为本文档的中文说明

apm-spec-guardian(APM 规范守护者)是微软提供的一个面向大型组织内部代码审查场景的专业技能,专门用于对任何涉及 APM(Application Performance Management 应用性能管理 / Application Performance Monitoring 应用性能监控)规范和配置变更的拉取请求(Pull Request / Merge Request)执行四面板对抗性咨询审查。在大型企业和复杂的微服务架构中,APM 的可观测性基础设施(指标 Metrics、链路追踪 Tracing、日志 Logging)的一致性和规范性直接关系到运维团队能否在故障发生时快速定位根因。该技能确保每一次 APM 相关的代码变更都经过严格的多视角审查。使用场景包括:在代码审查流程中自动识别和标记涉及 APM 配置或埋点代码变更的 Pull Request,并触发深入的 APM 专项审查;确保新建或修改的监控仪表板、自定义指标(Custom Metrics)、分布式追踪 Span 定义和日志结构化字段严格遵守团队或组织预先定义的 APM 命名规范、标签规范(Tag Convention)和采样策略约定;在大型组织中保持跨团队的 APM 数据采集和上报实践的一致性和高质量标准,防止因各自为政导致的监控数据"污染"和"碎片化"。核心特点包括:采用独创的四面板对抗性评审方法论(Four-Panel / Quadrant-Based Adversarial Review),模拟从四个彼此独立且视角互补的专家角色对同一份代码变更进行全方位审视:第一面板"规范合规性"检查 APM 配置是否遵循了组织定义的命名规范(如指标名称的 Metric Naming Convention 必须包含服务名+模块名+指标名三段式)、标签属性白名单(Allowed Tag Keys)和采样率(Sampling Rate)策略阈值;第二面板"性能影响"评估新增或修改的 APM 数据采集点和埋点逻辑对宿主应用运行时性能的实际影响,关注是否存在过度采集、高频采集或串行阻塞的埋点代码模式;第三面板"安全风险"分析 APM 数据上报链路中是否存在意外泄露敏感数据(PII、Token、SQL 查询中的用户个人信息)的风险,检查是否有对采集数据进行脱敏处理(Data Masking / Redaction);第四面板"可维护性"评估 APM 配置代码的质量、可读性和团队内其他成员理解和修改的难易程度。


APM Spec Guardian – Four-Panel Advisory Review for OpenAPM

This skill institutionalizes the two-round adversarial spec review
that produced OpenAPM v0.1 by hand. The panel is FAN-OUT +
SYNTHESIZER. Each panelist runs in its own agent thread (via the
tasktool) and returns JSON matching
assets/panelist-return-schema.json. The orchestrator schema-validates
each return, hands all returns to thespec-editor-synthesizer
(also a task thread, returns JSON matching
assets/synthesizer-return-schema.json), runs the linter checklist
inassets/linter-checklist.md, then renders ONE comment from
assets/comment-template.md.

This skill is ADVISORY by design. It does not compute a binary
verdict, it does not apply verdict labels, and it does not gate
merge. The panel surfaces findings; the maintainer ships.

Activation scope

This skill activates ONLY when the PR diff touches at least one of:

  • docs/src/content/docs/specs/openapm-*.md(the normative spec
    artifact, current and future versions)
  • docs/src/content/docs/specs/schemas/*.schema.json(sidecar JSON
    Schemas, if/when the inline Appendix-A schemas are extracted to
    files)
  • tests/fixtures/spec-conformance/**(the conformance fixture seed)

Edits to any OTHER documentation page MUST NOT trigger this skill.
The maintainer’s generaldocs-syncskill covers those.

Architecture invariants

  • Advisory regime, not gate regime.There is noAPPROVE/
    REJECT, nospec-approved/spec-rejectedlabel, no
    deterministic verdict computation. The synthesizer returns a
    ship_decision(fold_and_ship/needs_revision/
    next_brief); this is prose for the human reviewer, never
    auto-applied as a label or status check.
  • Ship-meter floor.ship_decision: fold_and_shipREQUIRES
    shocked_meter_avg >= 7.0. Below 7.0 the synthesizer MUST emit
    needs_revision(single drafter pass on the existing artifact)
    ornext_brief(another round of panel review with a new brief).
    The floor is advisory wording in the comment, not a status check.
  • Blocker veto.If ANY panelist returns
    new_blocking_findings[].length > 0, the synthesizer MUST emit
    ship_decision: next_briefregardless of the shocked_meter_avg.
    A blocking finding from one panel is not outweighed by three
    panels rating the artifact 9/10.
  • Single-writer interlock.Only the orchestrator writes to the
    PR: exactly oneadd-commentcall and oneremove-labelscall.
    Theremove-labelscall sweepsspec-review(trigger
    idempotency). NOadd-labelscall – there are no verdict labels.
    Panelist subagents and the synthesizer subagent return JSON only
    and MUST NOT call anyghwrite command, post comments, apply
    labels, or touch PR state.
  • Single-emission discipline.Exactly one comment per panel run,
    rendered fromassets/comment-template.mdafter all subagents
    return and the linter checklist runs.
  • ASCII-only artifact.Every byte the skill writes (the comment,
    the synthesizer prose, any rendered fold instruction) MUST be
    within printable ASCII (U+0020 - U+007E). The skill inherits the
    repo encoding rule from.github/instructions/encoding.instructions.md
    (if present) and additionally enforces it on the spec artifact via
    linter check 1.
  • No-vendor-foundation language ban.The spec artifact MUST NOT
    contain “CNCF”, “Linux Foundation”, “Sandbox”, “Incubation”,
    “W3C Process”, or “IETF RFC stream”. The persona prompts MAY
    reference these as pedigree (a panelist’s credibility comes from
    having edited OpenAPI; that does not put OpenAPI’s foundation
    affiliation in the spec text). Linter check 2 greps the artifact
    for the forbidden token list AFTER any fold.

Agent roster

AgentRoleAlways active?
Swagger / OpenAPI EditorInterface-contract discipline (schemas, $ref hygiene, oneOf discriminators, conformance enumeration)Yes
OCI Distribution EditorRegistry-HTTP rigor (hash
envelopes, mirror tolerance, fail-closed extraction, supply-chain threat model)Yes
Package-Manager Registry-Contract EditorDependency-resolution rigor (semver dialect pinning, lockfile determinism, transitive conflict policy, reserved-slot defensive MUSTs)Yes
W3C TAG ArchitectWeb-platform integration / architecture (extensibility, layering, fingerprinting, machine-readable contract surface)Yes
Spec Editor SynthesizerSame hand that drafted; aggregates panel returns, computes shocked_meter_avg, clusters convergent themes, produces fold-now / defer / reject lists and ship_decisionYes

The roster is invariant for the v0.1 lineage. Changing it requires
bumping the skill version.

Topology

apm-spec-guardian SKILL (orchestrator thread) | +------ Wave 0: scope decision (orchestrator-internal) ------+ | classify diff: | | - editorial-only (tiny patch, single section, no schema | | change, no fixture add) -> skip Wave 3, run Wave 5 | | linter only, render lightweight comment | | - editorial-patch (default for PR-trigger) | | -> skip Wave 1+2, start at Wave 3 | | - new-version (operator opt-in via PR body marker | | `apm-spec-guardian: new-version`) | | -> run Wave 1 + 2 + 3 + 4 + 5 | +------------------------------------------------------------+ | IF new-version mode: run Wave 1 + Wave 2 first | Wave 1 (optional, new-version only): task -> spec-editor-synthesizer acting as ASSESSOR -- reads issue context + corpus + produces SPEC_BRIEF_v0 (session-state artifact) Wave 2 (optional, new-version only): task -> spec-editor-synthesizer acting as DRAFTER -- produces SPEC_DRAFT_v0 from SPEC_BRIEF_v0 | Wave 3: FAN-OUT via task tool (4 panelists in parallel) +------+------+--------+------+ v v v v swagger oci pkgmgr tag (each returns JSON per assets/panelist-return-schema.json) | v <-- S4 schema-validate per return v <-- on malformed: re-spawn that panelist v (max 2 attempts; then placeholder) v Wave 4: task -> spec-editor-synthesizer - aggregates findings across 4 panels - computes shocked_meter_avg - resolves dissent - clusters into convergent themes - emits fold_now[] + defer_v0_1_1[] + defer_v0_2[] + reject[] - emits ship_decision honoring ship-meter floor + blocker veto - returns assets/synthesizer-return-schema.json | v <-- S4 schema-validate v Wave 5: LINTER (mechanical, from assets/linter-checklist.md) - 11 checks; each MUST pass - failures append to ship_prose as advisory notes - linter does NOT change ship_decision; it informs the human reviewer | Wave 6: orchestrator (sole writer) | | v v add-comment remove-labels (max:1) [spec-review] (trigger idempotency reset)

Wave 0 – scope decision

The orchestrator classifies the diff before spawning any panelist.
Decision rules, in order:

  1. New-version mode.If the PR body contains the literal marker
    lineapm-spec-guardian: new-version, OR the diff creates a new
    docs/src/content/docs/specs/openapm-*.mdfile (not an edit to
    an existing one), classify asnew-version. Run Waves 1 -> 2 ->
    3 -> 4 -> 5 -> 6.
  2. Editorial-only mode.If ALL of the following hold:
    • the diff added < 50 lines AND removed < 50 lines total across
      a
      ll in-scope paths,
    • no JSON Schema file was added, removed, or had its top-level
      propertieskeys changed,
    • no fixture file was added or removed (existing fixture
      content edits are OK),
    • no anchor of the form<a id="req-was added or removed,
      classify aseditorial-only. SKIP Wave 3 + Wave 4. Run Wave 5
      linter on the modified artifact. Render the lightweight
      editorial-only branch ofassets/comment-template.md(just the
      linter result + a one-line “no substantive spec change
      detected”).
  3. Editorial-patch mode (default).Everything else. Run Wave 3
    -> 4 -> 5 -> 6. Wave 1 + Wave 2 are SKIPPED; the panel reviews
    the existing artifact as modified by the PR diff.

Document the decision in the comment header (one line: “Scope: ;
diff = +X/-Y lines across N files”).

Wave 3 – panel fan-out

Spawn the following four tasks in PARALLEL via thetasktool, one
task per persona:

  • spec-swagger-editor
  • spec-oci-editor
  • spec-pkgmgr-editor
  • spec-tag-architect

Each task prompt MUST:

  • Reference its persona file by relative path
    (../../agents/spec-<slug>.agent.md) so the subagent loads its
    own scope, lens, and pedigree.
  • Include the PR number, title, body, and full diff (passed inline),
    PLUS the current contents of the in-scope spec artifact AS
    MODIFIED by the diff (the panel reviews the post-merge state of
    the file, not just the diff).
  • Citeassets/panelist-return-schema.jsonand require the
    subagent to emit JSON matching that schema as its FINAL message.
  • State the calibrated severity contract: “Use
    new_blocking_findingsONLY for issues that would break a
    conformant implementation, leak a security guarantee, or invalidate
    a published normative claim. Usenew_recommended_findingsfor
    substantive improvements. Usenew_nit_findingsfor one-line
    editorial polish. The panel is advisory; nothing you return blocks
    merge; pick the severity that honestly matches your signal
    strength.”
  • State the no-vendor-foundation rule: “Your pedigree as a [persona]
    is part of your prompt. Do NOT propose adding the names of any
    standards body, foundation, or governance program (CNCF, Linux
    Foundation, Sandbox, Incubation, W3C Process, IETF RFC stream) to
    the spec artifact text. Findings that recommend such additions
    will be auto-rejected by the synthesizer.”
  • State the ASCII rule: "Every byte in your return JSON and every
    byte of any proposed fix or replacement text MUST be within U+0020
    • U+007E. No emojis, no Unicode dashes, no curly quotes."
  • Passround(1 on first pass, 2+ on subsequent rounds in
    new-version mode).
  • Restate the output contract: NOghwrite commands, NO posting
    comments, NO label changes, NO touching PR state. JSON return only.

Wave 4 – synthesizer

Pass all four validated panelist JSON returns to ataskinvocation
that loads../../agents/spec-editor-synthesizer.agent.md. The prompt
MUST:

  • Provide all panelist returns as structured input.

  • Ask for:convergence_table,convergent_themes(themes flagged
    by 2+ panels),fold_now[](surgical single-section fixes only),
    defer_v0_1_1[](small patches deferrable to next patch
    release),defer_v0_2[](architectural work requiring a reserved
    slot in a future major),reject[](findings the synthesizer
    declines, with rationale),ship_decision,ship_prose,
    linter_handoff_notes.

  • State the ship-decision rules verbatim:

    • Ifsum(panelist.new_blocking_findings)> 0 across all panels,
      ship_decisionMUST benext_brief.
    • Else ifshocked_meter_avg < 7.0,ship_decisionMUST be
      needs_revision.
    • Elseship_decisionMAY befold_and_ship.
  • State the no-vendor-foundation rule: auto-reject any
    panelist-proposed fix that would add a banned token to the
    artifact; surface inreject[]with rationale.

  • Citeassets/synthesizer-return-schema.jsonand require JSON
    return.

  • Restate the contract: the panel is advisory. The synthesizer does
    NOT pick a verdict label. Theship_decisionis prose for the

    human reviewer, not a gate. NOghwrite commands.

Validate the synthesizer return against
assets/synthesizer-return-schema.json. On failure, re-spawn once
with the violation cited.

Wave 5 – linter

Runassets/linter-checklist.mdagainst the in-scope artifact set
(spec markdown + schemas + fixtures). The checklist has 11 mechanical
checks; each is a one-liner producing exit code 0 (or empty grep
output where noted). Record pass / fail per check.

Linter outcomes are ADVISORY: a failed check does NOT change the
synthesizer’sship_decision. It DOES surface in the comment as a
“Linter notes” section so the maintainer can decide whether to fold
the fix into the same PR. Ifship_decision == fold_and_shipAND
any linter check failed, the comment surfaces the conflict
prominently (“Synthesizer recommends ship; linter found N issues
worth folding first”).

Wave 6 – render the comment

Loadassets/comment-template.md, fill the placeholders from the
synthesizer + panelist JSON + linter results, and emit it as exactly
ONE comment.

Filling rules:

  • The convergence table renders ONE row per panelist with verdict,
    shocked_meter, new_blockers, new_recommended, new_nits counts.
  • The fold-now list renders the synthesizer’sfold_now[]
    verbatim, ordered as returned.
  • The defer-v0.1.1 and defer-v0.2 lists render below the fold list,
    collapsed in<details>blocks if either has more than 3 items.
  • The reject list renders only if non-empty.
  • The “Linter notes” section renders only if any check failed; each
    failed check renders the check id + the one-line failure summary.
  • Full per-panel findings collapse into a<details>at the bottom.
  • NEVER render the words “Verdict”, “APPROVE”, “REJECT”, “blocked”,
    “merge gate”, or any equivalent. The panel is advisory.

Then sweep thespec-reviewlabel viasafe-outputs.remove-labels
(idempotent on missing labels). NOadd-labelscall.

Output contract (non-negotiable)

  • Exactly ONE comment per panel run, rendered from
    assets/comment-template.md.
  • Exactly ONEremove-labelscall sweeping[spec-review].
  • NOadd-labelscall.
  • Subagents (panelists + synthesizer) NEVER write to PR state,
    NEVER callgh pr comment, NEVER callgh pr edit --add-label.
    They return JSON. The orchestrator is the sole writer.
  • ASCII-only across every byte the orchestrator writes.
  • Never invent new top-level template sections or drop existing
    ones.

Loop budget

  • Editorial-patch mode:at most 2 panel rounds. If round 2 still
    carries new_blocking_findings, the synthesizer emits
    ship_decision: next_briefwith aship_prosenote that the
    loop budget is exhausted and the maintainer should ESCALATE
    (manually decide between drafting a fix or closing the PR).
  • New-version mode:at most 3 panel rounds. Same exhaustion
    semantics on round 3.
  • Editorial-only mode:zero panel rounds (linter only).

The orchestrator increments and tracks the round counter; subagents
receive it as input but MUST NOT trust panel-side memory.

Gotchas

  • Roster invariant.The frontmatter description, the activation
    scope list, the roster table, the topology diagram, and the
    schema enum MUST agree on the 4 panelists + 1 synthesizer. If you
    change one, change all in the same edit.
  • Blocker veto trumps ship-meter.A panelist who returns one
    new_blocking_findingand a shocked_meter of 9 means “the spec is
    mostly excellent but this one thing would break a conformant
    implementation”. That blocker still vetoesfold_and_ship. Do not
    let the synthesizer average it away.
  • Calibrated severity discipline.The advisory regime relies on
    panelists distinguishing blocking from recommended honestly. If a
    panelist marks every editorial nit as blocking, the synthesizer’s
    blocker veto becomes a denial-of-ship. The panelist prompts state
    the contract explicitly; the synthesizer arbitration prose is the
    safety valve.
  • Wave 0 editorial-only is a noise filter, not a quality
    shortcut.
    It exists so a one-line typo fix to a fixture co
    mment
    does not summon four expert agents. It MUST NOT fire on schema
    changes, anchor additions, or fixture-tree topology changes; the
    rules above are intentionally conservative.
  • No-vendor-foundation tokens may appear in panelist returns(a
    panelist can name “the W3C TAG” as their pedigree in their
    summaryfield) but MUST NOT appear in the synthesizer’s
    fold_now[].patch_instructionor in the rendered comment body
    outside<details>collapsed sections. The synthesizer auto-rejects
    panelist proposals that would add banned tokens to the artifact.
  • ASCII enforcement is per-byte, not per-codepoint.A character
    with codepoint > 0x7E is non-ASCII even if it would round-trip
    through a different encoding. The linter checks raw byte values,
    not the rendered visual.
  • Subagent write enforcement is contract-based, not sandbox-based.
    Tool permissions are workflow-scoped, not subagent-scoped, so
    every spawned task technically inherits the sameghtoolset.
    The “subagents must not write” rule is enforced by the prompt
    contract in each.agent.mdplus thesafe-outputs.add-comment.max: 1fail-soft.
  • Spec drift across count sites.Linter check 6 catches when sec.
    1.3 sentence, Appendix C trailer, and Appendix D revision-history
    disagree on the normative-statement total. This is the most common
    failure mode of a fold pass and is the reason the linter is
    mandatory before render.

Relationship to apm-review-panel

apm-review-panelis the general OSS multi-persona review for any
non-trivial PR in the repo.apm-spec-guardianis its narrow,
spec-only sibling: a different persona roster, a different ship
decision schema (shocked_meter instead of stance enum), and a
mandatory linter step. The architectural shape (FAN-OUT +
SYNTHESIZER + single-writer interlock + advisory regime) is
deliberately the same so a contributor reading one can read the
other. Do not merge them; the persona pedigrees and the artifact
type (spec vs code) are different enough that one-size-fits-all
prompts would dilute both.