Skip to content

ci: wire the 6 Wave-3 doc/API-truth gates into run-ci (per-PR) - #31

Merged
mjerris merged 9 commits into
mainfrom
feat/wave3-wire-gates
Jul 14, 2026
Merged

mjerris merged 9 commits into
mainfrom
feat/wave3-wire-gates

Conversation

@mjerris

@mjerris mjerris commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

Wires the 6 Wave-3 doc/API-truth gates into this port's run-ci.sh (per-PR tier):
ERROR-ENVELOPE, DEAD-PUBLIC-ERROR, PAGINATION-WIRED, DOC-ENV, COUNT-CLAIM, ACCESSOR-TRUTH.

They're deterministic source/doc analysis — no build, no mock, no network — ~1.3s for all six, so they go per-PR (default tier) to catch doc/API-truth drift at PR time rather than a day later in nightly. All six pass at HEAD.

Follow-on to the Wave-3 gate rollout (the gates + paginate() already merged; this makes them enforce on every future PR).

🤖 Generated with Claude Code

mjerris and others added 9 commits July 11, 2026 20:32
ERROR-ENVELOPE, DEAD-PUBLIC-ERROR, PAGINATION-WIRED, DOC-ENV, COUNT-CLAIM,
ACCESSOR-TRUTH now run in the per-PR tier. They are deterministic source/doc
analysis (no build, no mock) — ~1.3s for all six — so they belong per-PR to
catch doc/API-truth drift at PR time, not a day later in nightly. All six pass
at HEAD.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqshDQajCmDHD3xPo4CXMC
… file

The nightly workflow had two SW_CI_TIER keys in one env: block (a hardcoded
`nightly` plus a `${{ steps.tier.outputs.tier }}` copied from a per-PR
path-triggered workflow). GitHub`s strict parser rejects a duplicated env key,
so the whole workflow failed to load ("workflow file issue" — no jobs, no logs)
on every push since it was introduced. The dynamic tier step was also wrong for
a nightly: on a schedule/dispatch event it computes tier=pr, running the CHEAP
tier instead of the heavy nightly gates. Remove the misplaced tier step and set
SW_CI_TIER: nightly unconditionally (matches typescript`s already-correct
nightly). actionlint clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqshDQajCmDHD3xPo4CXMC
Remove ignore entries the doc-auditor already resolves on its own (via the
snake_case->camelCase/PascalCase idiom translation it applies, or against the
port surface). These were dead weight — added defensively but not needed. Each
prune was verify-or-revert: the DOC-AUDIT gate re-run PASSES with the pruned
ledger against the exact surface run-ci uses. No genuine ignore entry removed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqshDQajCmDHD3xPo4CXMC
The README claimed 258 tests; the suite actually has 1917 TEST() macros (grew
~7x since the claim was written). Use a '1900+' floor so it does not re-stale on
the next test added. (COUNT-CLAIM gate checks skills/namespaces, not test counts,
so this slipped past it — a W3.3 §C5 residual.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqshDQajCmDHD3xPo4CXMC
…s -> PlayStopParams)

The REST generator built <Method>Params struct names by capitalizing only the
first letter of a snake method name, yielding half-snake types like
Play_stopParams / Ai_holdParams that read inconsistently next to their
single-word siblings (PlayParams, RecordParams). Add snake_to_pascal() and use it
at all three options-struct name sites so multi-word commands emit PlayStopParams,
AiHoldParams, DetectStopParams, etc. The METHOD name stays snake_case
(play_stop()) for Python parity — only the generated TYPE name is PascalCased.
Regenerated: 23 structs renamed, all references updated. GEN-FRESH clean,
1917/1917 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqshDQajCmDHD3xPo4CXMC
…, drop false enumerator-miss claim

Audited every DOC_AUDIT_IGNORE.md entry against port_surface.json, the C++
source, and the Python reference oracle. None of the ~60 ignored names is a real
public SDK method hidden by an enumerator miss:

- All are C++ stdlib / `nlohmann::json` (vendored) / cpp-httplib (vendored) /
  POSIX-libc calls, an internal free-function helper with NO Python-reference
  equivalent (get_env, http_get, http_post, ensure_builtin_skills_registered,
  to_wire_string — the surface enumerator correctly omits namespace free
  functions unless they project a Python module-level function), a filename
  fragment, the `delete_` reserved-word rename, or a Python/framework-only
  concept shown in an as-yet-unrewritten upstream doc block.
- Verified the two names that DO appear in the oracle are unrelated: `load` maps
  to `SileroVAD.load` (livewire, Python/Node-only — not ported) and `tool` maps
  to the `@AgentBase.tool` decorator (C++ uses `define_tool`, which IS surfaced).

Fixes:
- Removed the corrupted section-10 orphan prose that falsely asserted the
  enumerator "misses public methods declared on the same line block as
  overloaded factories … the symbol exists on the C++ surface." No such miss
  exists; `send_raw_request` is already surfaced (and documented in
  PORT_ADDITIONS.md) and `send_request` is a genuinely-private method.
- Removed the false section-8 "C++ RELAY client is a stub — transport not yet
  present" claim (the IXWebSocket transport is implemented).
