Zero the 32-byte r scalar while preserving the signature encoding, length, s and recovery byte. The previous tail overwrite could leave r/s unchanged and normalize recovery 27 to 0, preserving a valid payment. Keep and strengthen no-claim/no-handler/no-settlement checks before serving the original valid payment.
A claim write that times out can still land. When the guard fails
closed the handler never ran, so a late claim would make every retry
look like a replay of work that never happened; delete it once it
lands. Type the snippet so it passes tsc --strict against the real
packages, and close idle keep-alive sockets in the test on Node 18.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claim from the verified payload and matched requirements in the
resource server's onAfterVerify hook, so a forged header can no longer
reserve a legitimate payment's key, and an invalid payment takes no
claim. Fail closed on a store error or timeout by returning an abort
(a throwing hook is skipped and would run the handler unguarded);
document fail-open as an explicit, idempotent-only choice. Cover
Permit2 (BigInt nonce) and keep claims until validBefore/deadline.
The test now drives the real @x402/express middleware with payments
signed by the real @x402/evm client and a stand-in facilitator that
checks EIP-3009 signatures with viem, so verification, the hook, the
handler and settlement run in their real order. Adds exact-pinned,
test-only devDependencies and refreshes the registry digest.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The signer picks the EIP-3009 validBefore and verification does not cap
it at maxTimeoutSeconds, so a fixed 900 s TTL could drop the claim for
a still-valid authorization whose settlement failed, and a copy would
run the handler again. Expire claims at validBefore + 60 s (900 s
floor, one-year ceiling) with SET NX EXAT, using node-redis's current
option form. Also wrap messageBytes for createHash so the snippet
typechecks.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The claim timeout stops a request from waiting but does not cancel the
command, so a connected-but-silent Redis could accumulate abandoned SETs.
commandsQueueMaxLength bounds them; past the cap, claims reject at once
and the guard fails open. The test asserts the cap and counts unhandled
rejections in its summary.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Connect to Redis in the background with an error listener and the
offline queue disabled, so an unavailable store never blocks startup
or crashes the process; bound each claim with a 250 ms timeout.
- Include the asset in EVM claim keys (EIP-3009 nonces are per token).
- Cap the payment header at 16 KB before storing anything, and note that
the path needs the same rate limits as any unauthenticated write.
- State the TTL rule: longer than maxTimeoutSeconds plus the slowest
handler run.
- tests/ci/agent-payment-x402-seller-guard.test.js runs the guard block
from all three documents: concurrent copies, key equivalence (EVM
re-encoding, asset, Solana fee-payer slot), offline and hanging store,
oversized and missing headers.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* ci: audit closed-issue delivery claims — cited PRs must actually be merged
Follow-up to #3223: an issue closed as 'fixed in #N' while #N was closed
without merging (or does not exist) leaves a completion claim that does not
hold. The weekly maintenance workflow now runs a read-only audit over issues
closed in the last 30 days, extracts delivery-claim PR references from issue
bodies and close-window comments, verifies each cited PR's merge state, and
reports findings to the step summary.
Design constraints:
- Read-only: no comments, no closes, no labels; findings are advisory and
the run always stays green so the weekly audit never blocks maintenance.
- Unverifiable counts as unmerged: a 404 PR or an API failure fails the
verdict, because an unverifiable claim is exactly the failure mode.
- Pure decision functions are exported for tests; a first live run against
this repository surfaced one real finding (#3408 cites #3060, which does
not resolve), included here as the motivating sample.
8 unit/contract tests: extraction, windowing (close comments included),
the #3223 unmerged-citation failure mode, the all-clear summary, workflow
contract, and a no-write guard.
* ci: rework audit evidence contract — claims vs context, four PR states, visible completeness
Revision per the #3522 review (reviewer ran the CLI through 19 controlled
cases plus a bounded live check of #3408):
- Bind findings to asserted delivery claims. Closing wording ('Delivered
through #N'), claim verbs (fixed/shipped/landed/resolved/...), and bare
'PR #N' inside closing comments are claims; historical mentions, quoted
lines, fenced examples, negated claims, and tracking-only references are
reported as contextual references and never produce findings. On the live
#3408 the audit now recognizes the closing claim #3500 (merged) instead of
flagging the historical #3060 text.
- Separate observed states: merged / open-unmerged / closed-unmerged /
unknown (404, rate limit, transient). Unknown claims are advisory manual-
verification items, not failed claims; each row carries the claim snippet,
its source link, and the observation time. Checked claims are listed even
when passing, so the report is traceable rather than an opaque all-clear.
- Paginate issue and comment collection (--paginate --slurp), bound comment
requests (200) and PR checks (100), and surface skipped pages, rate limits,
and retrieval failures as an explicit incomplete audit instead of an empty
all-clear. A live-run maxBuffer overflow on the paginated issue list was
caught and fixed (64MB); the audit reported it as incomplete before the fix.
- Scope the job to read access: job-level contents/issues/pull-requests read.
13 contract/unit tests including a CLI fixture (stub gh) that places the
relevant issue on page two and forces a comment-fetch failure.
* ci: report incomplete audit at PR check cap
---------
Co-authored-by: chenhz01 <chenhz01@users.noreply.github.com>
Co-authored-by: haelyra <49814733+haelyra@users.noreply.github.com>
The runner executed 422 files one process at a time, which is most of
the 12 to 40 minutes a CI lane spends in "Run tests". ECC_TEST_JOBS
above 1 now runs files through a pool of that many processes; output is
still buffered and printed per file, so logs read the same. The default
stays 1 and that path is the original synchronous spawnSync loop, so the
VM-driven runner test and the piped-output tests are unchanged.
ECC_TEST_ONLY is the mirror of ECC_TEST_SKIP: a comma-separated list of
path substrings, and only matching files run. CI uses it to give the
package-manager lanes just the suites that read the package-manager
variable instead of the whole suite.
Two real-process tests cover the pool (grouped output, counted failure,
summary last) and the ONLY filter.
validateInlineJs unescaped the shell body with four chained replaces,
so a backslash pair followed by n or t was unescaped twice: the pair
became one backslash, then the new backslash-n became a newline. A
valid hook command such as console.log('\\n') failed validation with
an unterminated string. CodeQL flags the chain as double unescaping.
One regex pass maps each escape exactly once. The regression test
feeds the escaped-backslash program through the validator CLI.
Extend the PR burst guard with an open-PR cap. On every opened or reopened
PR by a non-collaborator, the guard lists the repository's open PRs, keeps
the author's oldest `maxOpen` (10) open and closes the newer ones with a
bot comment that names the count and the limit. No lock, no maintainer
alert: the cap is about review capacity, not spam. PRs the burst logic
already closed in the same run are excluded so nothing is mutated twice.
Collaborators with write access stay exempt, dry run reports without
mutating, and the comment is deduplicated on a bot-authored marker.
Haley asked for this on 2026-10-19: each contributor should only have 10
to 15 PRs open at a time. Existing open PRs are not bulk-closed; the cap
applies as each author opens or reopens their next PR.
Verification: 22 unit tests and the HTTP workflow test pass,
validate-workflow-security passes, eslint and markdownlint clean. Dry run
against affaan-m/ECC on #3621 reports openCount 19 and nine cap excess
PRs for that author, with no writes.
Treat non-2xx activity responses as feed errors, preserve non-Markdown Copilot agent assets, and apply the reviewed reference escape parity correction with regenerated bindings. Allow the test runner to drain piped output on its existing success or failure exit status. Validate installed workflows and bounded real Node20/24 pipe regressions.
Follow up PR #3187 at 38b8c07f while preserving the original contribution history and all current-main helper bodies. Remove both CI safety-suite exclusions, clean stale imports and the warning glyph, retain shipped test/coverage entrypoints, and keep unknown test totals honest. The tree matches the fully tested 6246-pass/325-file tree; disposable Claude/OpenCode lifecycle passes.
The catalog gate validated only the first README project-tree block and
had no skills/commands counterpart to the agents pattern, so:
- README.md project tree (skills) and (commands) were never checked.
- A stale count in a second tree block was invisible because the agents
pattern used String.match with a non-global regex, which reads only the
first occurrence.
Both are now fail-closed. parseReadmeExpectations walks every tree block
for all three categories via matchAll, reports the offending line number
in the source label, and throws when an entry is missing entirely rather
than skipping it. syncEnglishReadme uses replaceAllOrThrow so --write
repairs every block instead of only the first; replaceOrThrow could not
be reused because it replaces only the first match and its regex.test()
probe is unsafe once the pattern carries the g flag.
README.md:847 documented 67 agents against an actual 68 and was never
checked, so it was corrected.
Fixtures in tests/ci/catalog.test.js and tests/ci/validators.test.js now
emit the skills and commands tree lines the gate requires, and both gain
regression coverage that fails against the previous parser (5 new tests).
* chore: retire the Everything Claude Code name, ECC only
Replace the expanded product name and the everything-claude-code slug
with ECC across READMEs, translated docs, harness folders, skills,
commands, scripts and examples. Repo URLs now point at affaan-m/ECC.
Rename repo-internal artifacts to ecc forms (ecc-conventions skill,
ecc-guardrails, ecc-research-playbook, ecc-team-config, ecc-instincts
with ecc-* ids) and update .claude/ecc-tools.json.
Legacy install ids, plugin dirs, package names and MCP prefixes stay
where existing installs resolve against them. The codex global-state
check and harness-audit repo detection accept the new name first and
the legacy one as a fallback. The Discord bot prefers ~/GitHub/ECC and
falls back to the nested legacy checkout path.
Refresh the skill-triggers registryDigest for the changed skill text.
* fix(ecc-tools): drop managed paths to the removed Claude repo skill
.claude/skills/<repo-skill>/SKILL.md was deleted in #2770 but stayed listed in
ecc-tools.json and the team config. Remove those entries and point the Claude
Code adapter at the existing .agents/skills/ecc-conventions/SKILL.md.
Preserve translated prose and the contributor regression suite while matching
canonical models and tools, including current GAN evaluator capabilities.
Preserve contributor history and current-main behavior while resolving the exact reviewed follow-up.
Source-PR: https://github.com/affaan-m/ECC/pull/3195
Source-Parent: ffb69744b0
Review-Manifest-SHA256: f732b9a4ceb5adced2990690c3857227088bbcccbb5114fcaaa581ecf16eb13f
Retain the last gate diagnosis through deadline and attempt exhaustion, preserve unrelated failures, and use immutable hostile-response fixtures.
Source-PR: https://github.com/affaan-m/ECC/pull/3195
Reviewed-Manifest-SHA256: d480e46e86a19ea13ff0072612abf61d3a716a5ce05d6ac4232d5eb5edfbcd39