Repository navigation
feat(skills): add the verify-interface verification skill - #16
Conversation
Verdict: PASS+NOTESHead verified: Goal (Antony): every V5 verification skill lands on Tool versionThe repo pins Journeys at head (driver
|
| Break | Documented by | Result |
|---|---|---|
| mutual-exclusivity rule moved after the date rules | docs/4.implementing.md rule order | CAUGHT validate-dates, validate-order |
| currency rule before amount rule | same | CAUGHT validate-fields, validate-order |
currency regex unanchored (EURO passes) |
"exactly three uppercase letters" | CAUGHT validate-fields |
trialing terminal |
only canceled is terminal |
CAUGHT status-vocabulary |
omitted intervalCount refused |
"an explicit intervalCount", defaults to 1 | CAUGHT validate-interval, validate-fields, validate-dates |
| statuses not in lifecycle order | TSDoc "in lifecycle order" | CAUGHT status-vocabulary |
SubscriptionPaymentError drops providerCode |
"Each carries providerCode" | CAUGHT error-classes, every-function |
SubscriptionPaymentError.name = base name |
error table | CAUGHT error-classes, every-function |
base SubscriptionError.name = Error |
error table | CAUGHT error-classes, every-function |
billingAnchor validated with trialEnd's value |
date rules | CAUGHT validate-dates |
| every broken rule joined into one message | "naming the first failed rule" | CAUGHT validate-dates, validate-fields, validate-order |
subscription.payment_succeeded renamed |
event table | did not build (src/tests compile) |
quarter interval added |
day, week, month, year | CAUGHT field-types, validate-interval, validate-order, wire-names |
CANCELLATION_TIMINGS unfrozen |
frozen vocabularies | CAUGHT wire-names |
inWholeSeconds off the whole second |
shipped helper TSDoc | CAUGHT suite-helpers, suite-defaults |
tarball drops dist/tests ("!dist/tests" in files) |
README conformance suite | CAUGHT suite-files |
tarball drops dist/errors.* |
package installs and loads | CAUGHT every-function, calls-through-core, suite-files |
16 built, 16 CAUGHT, 0 missed; 1 did not build, so it cannot ship.
V4 eval (agent-skills main 1fe3a82, --min-catch 1.0 --min-door-catch 1.0 --jobs 3)
Catch rate 12/12, door catch rate 3/3, unpatched head no false alarm 1/1 (control PASS+NOTES), $1.27 over 16 cases, exit 0 (eval/subs/eval.log). Reproduces the owner's 12/12, 3/3.
Repo gates
GITHUB_BASE_REF=campaign/integration pnpm run checks:Checks: 8 passed, 0 failed.Without that variable the suppressions check compares withmain(where@ts-expect-erroris 0) and fails. CI sets it, and CI is green.- api-diff (slot script) against origin/campaign/integration: API 3 entries unchanged, runtime 2 entries unchanged. Suppressions all 0 -> 0 except
@ts-expect-error1 -> 1.guardrails.suppressions.jsonis not in the diff. - Outside
.agents/and the.claude/skills/verify-interfacelink, the only changed file isAGENTS.md, with the one-line pointer to the skill. - CI on 7c96927: ci / Node .nvmrc, ci / checks, checks, GitGuardian pass. Conventional Commits, no attribution.
Notes (non-blocking)
- Most journeys run
<repo>/dist/index.js(journey-kit.tspacked()passescontext.repo), not the tarballnewextracted. The title says "the packed interface" and the PR body says the validators run "the packedValidateSubscriptionRequest". The code is the same build, so behaviour breaks are caught. Packaging breaks are caught here only becauseevery-functionandcalls-through-coreload the real tarball andsuite-filesreads thefilesfield. A rename to "the built interface" would be accurate. - The 0.2.17 pin cannot see #128. A re-proof that runs every feature on this repo's own toolchain will report PASS even with a failing journey outside the plan until the pack bump lands.
- SKILL.md (sync-written) says
--base origin/main; on this campaign the base isorigin/campaign/integration. That text belongs to tooling-configs.
Evidence: /home/antony/.cache/campaign/h8/verify/v5i/logs/ (subs.log, subs-verdict2.log, mut-subs.log, mut-subs-pack.log), /home/antony/.cache/campaign/h8/verify/v5i/eval/subs/, subs-checks.log, subs-apidiff.log.
Why
Antony wants every AntelopeJS verification skill (V5) on
campaign/integration.interface-subscriptionshas the sharedverify-interfacelayer from the pack and nothing of its own. A backend author importsCreateSubscription,CancelSubscription,ValidateSubscriptionRequest, the error classes and the status and event vocabularies, calls them through core next to a billing provider, and a provider author runs the shipped conformance helpers. This PR adds the repo-owned layer that drives that path. No module source changes: outside.agents/and.claude/the diff is the one-lineAGENTS.mdpointer thatantelopejs-sync --verify interfacewrites.What changed
verify.config.tsplus helper modules: 14 journeys over 12 features. The interface owns no billing logic, so its executable surface is the validator, the error classes, the frozen vocabularies and the fiveInterfaceFunctions. Journeys drive each the way its consumer does:every-function(pack) andcalls-through-coreload the packed interface inajs project devnext to a stub provider and call the five functions with the arguments a backend passes (idempotency key positionally, optional trailingprovidergiven and left out). The stub logs the arguments in order, the second view.validate-fields,validate-order,validate-intervalandvalidate-datesrun the packedValidateSubscriptionRequestagainst every rule indocs/4.implementing.md: messages, error class chain, first-rule order, strict future dates with a fixednow, epoch seconds refused, past dates accepted withoutnow,NaNand infinities always refused.status-vocabularyandwire-namespin the frozen status, end reason, interval, timing and event strings,antelopeSubscriptionand the 366-day cap.error-classespins names, messages,providerCode,statusand the declinedpayment.signaturesandfield-typescompile strict consumer probes against the packed.d.ts(argument order, optional fields, literal unions, whatJsonObjectaccepts and refuses).suite-helpers,suite-defaultsandsuite-filesload the shippedtests/supportmodule through the package's ownexportswith and without the README's environment variables.features/: smoke, calls, signatures, field-types, validation-fields, validation-order, validation-interval, validation-dates, statuses, vocabularies, errors, conformance (plus the README map).seeded-breaks/: 12 patches, one per non-README feature, each editing only files its feature covers (smoke editssrc/functions.ts, as the other interface skills do).seeded-doors/: contract, format, publish.src/types.ts(the status, interval, timing, event strings and the metadata key providers store and consumers branch on), contained bystatuses/status-vocabularyandvocabularies/wire-names; Contract (src/index.ts,src/functions.ts,package.json); Publish (release files). No Data, Outbound or Exposure door applies: the package stores nothing, calls nothing and serves nothing.callsproves what reaches a provider, not what a provider answers. Provider behaviour belongs to the conformance suite, which needs a real provider and credentials.Proofs
Head
7c96927onorigin/campaign/integrationfa3d013, run by/home/antony/.cache/campaign/h8/work/v5-interfaces-tools/proof.sh(logproofs/interface-subscriptions.log). Journeys in the order the driver ran them:Doors, containments, evidence after
clean, containers:Seeded breaks (
antelopejs-verify seeded, each against the unpatched control):Mutation check beyond the shipped patches: 32 further breaks of documented behaviour (validator rules and messages, error fields, vocabularies, frozen lists, optional fields,
JsonObject, exports, the conformance helpers) were applied one at a time to the working tree, each run through every journey bymutate.py(logproofs/mut-subscriptions.log). 26 are CAUGHT by at least one journey and 6 did not build (the contract suite insrc/testsfails to compile), so they cannot ship; none was MISSED.Agent-skills V4 eval (
mainat 1fe3a82,--min-catch 1.0 --min-door-catch 1.0 --jobs 3, exit 0):Repo checks and api-diff on head
7c96927:Attention
SKILL.md(shared layer, from sync) says--base origin/main; on this campaign the base isorigin/campaign/integration. That text belongs to tooling-configs.minor-bumpis not used: it needs the npm registry and this skill avoids a journey that can end NOT VERIFIED.