- Recategorized every entry under an ACCURATE `## category` header so the
  IGNORE-LEDGER-VERIFY anti-laundering gate auto-accepts the no-divergence
  classes (stdlib / vendored / language-keyword / internal-accessor /
  filename-fragment) without a fake approver. Report-only flags dropped 22 → 3.

The 3 residual report-only entries (register_default_tools, include_router,
SignalWireClient) are genuine Python/framework-only doc references; they pass CI
(the gate does not run --require-fields) but are NOT self-stamped with a fake
approver — hard-clean needs either a doc rewrite or a human sign-off in
IGNORE_LEDGER_ALLOW.md.

Gates green: DOC-AUDIT, SURFACE-FRESH, SURFACE-DIFF, IGNORE-LEDGER-VERIFY,
DOC-LANG-PURITY, DOC-LINKS, ROOT-HYGIENE, FMT, TEST (1917/1917).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqshDQajCmDHD3xPo4CXMC
…NG-PURITY)

The DOC-LANG-PURITY regex fix (porting-sdk) exposed 5 Python code blocks
carried over verbatim from the upstream Python SDK that had been slipping
through the gate. A C++ port's docs must show C++, not Python.

architecture.md — the "Creating Custom Prefabs" tutorial (4 blocks):
  - Extend AgentBase: `class MyCustomPrefab : public agent::AgentBase` with a
    ctor forwarding name/route to the base and holding custom params.
  - Configure defaults + register a tool: moved into the ctor body using the
    real prefab idiom — prompt_add_section(...), add_skill("datetime"), and
    define_tool(name, description, params_json, ToolHandler lambda) returning
    swaig::FunctionResult (NOT the Python SwaigFunctionResult /
    register_default_tools, which have no C++ analog).
  - Factory: replaced the Python @classmethod create with a static
    from_config(const json&) factory (the idiomatic C++ equivalent).
  Also rewrote the inline Multi-Agent-Mode prose from the FastAPI
  `app.include_router(agent.as_router(), ...)` Python idiom to the C++
  `server::AgentServer::register_agent(agent, route)` hosting form.

configuration.md — debug-logging block: replaced
  `logging.basicConfig(level=logging.DEBUG)` with the C++ equivalent
  `Logger::instance().set_level(LogLevel::Debug)` plus the
  SIGNALWIRE_LOG_LEVEL env-var knob.

Both new C++ blocks verified with `g++ -std=c++17 -fsyntax-only` against the
real SDK headers (the same command the SNIPPET-COMPILE gate uses).

DOC_AUDIT_IGNORE.md: removed 3 now-dead report-only entries whose only doc
references were the rewritten Python blocks — register_default_tools,
include_router (section 8, now empty), and basicConfig (section 7). Kept
`super` (still matches false positives super-secret-password / supervisor).

MIGRATION-2.0.md: deleted (staged by orchestrator) — the SDK is unreleased,
there is no 2.0 to migrate from. Its DOC_AUDIT_IGNORE `SignalWireClient`
entry was already removed.

Gates green: DOC-LANG-PURITY (0 python fences), DOC-AUDIT (all symbols
resolve), DOC-LINKS (no dangling MIGRATION link), IGNORE-LEDGER-VERIFY,
README-INCLUDE.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqshDQajCmDHD3xPo4CXMC
Wave-3 W3.2 for the C++ port — set the SemVer release floor and flip the
remaining release-readiness gates from held/report-only to blocking.

- CMakeLists project VERSION 2.0.0 -> 3.0.2; commit the SEMVER-DIFF release
  floor as port_signatures.baseline.json (baseline_version 3.0.2, byte-identical
  to port_signatures.json). SEMVER-DIFF: none/none [ok].
- run-ci: wire SEMVER-DIFF blocking (was HELD); add --require-fields to
  IGNORE-LEDGER-VERIFY (strict field-completeness). RELEASE-FRESH already
  blocking; confirmed gates-before-publish.
- Add CHANGELOG.md with the 3.0.2 parity-release entry; META-CONSISTENT now
  runs the version<->changelog + non-empty checks (was WARN: no changelog).
- release.yml: add a `ci` job that runs the full run-ci gate set; `build`
  declares `needs: ci` (and `release` needs `build`), so a red gate blocks the
  release. Not enabled — tag/dispatch triggered only.
- Allowlist port_signatures.baseline.json in ARTIFACT_DENY_ALLOW.md and
  ROOT_HYGIENE_ALLOW.md (load-bearing release-floor file; must be at root, must
  not ship).

Full run-ci green (48 PASS, 0 FAIL): TEST, FMT, SEMVER-DIFF, IGNORE-LEDGER
--require-fields, RELEASE-FRESH, META-CONSISTENT, PACKAGE-SMOKE, DOC-AUDIT,
DOC-LANG-PURITY, SURFACE-DIFF, DOC-ENV, COUNT-CLAIM, ARTIFACT-DENY, ROOT-HYGIENE.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqshDQajCmDHD3xPo4CXMC
@mjerris
mjerris merged commit 4bf29dc into main Jul 14, 2026
3 checks passed
@mjerris
mjerris deleted the feat/wave3-wire-gates branch July 14, 2026 15:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant