mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-06-13 19:51:24 +08:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f6d7067ff5 | |||
| ef13690fc3 | |||
| 8cb9dac8ec | |||
| cd176504d3 | |||
| 44e13541fa | |||
| e61bb043ed |
@@ -11,7 +11,7 @@
|
||||
{
|
||||
"name": "ecc",
|
||||
"source": "./",
|
||||
"description": "The most comprehensive Claude Code plugin — 60 agents, 232 skills, 75 legacy command shims, selective install profiles, and production-ready hooks for TDD, security scanning, code review, and continuous learning",
|
||||
"description": "The most comprehensive Claude Code plugin — 60 agents, 230 skills, 75 legacy command shims, selective install profiles, and production-ready hooks for TDD, security scanning, code review, and continuous learning",
|
||||
"version": "2.0.0-rc.1",
|
||||
"author": {
|
||||
"name": "Affaan Mustafa",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ecc",
|
||||
"version": "2.0.0-rc.1",
|
||||
"description": "Battle-tested Claude Code plugin for engineering teams — 60 agents, 232 skills, 75 legacy command shims, production-ready hooks, and selective install workflows evolved through continuous real-world use",
|
||||
"description": "Battle-tested Claude Code plugin for engineering teams — 60 agents, 230 skills, 75 legacy command shims, production-ready hooks, and selective install workflows evolved through continuous real-world use",
|
||||
"author": {
|
||||
"name": "Affaan Mustafa",
|
||||
"url": "https://x.com/affaanmustafa"
|
||||
|
||||
@@ -5,16 +5,13 @@ on:
|
||||
tags: ['v*']
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
contents: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
verify:
|
||||
name: Verify Release
|
||||
release:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
already_published: ${{ steps.npm_publish_state.outputs.already_published }}
|
||||
dist_tag: ${{ steps.npm_publish_state.outputs.dist_tag }}
|
||||
package_file: ${{ steps.pack.outputs.package_file }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -100,42 +97,6 @@ jobs:
|
||||
- For migration tips and compatibility notes, see README and CHANGELOG.
|
||||
EOF
|
||||
|
||||
- name: Pack npm artifact
|
||||
id: pack
|
||||
run: |
|
||||
npm pack --json > npm-pack.json
|
||||
PACKAGE_FILE=$(node -e "const fs = require('fs'); const data = JSON.parse(fs.readFileSync('npm-pack.json', 'utf8')); console.log(data[0].filename)")
|
||||
echo "package_file=${PACKAGE_FILE}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Upload release artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: ecc-release-artifacts
|
||||
path: |
|
||||
release_body.md
|
||||
${{ steps.pack.outputs.package_file }}
|
||||
if-no-files-found: error
|
||||
|
||||
publish:
|
||||
name: Publish Release
|
||||
runs-on: ubuntu-latest
|
||||
needs: verify
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Download release artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: ecc-release-artifacts
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
node-version: '20.x'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
|
||||
with:
|
||||
@@ -145,7 +106,7 @@ jobs:
|
||||
make_latest: ${{ contains(github.ref_name, '-') && 'false' || 'true' }}
|
||||
|
||||
- name: Publish npm package
|
||||
if: needs.verify.outputs.already_published != 'true'
|
||||
if: steps.npm_publish_state.outputs.already_published != 'true'
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: npm publish "${{ needs.verify.outputs.package_file }}" --access public --provenance --tag "${{ needs.verify.outputs.dist_tag }}"
|
||||
run: npm publish --access public --provenance --tag "${{ steps.npm_publish_state.outputs.dist_tag }}"
|
||||
|
||||
@@ -28,16 +28,13 @@ on:
|
||||
default: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
contents: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
verify:
|
||||
name: Verify Release
|
||||
release:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
already_published: ${{ steps.npm_publish_state.outputs.already_published }}
|
||||
dist_tag: ${{ steps.npm_publish_state.outputs.dist_tag }}
|
||||
package_file: ${{ steps.pack.outputs.package_file }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -117,42 +114,6 @@ jobs:
|
||||
- Claude marketplace/plugin identifier: \`everything-claude-code@everything-claude-code\`
|
||||
EOF
|
||||
|
||||
- name: Pack npm artifact
|
||||
id: pack
|
||||
run: |
|
||||
npm pack --json > npm-pack.json
|
||||
PACKAGE_FILE=$(node -e "const fs = require('fs'); const data = JSON.parse(fs.readFileSync('npm-pack.json', 'utf8')); console.log(data[0].filename)")
|
||||
echo "package_file=${PACKAGE_FILE}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Upload release artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: ecc-release-artifacts
|
||||
path: |
|
||||
release_body.md
|
||||
${{ steps.pack.outputs.package_file }}
|
||||
if-no-files-found: error
|
||||
|
||||
publish:
|
||||
name: Publish Release
|
||||
runs-on: ubuntu-latest
|
||||
needs: verify
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Download release artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: ecc-release-artifacts
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
node-version: '20.x'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
|
||||
with:
|
||||
@@ -163,7 +124,7 @@ jobs:
|
||||
make_latest: ${{ contains(inputs.tag, '-') && 'false' || 'true' }}
|
||||
|
||||
- name: Publish npm package
|
||||
if: needs.verify.outputs.already_published != 'true'
|
||||
if: steps.npm_publish_state.outputs.already_published != 'true'
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: npm publish "${{ needs.verify.outputs.package_file }}" --access public --provenance --tag "${{ needs.verify.outputs.dist_tag }}"
|
||||
run: npm publish --access public --provenance --tag "${{ steps.npm_publish_state.outputs.dist_tag }}"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Everything Claude Code (ECC) — Agent Instructions
|
||||
|
||||
This is a **production-ready AI coding plugin** providing 60 specialized agents, 232 skills, 75 commands, and automated hook workflows for software development.
|
||||
This is a **production-ready AI coding plugin** providing 60 specialized agents, 230 skills, 75 commands, and automated hook workflows for software development.
|
||||
|
||||
**Version:** 2.0.0-rc.1
|
||||
|
||||
@@ -150,7 +150,7 @@ Troubleshoot failures: check test isolation → verify mocks → fix implementat
|
||||
|
||||
```
|
||||
agents/ — 60 specialized subagents
|
||||
skills/ — 232 workflow skills and domain knowledge
|
||||
skills/ — 230 workflow skills and domain knowledge
|
||||
commands/ — 75 slash commands
|
||||
hooks/ — Trigger-based automations
|
||||
rules/ — Always-follow guidelines (common + per-language)
|
||||
|
||||
@@ -123,7 +123,7 @@ This repo is the raw code only. The guides explain everything.
|
||||
### v2.0.0-rc.1 — Surface Refresh, Operator Workflows, and ECC 2.0 Alpha (Apr 2026)
|
||||
|
||||
- **Dashboard GUI** — New Tkinter-based desktop application (`ecc_dashboard.py` or `npm run dashboard`) with dark/light theme toggle, font customization, and project logo in header and taskbar.
|
||||
- **Public surface synced to the live repo** — metadata, catalog counts, plugin manifests, and install-facing docs now match the actual OSS surface: 60 agents, 232 skills, and 75 legacy command shims.
|
||||
- **Public surface synced to the live repo** — metadata, catalog counts, plugin manifests, and install-facing docs now match the actual OSS surface: 60 agents, 230 skills, and 75 legacy command shims.
|
||||
- **Operator and outbound workflow expansion** — `brand-voice`, `social-graph-ranker`, `connections-optimizer`, `customer-billing-ops`, `ecc-tools-cost-audit`, `google-workspace-ops`, `project-flow-ops`, and `workspace-surface-audit` round out the operator lane.
|
||||
- **Media and launch tooling** — `manim-video`, `remotion-video-creation`, and upgraded social publishing surfaces make technical explainers and launch content part of the same system.
|
||||
- **Framework and product surface growth** — `nestjs-patterns`, richer Codex/OpenCode install surfaces, and expanded cross-harness packaging keep the repo usable beyond Claude Code alone.
|
||||
@@ -392,7 +392,7 @@ If you stacked methods, clean up in this order:
|
||||
/plugin list ecc@ecc
|
||||
```
|
||||
|
||||
**That's it!** You now have access to 60 agents, 232 skills, and 75 legacy command shims.
|
||||
**That's it!** You now have access to 60 agents, 230 skills, and 75 legacy command shims.
|
||||
|
||||
### Dashboard GUI
|
||||
|
||||
@@ -1423,7 +1423,7 @@ The configuration is automatically detected from `.opencode/opencode.json`.
|
||||
|---------|-------------|----------|--------|
|
||||
| Agents | PASS: 60 agents | PASS: 12 agents | **Claude Code leads** |
|
||||
| Commands | PASS: 75 commands | PASS: 35 commands | **Claude Code leads** |
|
||||
| Skills | PASS: 232 skills | PASS: 37 skills | **Claude Code leads** |
|
||||
| Skills | PASS: 230 skills | PASS: 37 skills | **Claude Code leads** |
|
||||
| Hooks | PASS: 8 event types | PASS: 11 events | **OpenCode has more!** |
|
||||
| Rules | PASS: 29 rules | PASS: 13 instructions | **Claude Code leads** |
|
||||
| MCP Servers | PASS: 14 servers | PASS: Full | **Full parity** |
|
||||
@@ -1585,7 +1585,7 @@ ECC is the **first plugin to maximize every major AI coding tool**. Here's how e
|
||||
|---------|------------|------------|-----------|----------|----------------|
|
||||
| **Agents** | 60 | Shared (AGENTS.md) | Shared (AGENTS.md) | 12 | N/A |
|
||||
| **Commands** | 75 | Shared | Instruction-based | 35 | 6 prompts |
|
||||
| **Skills** | 232 | Shared | 10 (native format) | 37 | Via instructions |
|
||||
| **Skills** | 230 | Shared | 10 (native format) | 37 | Via instructions |
|
||||
| **Hook Events** | 8 types | 15 types | None yet | 11 types | None |
|
||||
| **Hook Scripts** | 20+ scripts | 16 scripts (DRY adapter) | N/A | Plugin hooks | N/A |
|
||||
| **Rules** | 34 (common + lang) | 34 (YAML frontmatter) | Instruction-based | 13 instructions | 1 always-on file |
|
||||
|
||||
+1
-1
@@ -160,7 +160,7 @@ Copy-Item -Recurse rules/typescript "$HOME/.claude/rules/"
|
||||
/plugin list ecc@ecc
|
||||
```
|
||||
|
||||
**完成!** 你现在可以使用 60 个代理、232 个技能和 75 个命令。
|
||||
**完成!** 你现在可以使用 60 个代理、230 个技能和 75 个命令。
|
||||
|
||||
### multi-* 命令需要额外配置
|
||||
|
||||
|
||||
+34
-139
@@ -14,68 +14,39 @@ execution truth is split across:
|
||||
|
||||
## Current Evidence
|
||||
|
||||
As of 2026-05-18:
|
||||
As of 2026-05-17:
|
||||
|
||||
- GitHub queues are clean across `affaan-m/everything-claude-code`,
|
||||
`affaan-m/agentshield`, `affaan-m/JARVIS`, `ECC-Tools/ECC-Tools`, and
|
||||
`ECC-Tools/ECC-website`: the latest `platform-audit` sweep found 0 open PRs,
|
||||
0 open issues, 0 discussion maintainer-touch gaps, 0 answerable Q&A missing
|
||||
accepted answers, and 0 blocking dirty files when allowing the unrelated
|
||||
local `docs/drafts/` directory. The May 18 sync also refreshed
|
||||
`scripts/work-items.js sync-github` across all five tracked repos, leaving
|
||||
no open or blocked local work items.
|
||||
- Owner-wide queue cleanup is also inside the requested budget:
|
||||
`docs/releases/2.0.0-rc.1/owner-queue-cleanup-2026-05-18.md` records the
|
||||
live `gh search` sweep that closed 24 stale dependency-bot PRs and 72 stale
|
||||
legacy payments/0EM roadmap issues, then closed the 9 remaining stale,
|
||||
generated, conflicting, or test/noise PRs and the 5 remaining legacy,
|
||||
outreach, or placeholder issues. The broader `affaan-m` owner namespace is
|
||||
now at 0 open PRs and 0 open issues by live `gh search`. Archived repos
|
||||
touched during closure were restored to archived state.
|
||||
local `docs/drafts/` directory. The May 17 queue batch merged #1961, #1963,
|
||||
and #1953, closed/skipped incompatible #1962, and #1953 closed #1951.
|
||||
- GitHub discussions are current across those tracked repos:
|
||||
`affaan-m/everything-claude-code` has 58 total discussions and 0 without
|
||||
maintainer touch after May 15 maintainer updates on #73 and #1239; AgentShield,
|
||||
JARVIS, ECC Tools, and the ECC Tools website have discussions disabled or 0
|
||||
total discussions. `docs/architecture/discussion-response-playbook.md` now
|
||||
supplies the ITO-59 response categories, public templates, security-escalation
|
||||
path, and readback rules for future discussion batches.
|
||||
total discussions.
|
||||
- The current Linear roadmap contains 16 issue lanes (`ITO-44` through
|
||||
`ITO-59`) and five milestones: Security and Access Baseline, ECC 2.0 Preview
|
||||
and Publication, AgentShield Enterprise Iteration, ECC Tools Next-Level
|
||||
Platform, and Legacy Audit and Salvage.
|
||||
- Linear live sync is current for the May 18 merge and supply-chain batch:
|
||||
ITO-57 has a final emergency supply-chain refresh comment
|
||||
(`3fe5b2b7-c4fe-401c-a317-b40d72119cb3`), and the ECC platform project has
|
||||
the latest operator progress comment (`e32e5b7a-287b-4bf4-9ed7-314389a157e1`).
|
||||
Linear project status updates are disabled in this workspace, so the project
|
||||
comment is the supported external status surface.
|
||||
- The latest May 18 merge batch on `main` includes PR #1970 workflow-security
|
||||
validator bypass fixes, PR #1971 metrics bridge cost-reporting and warning
|
||||
de-dup fixes, PR #1972 `uncloud` skill activation structure, PR #1976
|
||||
OpenAI/AstraFlow provider response guards, ECC-Tools Wrangler OAuth billing
|
||||
readback mirror evidence, the `04d4d819` defensive-deny IOC scanner hardening
|
||||
recheck, `7911af4a` release OIDC publishing-scope hardening, `97567a91`
|
||||
release workflow line-ending normalization, and release evidence with a
|
||||
refreshed operator dashboard.
|
||||
- `docs/releases/2.0.0-rc.1/publication-evidence-2026-05-18.md` records the
|
||||
May 18 queue-zero state, current-head TanStack/Mini Shai-Hulud protection
|
||||
recheck, no-lifecycle npm install, npm audit/signature checks, AgentShield
|
||||
project `.claude` scan, Linear sync, work-items sync, operator dashboard
|
||||
refresh, PR #1976 provider-guard validation, ECC-Tools Wrangler OAuth billing
|
||||
readback evidence, defensive-deny IOC scanner coverage, and current-head CI
|
||||
success for `97567a91`; a detached clean-worktree preview-pack smoke from
|
||||
`680aeff0` passed 5/5 with digest `0ed831dbd0cf`.
|
||||
- `docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-18.md`
|
||||
regenerates the ITO-44 prompt-to-artifact dashboard from live platform audit
|
||||
evidence: PR queue, issue queue, discussion queue, local worktree gate,
|
||||
dashboard generation, and supply-chain loop are current; publication, plugin,
|
||||
billing, AgentShield, ECC Tools, legacy, and Linear/productized sync lanes
|
||||
remain the next work.
|
||||
- Linear live sync is current for the May 17 merge batch: ITO-57 has a new
|
||||
supply-chain protection comment (`ca703b95-41a1-403e-9bc4-3d68edd4d4a3`),
|
||||
and the ECC platform project has a new operator progress snapshot
|
||||
(`6c4d1b92-95cf-4ea1-84fd-cbea36f24d1a`).
|
||||
- `docs/releases/2.0.0-rc.1/publication-evidence-2026-05-17.md` records the
|
||||
May 17 queue-zero state, Japanese localization merge, Dependabot TypeScript
|
||||
and Node type merges, post-merge ja-JP lint repair, Mini Shai-Hulud/TanStack
|
||||
local protection recheck, npm audit/signature checks, current operator
|
||||
dashboard, and GitHub CI success for `99dd6ac0`.
|
||||
- `docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-17.md`
|
||||
regenerates the ITO-44 prompt-to-artifact dashboard from live platform audit
|
||||
evidence: PR queue, issue queue, discussion queue, local worktree gate,
|
||||
dashboard generation, and supply-chain loop are current; publication, plugin,
|
||||
billing, AgentShield, ECC Tools, legacy, and Linear/productized sync lanes
|
||||
remain the next work.
|
||||
- `docs/releases/2.0.0-rc.1/publication-evidence-2026-05-16.md` records the
|
||||
queue, discussion, Linear roadmap, ECC Tools access, Mini Shai-Hulud/TanStack
|
||||
full-campaign follow-up, scheduled supply-chain watch coverage, no-lifecycle
|
||||
@@ -93,13 +64,9 @@ As of 2026-05-18:
|
||||
- `npm run harness:audit -- --format json` reports 70/70 on current `main`.
|
||||
- `npm run observability:ready` reports 21/21 readiness on current `main`,
|
||||
including the GitHub/Linear/handoff/roadmap progress-sync contract.
|
||||
- GitHub CI run `26017368895` completed successfully for
|
||||
`04d4d81938b20ac2bac1f0025145ab77d6a59f5f`, including Validate Components,
|
||||
- GitHub CI run `25983803011` completed successfully for
|
||||
`99dd6ac0db20fce51713b6a1c92515d2453b769e`, including Validate Components,
|
||||
Coverage, Lint, Security Scan, and the full Node/package-manager matrix.
|
||||
- Supply-Chain Watch run `26009825837` completed successfully for
|
||||
`3b7e0ba30a027ffd3319c2f145c63076c296d80a`, including no-lifecycle install,
|
||||
npm audit/signature verification, scanner fixtures, advisory-source
|
||||
fixtures, IOC/advisory artifact generation, and workflow-security validation.
|
||||
- PR #1846 merged as `797f283036904128bb1b348ae62019eb9f08cf39` and made
|
||||
npm registry signature verification a durable workflow-security gate:
|
||||
workflows that run `npm audit` now need `npm audit signatures`.
|
||||
@@ -294,71 +261,10 @@ As of 2026-05-18:
|
||||
verify the Marketplace test account, internal API token presence, and
|
||||
billing-readiness endpoint before making the privileged readback call.
|
||||
- ECC-Tools commit `eb6941290b2fa70db01a51084e9e79a160238468`
|
||||
recorded the first live production readback state: Cloudflare Worker secret
|
||||
names include `INTERNAL_API_SECRET`, but no Marketplace-managed account could
|
||||
pass the announcement gate yet.
|
||||
- ECC-Tools commit `95d0bec69dbcf364ed084e983a40d0a94d443d16`
|
||||
adds repeatable aggregate production KV readback with
|
||||
`npm run billing:kv-readback`: the latest API-authenticated run found 253
|
||||
`account-billing:*` records and 253 `billing-state:*` records, but 0
|
||||
Marketplace-managed Pro `billing-state:*` records, so native-payments copy
|
||||
remains blocked until `--require-ready` and the official internal
|
||||
announcement gate pass.
|
||||
- ECC-Tools commit `285967807ea7b5eb3146bc984fb2229db67d4290`
|
||||
requires GitHub Marketplace webhook provenance on Pro billing-state records
|
||||
before native-payments announcement readiness can pass. The CI run
|
||||
`26013559229` succeeded for the pushed head.
|
||||
- ECC-Tools commit `42653f9140c232961280d961ed76a6142433cfa1`
|
||||
adds `npm run billing:kv-readback -- --wrangler` so operators can run the
|
||||
aggregate production KV readback through an authenticated Wrangler OAuth
|
||||
session instead of requiring a separate Cloudflare API token/global key. CI
|
||||
run `26016223013` succeeded, and the latest live readback found 253
|
||||
`account-billing:*` records and 253 `billing-state:*` records with 194
|
||||
marketplace/free states, 59 Stripe/pro states, 0 Marketplace Pro states, 0
|
||||
ready-like Marketplace Pro states, and 0 parse failures. Native-payments
|
||||
copy remains blocked until a real Marketplace-managed Pro webhook creates
|
||||
billing-state provenance and `--require-ready` plus the official internal
|
||||
announcement gate pass.
|
||||
- ECC-Tools commit `632e059e51b6e1297ba118807c8b5b2adbac74ce`
|
||||
adds target account billing readback with `npm run billing:kv-readback -- --account <github-login> --require-ready`.
|
||||
The report redacts the account login and raw KV keys, emits only a stable
|
||||
fingerprint plus sanitized readiness booleans, and now requires both
|
||||
`account-billing:<login>` and `billing-state:<login>` before a target
|
||||
Marketplace Pro test account can pass the native-payments announcement
|
||||
readback gate. CI run `26018941515` succeeded. The 2026-05-18 live recheck
|
||||
split out Linear ITO-61 for the target-account blocker.
|
||||
- ECC-Tools commit `d5f60db` adds sanitized Marketplace-source provenance
|
||||
counts to `npm run billing:kv-readback`, including
|
||||
`marketplaceSourceRecords`, `marketplaceSourceWithWebhookEvidence`,
|
||||
`marketplaceSourceWithoutWebhookEvidence`, `byMarketplacePlanName`, and
|
||||
`byMarketplaceEventAction`. The 2026-05-18 live Wrangler OAuth readback now
|
||||
works and found 256 account-billing records, 256 billing-state records, 197
|
||||
Marketplace-source records, 59 Stripe-source records, 53 Pro records, 0
|
||||
Marketplace Pro records, 4 Marketplace webhook-provenance records, all
|
||||
`Open Source` purchases, and 193 Marketplace-source records without webhook
|
||||
provenance. Native-payments copy remains blocked by Linear ITO-61 until a
|
||||
real Marketplace-managed Pro webhook creates target account provenance and
|
||||
`billing:kv-readback -- --wrangler --wrangler-bin ./node_modules/.bin/wrangler --account <github-login> --require-ready`
|
||||
plus the official internal announcement gate pass.
|
||||
- ECC-Tools commit `13cd3fc` normalizes billing-state key casing so
|
||||
Marketplace webhook writes and announcement readbacks agree on GitHub login
|
||||
case; current-head CI `26037611421` passed. The code-side readback hardening
|
||||
remains green, but it does not create live Marketplace Pro state.
|
||||
- ECC-Tools commit `69ca535` surfaces hosted team-learning feedback controls:
|
||||
harness compatibility and team-backlog routing now show retention days,
|
||||
deletion route/SLA, and opt-out route before adaptive recommendations are
|
||||
routed into team-owned queues. Linear ITO-52 is Done with CI `26054455434`.
|
||||
- ECC-Tools commit `e56fc1a` updates the lockfile for
|
||||
`brace-expansion@5.0.6` and fixed Dependabot alert 44 for CVE-2026-45149;
|
||||
GitHub API reported `state: fixed` at `2026-05-18T19:10:15Z` and current-head
|
||||
CI `26054671308` passed.
|
||||
- The latest ITO-61 readback retry narrowed the blocker: Wrangler OAuth now
|
||||
works, the safe aggregate readback has 0 parse failures and still reports 0
|
||||
Marketplace Pro records, and `billing:announcement-gate -- --preflight` is
|
||||
missing the target Marketplace account plus `INTERNAL_API_SECRET`.
|
||||
Native-payments copy remains blocked until the target Pro readback and live
|
||||
announcement gate pass. Linear comment
|
||||
`6904e4fb-bec7-4787-90e2-759f077a628c` records the redacted readback counts.
|
||||
records live production readback state: Cloudflare Worker secret names include
|
||||
`INTERNAL_API_SECRET`, but the production KV namespace currently has no
|
||||
`account-billing:*` or `billing-state:*` records, so no
|
||||
Marketplace-managed account can pass the announcement gate yet.
|
||||
- Handoff `ecc-supply-chain-audit-20260513-0645.md` under
|
||||
`~/.cluster-swarm/handoffs/`
|
||||
records the May 13 supply-chain sweep: no active lockfile/manifest hit for
|
||||
@@ -715,23 +621,23 @@ is not complete unless the evidence column exists and has been freshly verified.
|
||||
|
||||
| Prompt requirement | Required artifact or gate | Current evidence | Status |
|
||||
| --- | --- | --- | --- |
|
||||
| Keep public PRs below 20 | Repo-family PR recheck | 0 open PRs across `everything-claude-code`, AgentShield, JARVIS, `ECC-Tools/ECC-Tools`, and `ECC-Tools/ECC-website` on 2026-05-18 after merging PR #1976 and refreshing platform audit evidence | Complete |
|
||||
| Keep public issues below 20 | Repo-family issue recheck | 0 open issues across `everything-claude-code`, AgentShield, JARVIS, `ECC-Tools/ECC-Tools`, and `ECC-Tools/ECC-website` on 2026-05-18 after the live platform audit refresh | Complete |
|
||||
| Manage repository discussions | Repo-family discussion recheck plus response playbook | Platform audit reports 0 discussion maintainer-touch gaps and 0 answerable Q&A missing accepted answers; trunk still has 58 total discussions; `docs/architecture/discussion-response-playbook.md` distinguishes support, maintainer coordination, stale/concluded, release, informational, and security-sensitive response paths | Complete |
|
||||
| Manage PR discussions | PR review/comment closure plus merge/close state | ECC #1976 merged after maintainer follow-up validation; no open tracked PRs remain | Complete |
|
||||
| Keep public PRs below 20 | Repo-family PR recheck | 0 open PRs across `everything-claude-code`, AgentShield, JARVIS, `ECC-Tools/ECC-Tools`, and `ECC-Tools/ECC-website` on 2026-05-17 after merging ECC #1961, #1963, and #1953 and closing/skipping incompatible #1962 | Complete |
|
||||
| Keep public issues below 20 | Repo-family issue recheck | 0 open issues across `everything-claude-code`, AgentShield, JARVIS, `ECC-Tools/ECC-Tools`, and `ECC-Tools/ECC-website` on 2026-05-17; #1951 closed with #1953 | Complete |
|
||||
| Manage repository discussions | Repo-family discussion recheck | Platform audit reports 0 discussion maintainer-touch gaps and 0 answerable Q&A missing accepted answers; trunk still has 58 total discussions | Complete |
|
||||
| Manage PR discussions | PR review/comment closure plus merge/close state | ECC #1961, #1963, and #1953 merged after maintainer validation; no open tracked PRs remain | Complete |
|
||||
| Salvage useful stale work | `docs/stale-pr-salvage-ledger.md` plus `docs/legacy-artifact-inventory.md` | Ledger records salvaged, superseded, skipped, and manual-review tails; #1815-#1818 added cost tracking, skill scout, frontend design guidance, code-reviewer false-positive guardrails, and the May 12 gap pass; #1687, #1609, #1563, #1564, and #1565 localization tails are attached to Linear ITO-55 for language-owner review and no automatic import remains release-blocking | Complete; repeat legacy scan before release |
|
||||
| ECC 2.0 preview pack ready | Release docs, quickstart, publication readiness, release notes | `docs/releases/2.0.0-rc.1/` and readiness docs are in-tree; May 18 evidence records queue-zero state, #1970/#1971/#1972/#1976 merge batch, supply-chain recheck, defensive-deny IOC scanner hardening, npm no-lifecycle install/audit/signature gates, Linear sync, refreshed operator dashboard, provider-guard validation, ECC-Tools Wrangler OAuth billing readback evidence, successful current-head CI on `04d4d819`, and detached clean-worktree preview-pack smoke digest `59bbf2630a44` | Needs final release approval |
|
||||
| ECC 2.0 preview pack ready | Release docs, quickstart, publication readiness, release notes | `docs/releases/2.0.0-rc.1/` and readiness docs are in-tree; May 17 evidence records queue-zero state, localized docs merge, supply-chain recheck, lint/test/security gates, operator dashboard, and successful GitHub CI on `99dd6ac0` | Needs final clean-checkout release approval |
|
||||
| Hermes specialized skills included safely | Hermes setup/import docs and sanitized skill surface | Hermes setup and import playbook are public; secrets stay local | Needs final release review |
|
||||
| Naming and rename readiness | Naming matrix across package/plugin/docs/social surfaces | `docs/releases/2.0.0-rc.1/naming-and-publication-matrix.md` records current package, repo, Claude plugin, Codex plugin, OpenCode, and npm availability evidence | Complete for rc.1; post-rc rename remains future work |
|
||||
| Claude and Codex plugin publication | Contact/submission path with required artifacts and status | Publication readiness, naming matrix, and May 12 dry-run evidence document plugin validation, clean-checkout Claude tag/install smoke, and Codex marketplace CLI shape | Needs explicit approval for real tag/push and marketplace submission |
|
||||
| Articles, tweets, and announcements | X thread, LinkedIn copy, GitHub release copy, push checklist | Draft launch collateral exists under rc.1 release docs | Needs URL-backed refresh |
|
||||
| AgentShield enterprise iteration | Policy gates, SARIF, packs, provenance, corpus, HTML reports, exception lifecycle audit, baseline drift Action/CLI surfaces, evidence-pack redaction, harness adapter registry, enterprise research roadmap, supply-chain hardened release path, CI-safe baseline fingerprints, corpus accuracy recommendations, remediation workflow phases, env proxy hijack corpus coverage, Mini Shai-Hulud full-campaign package IOCs, CI-provenance evidence packs, plugin-cache runtime-confidence triage, evidence-pack consumer readback, fleet-level evidence-pack routing, fleet review items, fleet review ticket payloads, checksum-backed policy export, checksum-verified policy promotion, policy promotion review items, package-manager hardening drift detection, npm age-gate guidance correction, workflow action-runtime pin refresh, package-manager hardening Action outputs, policy-promotion Action outputs, ECC-Tools hosted consumption of promotion Action outputs, ECC-Tools operator-visible promotion output values, and ECC-Tools hosted promotion judge audit traces | PRs #53, #55-#64, #67-#69, and #78-#92 landed with test evidence, ECC-Tools #76 consumes the fleet-summary output in hosted security review, #77 surfaces source evidence paths in hosted finding output, and #78 links fleet routes to harness owner review; AgentShield #91 adds `agentshield policy export` bundles for branch-protection review and downstream promotion; AgentShield #92 adds `agentshield policy promote` with digest verification, tamper rejection, explicit pack selection, dry-run review, and JSON output before writing active policy; AgentShield commit `87aec47` adds `reviewItems` for digest evidence, owner review, protected rollout PR handoff, and runtime smoke testing with green local and remote CI; AgentShield commit `28d08c7` adds package-manager hardening drift detection for plaintext registry credentials, lifecycle-script enablement, and weak pnpm/Yarn release-age cooldowns with green local and remote CI; AgentShield commit `659f569` refreshes all workflow action runtime pins to SHA-pinned checkout v6.0.2 and setup-node v6.4.0 with green remote CI and no remaining action-runtime deprecation annotation; AgentShield commit `ee585cd` corrects npm release-age guidance by flagging unsupported npm age keys and keeping enforceable cooldown findings on pnpm/Yarn with green local and remote CI; AgentShield commit `1124535` exposes package-manager hardening status/count outputs and a redacted job-summary section for registry credentials, lifecycle scripts, and release-age gates with green local and remote CI; AgentShield commit `1593925` exposes policy-promotion status/count/digest outputs plus job-summary review items for owner approval, protected rollout, and runtime smoke, and marks runtime smoke verified when the same Action job scans with the promoted policy; AgentShield commit `840952a` adds Linear/operator-ready fleet review ticket payloads and expands current Mini Shai-Hulud IOC breadcrumbs with green local and remote CI; ECC-Tools commit `8658951` routes those policy-promotion Action outputs into hosted security review findings and Hosted Promotion Readiness scoring; ECC-Tools commit `16c537f` renders policy-promotion status, pack, review item count, action-required count, and digest in hosted security job comments/check-runs; ECC-Tools commit `05d4e82` renders hosted promotion judge request fingerprints and allowed-citation counts without raw provider output; native PDF export deferred in favor of self-contained HTML plus print-to-PDF until explicit enterprise demand appears; `docs/architecture/agentshield-enterprise-research-roadmap.md` now has baseline drift, evidence-pack bundle, redaction, adapter-registry, supply-chain hardening, hashed baseline fingerprints, corpus accuracy recommendation, remediation workflow, env proxy hijack corpus, Mini Shai-Hulud full-campaign package-table, `ci-context.json` provenance, `plugin-cache` confidence, `evidence-pack inspect` readback, `evidence-pack fleet` routing, fleet `reviewItems`, fleet review ticket payloads, policy export, policy promotion, policy promotion `reviewItems`, package-manager hardening Action outputs, policy-promotion Action outputs, hosted consumption of promotion Action outputs, operator-visible promotion output values, and hosted promotion judge audit traces landed | Next workflow automation should deepen live operator approval/readback after Marketplace/payment gates |
|
||||
| ECC Tools next-level app | Billing audit, PR checks, deep analyzer, sync backlog, evaluator/RAG corpus, analysis-depth readiness, hosted execution planning, hosted CI diagnostics, hosted security evidence review, hosted harness compatibility audit, hosted reference-set evaluation, hosted AI routing/cost review, hosted team backlog routing, hosted depth-plan check-run, PR-comment hosted job dispatch, hosted job result history/check-runs, hosted result status command, status-aware depth-plan recommendations, hosted promotion readiness, hosted promotion output scoring, hosted promotion retrieval planning, hosted promotion judge contract, gated hosted promotion judge execution, hosted promotion judge audit trace, payment-announcement readiness, billing announcement preflight, aggregate production billing KV readback, Marketplace webhook provenance, target-account billing readback, Marketplace-source provenance counts, AgentShield fleet-summary hosted routing, hosted finding evidence paths, harness-route policy linking, policy-promotion Action-output hosted telemetry, and operator-visible promotion output values | PRs #26-#43 plus #53-#78 landed with test evidence, including AgentShield evidence-pack gap routing, canonical bundle recognition, supply-chain signature gates, PR draft follow-up Linear tracking, evidence-backed/deep-ready repository classification, the `/api/analysis/depth-plan` hosted job plan, `/api/analysis/jobs/ci-diagnostics`, `/api/analysis/jobs/security-evidence-review`, `/api/analysis/jobs/harness-compatibility-audit`, `/api/analysis/jobs/reference-set-evaluation`, `/api/analysis/jobs/ai-routing-cost-review`, `/api/analysis/jobs/team-backlog-routing`, the `ECC Tools / Hosted Depth Plan` check-run, `/ecc-tools analyze --job ...` PR-comment dispatch, non-blocking per-hosted-job result check-runs backed by 30-day result cache records, `/ecc-tools analyze --job status` cache lookup, cache-aware next-job recommendations in the depth-plan check-run, the `ECC Tools / Hosted Promotion Readiness` corpus-backed PR check-run, deterministic hosted-output scoring against cached completed job artifacts/findings, ranked retrieval/model-prompt planning, the fail-closed `hosted-promotion-judge.v1` request contract, opt-in live model-judge execution behind hosted evidence, entitlement, budget, provider, executor, strict JSON, and citation gates, hosted promotion judge request fingerprints plus allowed-citation audit trails, a fail-closed `/api/billing/readiness` `announcementGate` for native GitHub payments claims, `npm run billing:announcement-gate` plus `--preflight` as the non-secret operator verifier, hosted security findings for AgentShield fleet summaries, an `Evidence` column in hosted finding comments/check-runs, hosted harness findings that route AgentShield fleet target paths to harness owners, ECC-Tools commit `8658951` routing AgentShield policy-promotion Action outputs into hosted security review and promotion-readiness scoring, ECC-Tools commit `16c537f` rendering policy-promotion status/pack/count/digest values directly in hosted security job comments/check-runs, ECC-Tools commit `05d4e82` rendering model-judge audit traces without exposing raw provider output, ECC-Tools commit `91a441b` adding the safe billing announcement preflight path, ECC-Tools commit `eb69412` recording the initial production readback state, ECC-Tools commit `95d0bec` adding `npm run billing:kv-readback` with aggregate account-billing and billing-state records but 0 Marketplace Pro billing-state records, ECC-Tools commit `2859678` requiring webhook-derived Marketplace provenance before announcement readiness, ECC-Tools commit `42653f9` adding Wrangler OAuth readback, ECC-Tools commit `632e059` adding sanitized target-account readback that requires both target key families before `--require-ready` can pass, and ECC-Tools commit `d5f60db` adding sanitized Marketplace plan/action provenance counts; the latest 2026-05-18 live Wrangler OAuth recheck found 256 account-billing records, 256 billing-state records, 197 Marketplace-source records, 4 Marketplace webhook-provenance records, all `Open Source`, and 0 Marketplace Pro records, then updated Linear ITO-61 with the data/provisioning blocker | Next work is create or verify Marketplace-managed Pro target billing-state with webhook provenance, configure target account plus `INTERNAL_API_SECRET`, then run `billing:kv-readback -- --wrangler --wrangler-bin ./node_modules/.bin/wrangler --account <github-login> --require-ready`, followed by the live announcement gate |
|
||||
| AgentShield enterprise iteration | Policy gates, SARIF, packs, provenance, corpus, HTML reports, exception lifecycle audit, baseline drift Action/CLI surfaces, evidence-pack redaction, harness adapter registry, enterprise research roadmap, supply-chain hardened release path, CI-safe baseline fingerprints, corpus accuracy recommendations, remediation workflow phases, env proxy hijack corpus coverage, Mini Shai-Hulud full-campaign package IOCs, CI-provenance evidence packs, plugin-cache runtime-confidence triage, evidence-pack consumer readback, fleet-level evidence-pack routing, fleet review items, checksum-backed policy export, checksum-verified policy promotion, policy promotion review items, package-manager hardening drift detection, npm age-gate guidance correction, workflow action-runtime pin refresh, package-manager hardening Action outputs, policy-promotion Action outputs, ECC-Tools hosted consumption of promotion Action outputs, ECC-Tools operator-visible promotion output values, and ECC-Tools hosted promotion judge audit traces | PRs #53, #55-#64, #67-#69, and #78-#92 landed with test evidence, ECC-Tools #76 consumes the fleet-summary output in hosted security review, #77 surfaces source evidence paths in hosted finding output, and #78 links fleet routes to harness owner review; AgentShield #91 adds `agentshield policy export` bundles for branch-protection review and downstream promotion; AgentShield #92 adds `agentshield policy promote` with digest verification, tamper rejection, explicit pack selection, dry-run review, and JSON output before writing active policy; AgentShield commit `87aec47` adds `reviewItems` for digest evidence, owner review, protected rollout PR handoff, and runtime smoke testing with green local and remote CI; AgentShield commit `28d08c7` adds package-manager hardening drift detection for plaintext registry credentials, lifecycle-script enablement, and weak pnpm/Yarn release-age cooldowns with green local and remote CI; AgentShield commit `659f569` refreshes all workflow action runtime pins to SHA-pinned checkout v6.0.2 and setup-node v6.4.0 with green remote CI and no remaining action-runtime deprecation annotation; AgentShield commit `ee585cd` corrects npm release-age guidance by flagging unsupported npm age keys and keeping enforceable cooldown findings on pnpm/Yarn with green local and remote CI; AgentShield commit `1124535` exposes package-manager hardening status/count outputs and a redacted job-summary section for registry credentials, lifecycle scripts, and release-age gates with green local and remote CI; AgentShield commit `1593925` exposes policy-promotion status/count/digest outputs plus job-summary review items for owner approval, protected rollout, and runtime smoke, and marks runtime smoke verified when the same Action job scans with the promoted policy; ECC-Tools commit `8658951` routes those policy-promotion Action outputs into hosted security review findings and Hosted Promotion Readiness scoring; ECC-Tools commit `16c537f` renders policy-promotion status, pack, review item count, action-required count, and digest in hosted security job comments/check-runs; ECC-Tools commit `05d4e82` renders hosted promotion judge request fingerprints and allowed-citation counts without raw provider output; native PDF export deferred in favor of self-contained HTML plus print-to-PDF until explicit enterprise demand appears; `docs/architecture/agentshield-enterprise-research-roadmap.md` now has baseline drift, evidence-pack bundle, redaction, adapter-registry, supply-chain hardening, hashed baseline fingerprints, corpus accuracy recommendation, remediation workflow, env proxy hijack corpus, Mini Shai-Hulud full-campaign package-table, `ci-context.json` provenance, `plugin-cache` confidence, `evidence-pack inspect` readback, `evidence-pack fleet` routing, fleet `reviewItems`, policy export, policy promotion, policy promotion `reviewItems`, package-manager hardening Action outputs, policy-promotion Action outputs, hosted consumption of promotion Action outputs, operator-visible promotion output values, and hosted promotion judge audit traces landed | Next workflow automation should deepen live operator approval/readback after Marketplace/payment gates |
|
||||
| ECC Tools next-level app | Billing audit, PR checks, deep analyzer, sync backlog, evaluator/RAG corpus, analysis-depth readiness, hosted execution planning, hosted CI diagnostics, hosted security evidence review, hosted harness compatibility audit, hosted reference-set evaluation, hosted AI routing/cost review, hosted team backlog routing, hosted depth-plan check-run, PR-comment hosted job dispatch, hosted job result history/check-runs, hosted result status command, status-aware depth-plan recommendations, hosted promotion readiness, hosted promotion output scoring, hosted promotion retrieval planning, hosted promotion judge contract, gated hosted promotion judge execution, hosted promotion judge audit trace, payment-announcement readiness, billing announcement preflight, production Marketplace readback state, AgentShield fleet-summary hosted routing, hosted finding source-evidence surfacing, harness policy-route review, policy-promotion Action-output hosted telemetry, and operator-visible promotion output values | PRs #26-#43 plus #53-#78 landed with test evidence, including AgentShield evidence-pack gap routing, canonical bundle recognition, supply-chain signature gates, PR draft follow-up Linear tracking, evidence-backed/deep-ready repository classification, the `/api/analysis/depth-plan` hosted job plan, `/api/analysis/jobs/ci-diagnostics`, `/api/analysis/jobs/security-evidence-review`, `/api/analysis/jobs/harness-compatibility-audit`, `/api/analysis/jobs/reference-set-evaluation`, `/api/analysis/jobs/ai-routing-cost-review`, `/api/analysis/jobs/team-backlog-routing`, the `ECC Tools / Hosted Depth Plan` check-run, `/ecc-tools analyze --job ...` PR-comment dispatch, non-blocking per-hosted-job result check-runs backed by 30-day result cache records, `/ecc-tools analyze --job status` cache lookup, cache-aware next-job recommendations in the depth-plan check-run, the `ECC Tools / Hosted Promotion Readiness` corpus-backed PR check-run, deterministic hosted-output scoring against cached completed job artifacts/findings, ranked retrieval/model-prompt planning, the fail-closed `hosted-promotion-judge.v1` request contract, opt-in live model-judge execution behind hosted evidence, entitlement, budget, provider, executor, strict JSON, and citation gates, hosted promotion judge request fingerprints plus allowed-citation audit trails, a fail-closed `/api/billing/readiness` `announcementGate` for native GitHub payments claims, `npm run billing:announcement-gate` plus `--preflight` as the non-secret operator verifier, hosted security findings for AgentShield fleet summaries, an `Evidence` column in hosted finding comments/check-runs, hosted harness findings that route AgentShield fleet target paths to harness owners, ECC-Tools commit `8658951` routing AgentShield policy-promotion Action outputs into hosted security review and promotion-readiness scoring, ECC-Tools commit `16c537f` rendering policy-promotion status/pack/count/digest values directly in hosted security job comments/check-runs, ECC-Tools commit `05d4e82` rendering model-judge audit traces without exposing raw provider output, ECC-Tools commit `91a441b` adding the safe billing announcement preflight path, and ECC-Tools commit `eb69412` recording that production has no Marketplace billing-state KV records yet | Next work is complete Marketplace purchase/webhook readback, then run the live announcement gate |
|
||||
| GitGuardian/Dependabot/CodeRabbit-style checks | Non-blocking taxonomy, deterministic follow-up checks, and local supply-chain gates | ECC-Tools risk taxonomy check plus follow-up signals landed, including Skill Quality, Deep Analyzer Evidence, Analyzer Corpus Evidence, RAG/Evaluator Evidence, PR Review/Salvage Evidence, and AgentShield evidence-pack evidence; #1846 added npm registry signature gates; #1848 added the supply-chain incident-response playbook and `pull_request_target` cache-poisoning validator guard; #1851 added the privileged checkout credential-persistence guard; AgentShield #78, JARVIS #13, and ECC-Tools #53 applied the same hardening outside trunk | Current supply-chain gate complete; deeper hosted review features remain future |
|
||||
| Harness-agnostic learning system | Audit, adapter matrix, observability, traces, promotion loop | Audit/adapters/observability gates plus `docs/architecture/evaluator-rag-prototype.md`, `examples/evaluator-rag-prototype/`, and ECC-Tools PR #40 define read-only stale-salvage, billing-readiness, CI-failure-diagnosis, harness-config-quality, AgentShield policy-exception, skill-quality evidence, deep-analyzer evidence, and RAG/evaluator comparison scenarios with trace, report, playbook, verifier, and predictive-check artifacts; ECC-Tools PRs #68-#72 now turn that corpus into a deterministic PR check-run gate with cached hosted-output scoring, ranked retrieval candidates, a model prompt seed, a fail-closed hosted model-judge request contract, and opt-in live model execution behind strict hosted-evidence gates | Deterministic hosted PR check, cached output scoring, retrieval planning, judge contract, and gated model execution integrated |
|
||||
| Linear roadmap is detailed | Linear project status plus repo mirror | Repo mirror exists; issue creation was retried on 2026-05-12 and remains blocked by the workspace free issue limit; the May 18 sync adds queue-zero/work-items state, #1970/#1971/#1972/#1976 merge evidence, ITO-57 current-head supply-chain refresh comment `0b9931b9-1556-4ebc-a70c-f3635557625d`, ITO-57 defensive-deny scanner recheck reply `6fa15367-d994-4e53-ade3-9462477e1100`, ECC platform progress comment `e32e5b7a-287b-4bf4-9ed7-314389a157e1`, and generated `operator:dashboard` prompt-to-artifact audit for recurring status updates | Needs recurring status updates after each significant merge batch |
|
||||
| Linear roadmap is detailed | Linear project status plus repo mirror | Repo mirror exists; issue creation was retried on 2026-05-12 and remains blocked by the workspace free issue limit; the May 17 sync adds the queue-zero batch, Japanese localization merge, ITO-57 live supply-chain refresh comment, ECC platform project progress snapshot, and generated `operator:dashboard` prompt-to-artifact audit for recurring status updates | Needs recurring status updates after each significant merge batch |
|
||||
| Flow separation and progress tracking | Flow lanes with owner artifacts and update cadence | This roadmap defines lanes below and `docs/architecture/progress-sync-contract.md` makes GitHub/Linear/handoff/roadmap sync part of the readiness gate | Active |
|
||||
| Realtime Linear sync | Project comments while issue/status capacity is blocked; issues later | ECC-Tools #39 implements opt-in Linear API sync for deferred follow-up backlog items, and ECC-Tools #54 adds copy-ready PR drafts to that backlog when draft PR shells are not opened; `docs/architecture/progress-sync-contract.md` defines the local file-backed realtime boundary while issue capacity is blocked; May 18 live connector comments were posted to ITO-57 and the ECC platform project after project status updates returned disabled | Needs workspace capacity/config rollout for productized issue sync |
|
||||
| Realtime Linear sync | Project updates while issue limit is blocked; issues later | ECC-Tools #39 implements opt-in Linear API sync for deferred follow-up backlog items, and ECC-Tools #54 adds copy-ready PR drafts to that backlog when draft PR shells are not opened; `docs/architecture/progress-sync-contract.md` defines the local file-backed realtime boundary while issue capacity is blocked; May 17 live connector comments were posted to ITO-57 and the ECC platform project | Needs workspace capacity/config rollout for productized issue sync |
|
||||
| Observability for self-use | Local readiness gate, traces, status snapshots, HUD/status contract, risk ledger, progress-sync contract | `npm run observability:ready` reports 21/21 | Complete for local gate |
|
||||
| Proper release and notifications | Release tag, npm publish state, plugin state, social posts | Publication readiness gate exists with May 12 dry-run and May 13 readiness evidence | Not complete; approval/live URLs required |
|
||||
|
||||
@@ -748,9 +654,9 @@ repo evidence and merge commits.
|
||||
| Queue hygiene and salvage | GitHub PR/issue state, salvage ledger | Append ledger entries for any future stale closures | Every cleanup batch |
|
||||
| Release and publication | rc.1 release docs, publication readiness doc | Naming matrix and plugin submission/contact checklist | Before any tag |
|
||||
| Harness OS core | Audit, adapter matrix, observability docs, `ecc2/` | HUD/session-control acceptance spec | Weekly until GA |
|
||||
| Evaluation and RAG | Reference-set validation, harness audit, traces, ECC-Tools corpus | Read-only evaluator/RAG prototype plus stale-salvage, billing-readiness, CI-failure-diagnosis, harness-config-quality, AgentShield policy-exception, skill-quality evidence, deep-analyzer evidence, and RAG/evaluator comparison fixtures; ECC-Tools #68 publishes the corpus as a hosted promotion readiness check-run, #69 scores cached hosted job outputs against the same corpus, #70 emits ranked retrieval candidates plus a model prompt seed, #71 adds a fail-closed hosted model-judge request contract, and #72 executes that judge only when explicitly enabled and backed by hosted retrieval citations; ECC-Tools `16c537f` surfaces policy-promotion Action output values in hosted security comments/checks; ECC-Tools `05d4e82` adds hosted model-judge audit traces with request fingerprints and allowed-citation counts | Marketplace Pro billing-state verification with webhook provenance |
|
||||
| AgentShield enterprise | AgentShield PR evidence and roadmap notes | Fleet routing landed in #89 after evidence-pack inspect/readback shipped in #88; #90 emits fleet `reviewItems`; #91 exports checksum-backed policy bundles; #92 promotes checksum-verified policies from those bundles into active policy files; AgentShield `87aec47` adds policy promotion `reviewItems`; `28d08c7` adds package-manager hardening drift detection; `659f569` refreshes workflow action runtime pins; `ee585cd` corrects unsupported npm release-age guidance and keeps enforceable cooldown findings on pnpm/Yarn; `1124535` exposes package-manager hardening Action outputs for CI/hosted routing; `1593925` exposes policy-promotion Action outputs and runtime-smoke job-summary evidence; `840952a` adds fleet review ticket payloads and current Mini Shai-Hulud IOC breadcrumbs; ECC-Tools #76 consumes fleet summaries, #77 surfaces source evidence paths in hosted findings, #78 links fleet routes to harness owners, ECC-Tools `8658951` consumes policy-promotion Action outputs, and ECC-Tools `16c537f` renders operator-visible output values | Deepen live operator approval/readback after Marketplace/payment gates |
|
||||
| ECC Tools app | ECC-Tools PR evidence, billing audit, risk taxonomy, evaluator/RAG corpus | ECC-Tools #53 published the supply-chain workflow hardening branch, #54 tracks copy-ready PR drafts in the Linear/project backlog, #55 classifies analysis-depth readiness, #56 exposes the hosted execution plan, #57 executes the first hosted CI diagnostics job, #58 executes the hosted security evidence review job, #59 executes the hosted harness compatibility audit, #60 executes the hosted reference-set evaluation, #61 executes the hosted AI routing/cost review, #62 executes hosted team backlog routing, #63 publishes the hosted depth-plan check-run, #64 dispatches hosted jobs from PR comments, #65 persists hosted result history/check-runs, #66 exposes hosted job status from PR comments, #67 makes depth-plan recommendations cache-aware, #68 publishes hosted promotion readiness from the evaluator/RAG corpus, #69 scores cached hosted job outputs against that corpus, #70 emits ranked retrieval candidates plus a model prompt seed, #71 emits the gated `hosted-promotion-judge.v1` contract without live model calls, #72 adds opt-in live model-judge execution behind hosted-evidence and strict JSON/citation gates, #73 adds a fail-closed native-payments `announcementGate` to billing readiness, #74 adds `npm run billing:announcement-gate` for operator verification, #75 tightens the billing announcement gate for live Marketplace readback, #76 routes AgentShield fleet-summary evidence into hosted security findings, #77 adds source evidence paths to hosted finding output, #78 links AgentShield fleet target paths to hosted harness owner findings, `8658951` routes AgentShield policy-promotion Action outputs into hosted security review and promotion readiness, `16c537f` renders policy-promotion status/pack/count/digest values in hosted security comments/checks, `05d4e82` renders hosted promotion judge request fingerprints plus allowed-citation audit traces, `91a441b` adds billing announcement preflight output for required readback inputs, `eb69412` records the initial production readback state, `95d0bec` adds aggregate `billing:kv-readback` evidence, `2859678` requires Marketplace webhook provenance in billing readiness, `42653f9` adds Wrangler OAuth readback with live aggregate production counts, and `632e059` adds sanitized target-account billing readback for the exact Marketplace test account | Create or verify Marketplace-managed Pro target billing-state with webhook provenance, then live target readback and announcement gate |
|
||||
| Evaluation and RAG | Reference-set validation, harness audit, traces, ECC-Tools corpus | Read-only evaluator/RAG prototype plus stale-salvage, billing-readiness, CI-failure-diagnosis, harness-config-quality, AgentShield policy-exception, skill-quality evidence, deep-analyzer evidence, and RAG/evaluator comparison fixtures; ECC-Tools #68 publishes the corpus as a hosted promotion readiness check-run, #69 scores cached hosted job outputs against the same corpus, #70 emits ranked retrieval candidates plus a model prompt seed, #71 adds a fail-closed hosted model-judge request contract, and #72 executes that judge only when explicitly enabled and backed by hosted retrieval citations; ECC-Tools `16c537f` surfaces policy-promotion Action output values in hosted security comments/checks; ECC-Tools `05d4e82` adds hosted model-judge audit traces with request fingerprints and allowed-citation counts | Marketplace readback |
|
||||
| AgentShield enterprise | AgentShield PR evidence and roadmap notes | Fleet routing landed in #89 after evidence-pack inspect/readback shipped in #88; #90 emits fleet `reviewItems`; #91 exports checksum-backed policy bundles; #92 promotes checksum-verified policies from those bundles into active policy files; AgentShield `87aec47` adds policy promotion `reviewItems`; `28d08c7` adds package-manager hardening drift detection; `659f569` refreshes workflow action runtime pins; `ee585cd` corrects unsupported npm release-age guidance and keeps enforceable cooldown findings on pnpm/Yarn; `1124535` exposes package-manager hardening Action outputs for CI/hosted routing; `1593925` exposes policy-promotion Action outputs and runtime-smoke job-summary evidence; ECC-Tools #76 consumes fleet summaries, #77 surfaces source evidence paths in hosted findings, #78 links fleet routes to harness owners, ECC-Tools `8658951` consumes policy-promotion Action outputs, and ECC-Tools `16c537f` renders operator-visible output values | Deepen live operator approval/readback after Marketplace/payment gates |
|
||||
| ECC Tools app | ECC-Tools PR evidence, billing audit, risk taxonomy, evaluator/RAG corpus | ECC-Tools #53 published the supply-chain workflow hardening branch, #54 tracks copy-ready PR drafts in the Linear/project backlog, #55 classifies analysis-depth readiness, #56 exposes the hosted execution plan, #57 executes the first hosted CI diagnostics job, #58 executes the hosted security evidence review job, #59 executes the hosted harness compatibility audit, #60 executes the hosted reference-set evaluation, #61 executes the hosted AI routing/cost review, #62 executes hosted team backlog routing, #63 publishes the hosted depth-plan check-run, #64 dispatches hosted jobs from PR comments, #65 persists hosted result history/check-runs, #66 exposes hosted job status from PR comments, #67 makes depth-plan recommendations cache-aware, #68 publishes hosted promotion readiness from the evaluator/RAG corpus, #69 scores cached hosted job outputs against that corpus, #70 emits ranked retrieval candidates plus a model prompt seed, #71 emits the gated `hosted-promotion-judge.v1` contract without live model calls, #72 adds opt-in live model-judge execution behind hosted-evidence and strict JSON/citation gates, #73 adds a fail-closed native-payments `announcementGate` to billing readiness, #74 adds `npm run billing:announcement-gate` for operator verification, #75 tightens the billing announcement gate for live Marketplace readback, #76 routes AgentShield fleet-summary evidence into hosted security findings, #77 adds source evidence paths to hosted finding output, #78 links AgentShield fleet target paths to hosted harness owner findings, `8658951` routes AgentShield policy-promotion Action outputs into hosted security review and promotion readiness, `16c537f` renders policy-promotion status/pack/count/digest values in hosted security comments/checks, `05d4e82` renders hosted promotion judge request fingerprints plus allowed-citation audit traces, `91a441b` adds billing announcement preflight output for required readback inputs, and `eb69412` records the live production KV readback state | Marketplace purchase/webhook readback, then live announcement gate |
|
||||
| Linear progress | Linear project status updates, `docs/architecture/progress-sync-contract.md`, generated `operator:dashboard` output, and this mirror | Status update with queue/evidence/missing gates | Every significant merge batch |
|
||||
|
||||
The project status update should always include:
|
||||
@@ -997,24 +903,13 @@ Acceptance:
|
||||
security review and Hosted Promotion Readiness scoring, and ECC-Tools
|
||||
commit `16c537f` renders promotion status, pack, review item count,
|
||||
remaining action count, and digest in hosted security comments/check-runs.
|
||||
AgentShield commit `840952a` adds Linear/operator-ready fleet review ticket
|
||||
payloads and expands current Mini Shai-Hulud IOC breadcrumbs, with green
|
||||
local and remote CI. AgentShield commit `4e36aab` hardens CI package installs
|
||||
after the expanded Mini Shai-Hulud refresh, with CI, Test GitHub Action,
|
||||
Self-Scan, and Dependabot Update workflows green.
|
||||
ECC-Tools commit `05d4e82` adds hosted promotion judge audit traces with
|
||||
deterministic request fingerprints and allowed-citation counts, without
|
||||
exposing raw provider output.
|
||||
ECC-Tools commit `91a441b` adds a billing announcement preflight command
|
||||
for checking Marketplace readback inputs before privileged API calls.
|
||||
ECC-Tools commit `2859678` requires Marketplace webhook provenance in
|
||||
billing-state before native-payments announcement readiness can pass.
|
||||
ECC-Tools commit `42653f9` adds Wrangler OAuth KV readback and confirms the
|
||||
current blocker is not Cloudflare read access; it is the absence of a
|
||||
ready-like Marketplace Pro billing-state record with webhook provenance.
|
||||
ECC-Tools commit `632e059` adds sanitized target-account readback, so the
|
||||
final operator gate should verify the exact Marketplace test account without
|
||||
printing its login or raw KV key names.
|
||||
The next slice is live operator approval/readback after Marketplace/payment
|
||||
gates.
|
||||
2. Run `npm run billing:announcement-gate -- --preflight --account
|
||||
<github-login>`, then run the same command without `--preflight` against a
|
||||
Marketplace-managed test account and require `announcementGate.ready ===
|
||||
|
||||
@@ -229,8 +229,7 @@ Required safeguards:
|
||||
## Near-Term Implementation Order
|
||||
|
||||
1. Extend the harness adapter matrix and public scorecard onramp.
|
||||
2. Keep the release/name/plugin publication checklist current with fresh
|
||||
final-commit evidence before rc.1 publication.
|
||||
2. Add the release/name/plugin publication checklist with evidence fields.
|
||||
3. Define the HUD/status JSON contract and fixture directory.
|
||||
4. Start AgentShield policy schema plus SARIF fixtures.
|
||||
5. Audit ECC Tools billing and check-run surfaces.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# AgentShield Enterprise Research Roadmap
|
||||
|
||||
Generated: 2026-05-12; refreshed with May 18 AgentShield fleet-ticket and
|
||||
Mini Shai-Hulud IOC evidence.
|
||||
Generated: 2026-05-12; refreshed with May 16 AgentShield PR #87, #88, and #89 evidence.
|
||||
|
||||
This is a planning artifact for the next AgentShield enterprise iteration. It
|
||||
does not modify AgentShield code. The goal is to turn the current scanner,
|
||||
@@ -117,21 +116,14 @@ AgentShield PR #89 merged as
|
||||
`agentshield evidence-pack fleet <dirs...> [--json]`, verifies each pack through
|
||||
the inspect path, aggregates finding, policy, baseline, supply-chain, and
|
||||
remediation totals, and assigns each pack to a deterministic fleet route.
|
||||
AgentShield commit `840952a7a07f820f24081c43df656d7f7295f23b` adds
|
||||
Linear/operator-ready fleet review ticket payloads with priority, labels,
|
||||
titles, and Markdown bodies. The same commit expands current Mini
|
||||
Shai-Hulud/TanStack IOC coverage for the in-cluster Vault endpoint and
|
||||
temporary lockfile breadcrumb, with local typecheck, lint, full tests,
|
||||
`git diff --check`, and GitHub CI/Self-Scan/Action-test evidence.
|
||||
|
||||
The next iteration after fleet routing should not be "add more regex rules" by
|
||||
default. ECC-Tools follow-up routing now consumes fleet summaries and surfaces
|
||||
source evidence paths in hosted findings, and the first cross-harness policy
|
||||
slice now links AgentShield fleet route target paths to harness-owner review.
|
||||
AgentShield fleet output now also emits `reviewItems` with source evidence paths
|
||||
and owner-ready recommendations plus copy-ready ticket payloads for routed
|
||||
packs. The higher leverage move is durable operator approval/readback and
|
||||
workflow automation for routed fleet findings.
|
||||
and owner-ready recommendations for routed packs. The higher leverage move is
|
||||
durable policy export and workflow automation for routed fleet findings.
|
||||
|
||||
## Enterprise Gaps
|
||||
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
# Discussion Response Playbook
|
||||
|
||||
This playbook turns GitHub Discussions into the same operating queue as PRs,
|
||||
issues, Linear work, and release evidence. It is an operator guide, not a
|
||||
promise that every informational thread needs a public reply.
|
||||
|
||||
## Audit Loop
|
||||
|
||||
Run these checks before a release, after a major merge batch, and when Linear
|
||||
ITO-59 is refreshed:
|
||||
|
||||
```bash
|
||||
npm run discussion:audit -- --json
|
||||
node scripts/platform-audit.js --json
|
||||
```
|
||||
|
||||
The queue is current only when:
|
||||
|
||||
- discussion fetch errors are explained or fixed;
|
||||
- `needsMaintainerTouch` is zero for support-like discussion categories;
|
||||
- answerable Q&A discussions either have an accepted answer or a clear routing
|
||||
note; and
|
||||
- any product-scope thread is linked to a GitHub issue, Linear issue, roadmap
|
||||
row, or explicit deferral.
|
||||
|
||||
Informational threads such as announcements, references, show-and-tell, or
|
||||
maintainer-authored updates can remain visible without becoming response debt.
|
||||
|
||||
## Categories
|
||||
|
||||
| Category | Route | Required readback |
|
||||
| --- | --- | --- |
|
||||
| Product support or install confusion | Reply with the exact command/doc path; mark accepted answer for Q&A when the fix is complete | Discussion URL plus accepted-answer URL when applicable |
|
||||
| Bug report | Ask for a minimal repro, version, harness, and logs; create or link a GitHub issue when reproducible | Issue URL or deferral reason |
|
||||
| Feature request | Acknowledge the desired outcome and link the closest roadmap issue; do not imply commitment unless scoped | Linear/GitHub roadmap link |
|
||||
| Security concern | Move exploit details and secrets to a private channel; keep the public reply short and non-operational | Private escalation note plus public safety reply |
|
||||
| Release or billing question | Answer from the release URL ledger and publication-readiness gates; do not claim unpublished URLs, billing readiness, or plugin availability | Evidence artifact or blocker link |
|
||||
| Show-and-tell, reference, or announcement | Leave as informational unless there is a direct question or a product-scope signal | Optional roadmap link if useful |
|
||||
| Stale or concluded thread | Summarize the current state and link the durable doc/issue; avoid reviving low-signal threads | Closure note or explicit no-action rationale |
|
||||
|
||||
## Templates
|
||||
|
||||
### Public Support
|
||||
|
||||
Thanks for the report. The current supported path is:
|
||||
|
||||
```bash
|
||||
<command>
|
||||
```
|
||||
|
||||
The relevant doc is `<doc path or URL>`. If this does not match your setup,
|
||||
please reply with the harness, OS, package manager, and the exact error text.
|
||||
|
||||
### Maintainer Coordination
|
||||
|
||||
I am routing this into `<issue or Linear key>` so it does not get lost in the
|
||||
discussion queue. The next decision is `<specific decision>`. Until that lands,
|
||||
the supported workaround is `<workaround or "none">`.
|
||||
|
||||
### Stale Or Concluded
|
||||
|
||||
This thread looks resolved or superseded by `<doc/issue/release>`. I am leaving
|
||||
it visible for history, but it is no longer an active support queue item. New
|
||||
repro details should go to `<issue/discussion path>`.
|
||||
|
||||
### Release Announcement
|
||||
|
||||
The current release status is `<rc/beta/GA state>`. Live URLs are recorded in
|
||||
`docs/releases/2.0.0-rc.1/release-url-ledger-2026-05-18.md`. Anything marked
|
||||
pending there should not be announced as shipped yet.
|
||||
|
||||
### Security Escalation
|
||||
|
||||
Thanks for flagging this. Please do not post exploit steps, tokens, customer
|
||||
data, or secret values in the public thread. I am routing this through the
|
||||
security response path and will keep the public thread limited to safe status
|
||||
updates.
|
||||
|
||||
## Recording Outcomes
|
||||
|
||||
For each high-signal discussion, record one of these outcomes:
|
||||
|
||||
- replied publicly and accepted answer read back;
|
||||
- linked to a GitHub issue or Linear issue;
|
||||
- routed to the security response path;
|
||||
- classified as informational; or
|
||||
- explicitly deferred with a reason.
|
||||
|
||||
Mirror the summary into ITO-59 when the batch closes, and include the counts in
|
||||
the next operator dashboard or publication evidence refresh.
|
||||
@@ -1,63 +0,0 @@
|
||||
# ECC 1.10.1 release announcement draft
|
||||
|
||||
ECC 1.10.1 is the follow-up stabilization release to 1.10.0.
|
||||
|
||||
This release is focused on install correctness, cross-surface naming clarity, Windows/PowerShell recovery, Cursor project install correctness, and Claude Code hook compatibility. It is not a feature-heavy release.
|
||||
|
||||
## What landed in the stabilization pass
|
||||
- npm/package/release surfaces are aligned and `ecc-universal@1.10.0` is live on npm
|
||||
- Windows locale/path and PowerShell install-path regressions fixed
|
||||
- Bash hook process-storm regression fixed
|
||||
- Claude Code 2.1.x hook schema compatibility fixed
|
||||
- Cursor native project install path repaired:
|
||||
- `.cursor/hooks.json` now includes the required schema/version surface
|
||||
- `.cursor/mcp.json` is written in the native Cursor project location
|
||||
- continuous-learning-v2 now accepts `claude-desktop` as a valid entrypoint
|
||||
- Windows observe path now skips `AppInstallerPythonRedirector.exe`
|
||||
- docs now distinguish plugin installs from full manual installs more clearly
|
||||
|
||||
## What 1.10.1 is for
|
||||
- make the current install surfaces predictable
|
||||
- reduce stale naming/install guidance
|
||||
- close the follow-up regressions from 1.10.0
|
||||
- give users one stable update point instead of piecing together fixes across issues and discussions
|
||||
|
||||
## Included release fixes
|
||||
- `#1543` Cursor native project hook + MCP install repair
|
||||
- `#1524` Claude Code v2.1.116 argv-dup mitigation in `settings.local.json`
|
||||
- `#1522` continuous-learning-v2 accepts `claude-desktop` as a valid entrypoint
|
||||
- `#1511` Windows observe path skips `AppInstallerPythonRedirector.exe`
|
||||
- `#1546` continuous-learning-v2 plugin quick start correction
|
||||
- `#1535` hero overflow follow-up
|
||||
|
||||
## Important naming clarification
|
||||
- Claude marketplace/plugin identifier: `everything-claude-code@everything-claude-code`
|
||||
- npm package: `ecc-universal`
|
||||
- GitHub repo: `affaan-m/everything-claude-code`
|
||||
|
||||
Those are intentionally different surfaces. The plugin identifier follows Anthropic marketplace rules; the npm package remains `ecc-universal`.
|
||||
|
||||
## Still being monitored
|
||||
This should be announced as a stabilization release, not as “all edge cases are solved.”
|
||||
|
||||
We are still watching for:
|
||||
- OS-specific edge cases across macOS, Windows, Linux
|
||||
- shell-specific behavior differences
|
||||
- Cursor vs Claude plugin install-path mismatches that only appear in older or mixed installs
|
||||
- third-party provider/tool-name compatibility reports that still need current-main repro
|
||||
|
||||
Current watch-list examples:
|
||||
- `#1520` likely obsolete unless repro returns on the current installer
|
||||
- `#1516` not gating unless reproduced on current `main`
|
||||
- `#1484` remains a Windows umbrella/watch-list issue rather than an active release gate
|
||||
|
||||
## Recommended update guidance
|
||||
If you hit 1.10.0 install/runtime problems:
|
||||
1. update to the latest package/plugin surface
|
||||
2. avoid mixing plugin install plus full manual repo copy unless the docs explicitly say to
|
||||
3. if problems persist, report:
|
||||
- OS + shell
|
||||
- Claude Code/Cursor version
|
||||
- install method used
|
||||
- exact stderr/output
|
||||
- whether the issue is plugin install, npm install, repo sync, or Cursor project install
|
||||
@@ -12,8 +12,6 @@
|
||||
- verify `preview-pack-manifest.md` lists the public release, Hermes, adapter,
|
||||
observability, publication, and announcement artifacts before running final
|
||||
publish checks
|
||||
- verify `release-name-plugin-publication-checklist-2026-05-18.md` still
|
||||
matches current GitHub, npm, Claude, Codex, OpenCode, and billing surfaces
|
||||
- keep private tokens, personal docs, and raw workspace exports out of the repo
|
||||
|
||||
## Release Surface
|
||||
@@ -21,9 +19,6 @@
|
||||
- verify package, plugin, marketplace, OpenCode, and agent metadata stays at `2.0.0-rc.1`
|
||||
- verify `ecc2/Cargo.toml` stays at `0.1.0` for rc.1; `ecc2/` remains an alpha control-plane scaffold
|
||||
- complete `publication-readiness.md` with fresh evidence before any GitHub release, npm publish, plugin submission, or announcement post
|
||||
- rerun the release name/plugin publication checklist before creating a
|
||||
GitHub prerelease, publishing npm, pushing Claude plugin tags, recording the
|
||||
Codex marketplace path, or posting public copy
|
||||
- include `publication-evidence-2026-05-17.md` and
|
||||
`operator-readiness-dashboard-2026-05-17.md` in the final evidence review,
|
||||
then rerun publish-facing checks from the exact release commit
|
||||
|
||||
@@ -37,6 +37,3 @@ There is still more to harden before GA, especially around packaging, installers
|
||||
Public publication is still approval-gated until the GitHub release, npm
|
||||
`next` publish, plugin path, final URLs, and billing/native-payments claims have
|
||||
live evidence.
|
||||
|
||||
The release URL ledger now separates links that already resolve from links that
|
||||
must wait for the approval-gated release, package, plugin, and billing checks.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# ECC v2.0.0-rc.1 Naming And Publication Matrix
|
||||
|
||||
Snapshot date: 2026-05-18.
|
||||
Snapshot date: 2026-05-12.
|
||||
|
||||
This matrix answers the release question "ship as Everything Claude Code, ECC,
|
||||
or a renamed surface?" for the rc.1 lane. It is evidence for planning, not a
|
||||
@@ -28,26 +28,26 @@ Reason:
|
||||
|
||||
## Current Values
|
||||
|
||||
| Surface | Current value | Evidence command | 2026-05-18 result | Release decision |
|
||||
| Surface | Current value | Evidence command | 2026-05-12 result | Release decision |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Product display name | `Everything Claude Code` | `rg -n "Everything Claude Code" README.md CHANGELOG.md docs/releases/2.0.0-rc.1` | Present across README, release notes, launch copy, and plugin manifests | Keep for rc.1 |
|
||||
| Short name | `ECC` | README/release docs | Used as the short cross-harness brand | Keep and prefer in tight copy |
|
||||
| GitHub repo | `affaan-m/everything-claude-code` | `git remote get-url origin` | `https://github.com/affaan-m/everything-claude-code.git` | Keep for rc.1 |
|
||||
| Possible short repo | `affaan-m/ecc` | `gh repo view affaan-m/ecc` | Not found with current auth | Candidate after rc.1 only |
|
||||
| npm package | `ecc-universal` | `node -p "require('./package.json').name"` | `ecc-universal` | Keep for rc.1 |
|
||||
| npm package version | `2.0.0-rc.1` local, `1.10.0` registry latest | `node -p "require('./package.json').version"` and `npm view ecc-universal name version dist-tags --json` | Local rc.1 is ready; registry latest remains `1.10.0` and no `next` dist-tag exists yet | Publish rc as `next`, not `latest` |
|
||||
| npm package version | `2.0.0-rc.1` local, `1.10.0` registry latest | `node -p "require('./package.json').version"` and `npm view ecc-universal name version dist-tags --json` | Local rc.1 is ready; registry latest remains `1.10.0` | Publish rc as `next`, not `latest` |
|
||||
| Exact npm short name | `ecc` | `npm view ecc name version description repository.url --json` | Occupied by `ecc@0.0.2`, "Elliptic curve cryptography functions." | Do not use |
|
||||
| Scoped npm short name | `@affaan-m/ecc` | `npm view @affaan-m/ecc name version --json` | Registry 404 | Possible future scoped package if npm scope policy permits |
|
||||
| Former package name | `everything-claude-code` | `npm view everything-claude-code name version dist-tags --json` | Registry reports unpublished on 2026-02-07 | Do not revive for rc.1 |
|
||||
| Claude plugin slug | `ecc` | `node -p "require('./.claude-plugin/plugin.json').name"` | `ecc` | Keep |
|
||||
| Claude plugin version | `2.0.0-rc.1` | `claude plugin validate .claude-plugin/plugin.json`; `claude plugin tag .claude-plugin --dry-run` | Validation passed on Claude Code `2.1.143`; dry run would create `ecc--v2.0.0-rc.1` | Ready for release-tag gate |
|
||||
| Claude marketplace entry | `ecc` | `.claude-plugin/marketplace.json`; `claude plugin marketplace add --help`; Anthropic plugin marketplace docs | Version and repo point at current rc.1 surface; GitHub, git URL, remote marketplace JSON, and local path marketplace sources are supported | Keep |
|
||||
| Claude plugin version | `2.0.0-rc.1` | `claude plugin validate .claude-plugin/plugin.json` | Validation passed on Claude Code `2.1.121` | Ready for release-tag gate |
|
||||
| Claude marketplace entry | `ecc` | `.claude-plugin/marketplace.json` | Version and repo point at current rc.1 surface | Keep |
|
||||
| Codex plugin slug | `ecc` | `node -p "require('./.codex-plugin/plugin.json').name"` | `ecc` | Keep |
|
||||
| Codex plugin version | `2.0.0-rc.1` | `node tests/plugin-manifest.test.js`; `node tests/docs/ecc2-release-surface.test.js` | Plugin manifest passed 54/54; release surface passed 21/21 on Codex CLI `0.131.0` | Ready for Codex marketplace/manual marketplace gate |
|
||||
| Codex repo marketplace | `ecc` | `.agents/plugins/marketplace.json`; `codex plugin marketplace add --help`; OpenAI Codex plugin docs | Repo marketplace add supports GitHub shorthand, Git URLs, SSH URLs, local roots, `--ref`, and `--sparse`; local and GitHub-ref temp-home add smokes passed | Use as rc.1 Codex distribution path |
|
||||
| Codex plugin version | `2.0.0-rc.1` | `node tests/docs/ecc2-release-surface.test.js` | Release surface test passed | Ready for Codex marketplace/manual marketplace gate |
|
||||
| Codex repo marketplace | `ecc` | `.agents/plugins/marketplace.json`; `codex plugin marketplace add --help` | Repo marketplace add supports GitHub shorthand and local roots; local temp-home add smoke passed | Use as rc.1 Codex distribution path |
|
||||
| OpenCode package | `ecc-universal` | `node -p "require('./.opencode/package.json').name"` | `ecc-universal` | Keep |
|
||||
| OpenCode build | Generated package output | `npm run build:opencode` | Passed | Ready for package dry-run gate |
|
||||
| npm pack surface | Reduced runtime package | `NPM_CONFIG_USERCONFIG=/dev/null npm pack --dry-run --json` | Produced `ecc-universal-2.0.0-rc.1.tgz`, 2228 entries, 4,348,504 bytes packed, 13,024,929 bytes unpacked | Needs final release-commit rerun |
|
||||
| npm pack surface | Reduced runtime package | `npm pack --dry-run --json` | Produced `ecc-universal-2.0.0-rc.1.tgz`, 969 entries, about 5.0 MB unpacked | Needs final release-commit rerun |
|
||||
|
||||
## Publication Paths
|
||||
|
||||
@@ -57,26 +57,11 @@ Reason:
|
||||
| npm | `ecc-universal` local package version is `2.0.0-rc.1`; registry latest is `1.10.0` | Publish rc with `npm publish --tag next` after final `npm pack --dry-run` and release tests | Do not publish before final release commit |
|
||||
| Claude plugin | `claude plugin validate .claude-plugin/plugin.json` passed; `claude plugin tag --help` confirms the release tag flow creates `{name}--v{version}` tags and can push them | Run `claude plugin tag .claude-plugin --dry-run` from the clean release commit, then tag/push only after release approval | No plugin release tag created in this pass |
|
||||
| Claude marketplace | `.claude-plugin/marketplace.json` points at `ecc` and the public repo | Verify marketplace update/install path after tag exists | External marketplace propagation not verified |
|
||||
| Codex plugin | `codex plugin marketplace` supports local and Git marketplace sources; `.codex-plugin/plugin.json` is present; `.agents/plugins/marketplace.json` exposes `ecc` from the repo root; temp-home local and GitHub-ref marketplace adds passed | Publish rc.1 docs with the repo-marketplace command, then monitor OpenAI's official Plugin Directory path | Do not claim official Plugin Directory listing before OpenAI submission evidence |
|
||||
| Codex plugin | `codex plugin marketplace` supports add/upgrade/remove; `.codex-plugin/plugin.json` is present; `.agents/plugins/marketplace.json` exposes `ecc` from the repo root; temp-home local `codex plugin marketplace add` passed | Publish rc.1 docs with the repo-marketplace command, then monitor OpenAI's official Plugin Directory self-serve path | Official Plugin Directory publishing is documented as coming soon |
|
||||
| OpenCode package | `.opencode/package.json` builds from source and ships inside npm package | Re-run `npm run build:opencode` and package dry-run from release commit | OpenCode CLI 1.2.21 does not expose a separate plugin publication command in this pass |
|
||||
| ECC Tools billing claim | README and launch copy mention ECC Tools / marketplace context | ECC-Tools #73 adds `/api/billing/readiness` `announcementGate`; run it against a Marketplace-managed test account before any payment announcement | Billing announcement code gate exists; live Marketplace account readback still pending |
|
||||
| Social and longform copy | X thread, LinkedIn copy, article outline, GitHub release copy exist | Replace any stale URLs, then publish only after release/npm/plugin URLs work | Public URLs not final until release actions complete |
|
||||
|
||||
## ITO-46 Blocker Register
|
||||
|
||||
| Channel | Current status | Required metadata/evidence | Owner | Blocker or follow-up |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| GitHub release | Approval-gated; no `v2.0.0-rc.1` prerelease yet | Tag, release URL, prerelease flag, final release notes, URL ledger | Release owner | Create only after final clean-checkout evidence |
|
||||
| npm | `ecc-universal@2.0.0-rc.1` dry-run passed; registry latest is `1.10.0` | Pack summary, publish dry-run, `next` dist-tag readback, registry signature evidence | Package owner | Do not publish before approval and final release commit |
|
||||
| Short npm name | `ecc` is occupied; `@affaan-m/ecc` returns 404 | Name availability outputs and migration plan | Release owner | Keep `ecc-universal` for rc.1; scoped rename is post-rc only |
|
||||
| Claude plugin | `ecc@2.0.0-rc.1` validates; tag dry run would create `ecc--v2.0.0-rc.1` | `claude plugin validate .`, `claude plugin tag .claude-plugin --dry-run`, marketplace install/update smoke | Plugin owner | Real tag push and marketplace propagation require release approval |
|
||||
| Claude marketplace | Docs and CLI support GitHub, git URL, remote marketplace JSON, and local path sources | Public repo marketplace JSON, support/contact metadata, post-tag install smoke | Plugin owner | No external official listing has been submitted in this pass |
|
||||
| Codex repo marketplace | Local and GitHub-ref temp-home marketplace add smokes passed on Codex CLI `0.131.0` | `.codex-plugin/plugin.json`, `.agents/plugins/marketplace.json`, repo/personal marketplace evidence | Plugin owner | Official Plugin Directory listing requires OpenAI submission/listing evidence |
|
||||
| Codex official Plugin Directory | OpenAI docs describe the curated official directory; ECC has not submitted or received listing evidence | Directory submission link or OpenAI approval path once available | Plugin owner | Track as an ITO-56/ITO-46 follow-up; do not claim an official listing |
|
||||
| OpenCode package | `npm run build:opencode` passed | Built `.opencode` package metadata inside npm tarball | Package owner | No separate public plugin channel identified; follows npm |
|
||||
| Billing/native payments | Announcement remains blocked by ITO-61 | Marketplace Pro target readback, webhook provenance, `INTERNAL_API_SECRET`, announcement gate | ECC Tools owner | Do not include native-payments claim in rc.1 announcement |
|
||||
| Social/longform copy | Drafts exist | Final live GitHub, npm, Claude, Codex, billing URLs | Release owner | Publish only after release/package/plugin URLs exist |
|
||||
|
||||
## Rename After rc.1
|
||||
|
||||
If the project moves from "Everything Claude Code" toward "ECC" after rc.1,
|
||||
@@ -98,7 +83,7 @@ do it as a staged migration:
|
||||
|
||||
```text
|
||||
git rev-parse HEAD
|
||||
67e63e63f9bfd074bd6a21bf6bac71f3dfefa58b
|
||||
7109ee08db7209c5d14809efcf832043020dfc57
|
||||
|
||||
node -p "require('./package.json').name + '@' + require('./package.json').version"
|
||||
ecc-universal@2.0.0-rc.1
|
||||
@@ -119,30 +104,19 @@ npm view ecc-universal name version dist-tags --json
|
||||
registry latest is 1.10.0; no rc dist-tag exists yet.
|
||||
|
||||
claude plugin validate .claude-plugin/plugin.json
|
||||
Validation passed on Claude Code 2.1.143.
|
||||
|
||||
claude plugin validate .
|
||||
Validation passed with one warning: root CLAUDE.md is not loaded as plugin
|
||||
context; ship plugin context through skills instead.
|
||||
|
||||
claude plugin tag .claude-plugin --dry-run
|
||||
Would create and push tag ecc--v2.0.0-rc.1.
|
||||
Validation passed on Claude Code 2.1.121.
|
||||
|
||||
node tests/docs/ecc2-release-surface.test.js
|
||||
21 release-surface checks passed.
|
||||
18 release-surface checks passed.
|
||||
|
||||
node tests/plugin-manifest.test.js
|
||||
54 plugin-manifest checks passed.
|
||||
node tests/scripts/npm-publish-surface.test.js
|
||||
2 npm publish-surface checks passed.
|
||||
|
||||
npm run build:opencode
|
||||
Passed.
|
||||
|
||||
npm pack --dry-run --json
|
||||
Produced ecc-universal-2.0.0-rc.1.tgz, 2228 entries, 4,348,504 bytes
|
||||
packed, and 13,024,929 bytes unpacked.
|
||||
|
||||
npm publish --tag next --dry-run
|
||||
Dry run would publish ecc-universal@2.0.0-rc.1 to npm with tag next.
|
||||
Produced ecc-universal-2.0.0-rc.1.tgz, 969 entries, about 5.0 MB unpacked.
|
||||
|
||||
codex plugin marketplace add --help
|
||||
Supports GitHub shorthand, HTTP(S) Git URLs, SSH URLs, local marketplace roots,
|
||||
@@ -151,9 +125,4 @@ Supports GitHub shorthand, HTTP(S) Git URLs, SSH URLs, local marketplace roots,
|
||||
HOME="$(mktemp -d)" codex plugin marketplace add <local-checkout>
|
||||
Added marketplace ecc and recorded the installed marketplace root as
|
||||
<local-checkout> without touching the real Codex config.
|
||||
|
||||
HOME="$(mktemp -d)" codex plugin marketplace add affaan-m/everything-claude-code --ref "$(git rev-parse HEAD)"
|
||||
Added marketplace ecc from the GitHub repo pinned to
|
||||
67e63e63f9bfd074bd6a21bf6bac71f3dfefa58b without touching the real Codex
|
||||
config.
|
||||
```
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
This dashboard is generated by `npm run operator:dashboard`. It is an operator snapshot, not release approval.
|
||||
|
||||
Generated: 2026-05-18T01:50:19.099Z
|
||||
Commit: 000df72d6b9c5b11feb11deef609911943b48424
|
||||
Generated: 2026-05-17T21:57:47.582Z
|
||||
Commit: e6c16b40b80b3b323586c9e8341faa87c01a728c
|
||||
Status: work remaining
|
||||
|
||||
## Current Status
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
# ECC Operator Readiness Dashboard
|
||||
|
||||
This dashboard is generated by `npm run operator:dashboard`. It is an operator snapshot, not release approval.
|
||||
|
||||
Generated: 2026-05-18T20:25:22.649Z
|
||||
Commit: 4470e2e6702f17099d6feb137ba03ff00582c202
|
||||
Status: work remaining
|
||||
|
||||
## Current Status
|
||||
|
||||
| Area | Status | Evidence |
|
||||
| --- | --- | --- |
|
||||
| PR queue | Current | 0 open PRs across tracked repos |
|
||||
| Issue queue | Current | 0 open issues across tracked repos |
|
||||
| Discussions | Current | 0 need maintainer touch; 0 missing accepted answer |
|
||||
| Local worktree | Current | 0 blocking dirty files; 0 ignored dirty entries |
|
||||
| Dashboard generation | Current | platform audit ready: true; GitHub skipped: false |
|
||||
| Publication | Not complete | release, npm, plugin, billing, and announcement gates are tracked below |
|
||||
|
||||
## Prompt-To-Artifact Checklist
|
||||
|
||||
| Objective requirement | Artifact or gate | Status | Evidence | Gap |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Keep public PRs below 20 | scripts/platform-audit.js live GitHub sweep plus owner-wide queue cleanup ledger | current | 0 open PRs across 5 tracked repos; 0 owner-wide open PRs after cleanup | repeat platform:audit and owner-wide gh search before release |
|
||||
| Keep public issues below 20 | scripts/platform-audit.js live GitHub sweep plus owner-wide queue cleanup ledger | current | 0 open issues across 5 tracked repos; 0 owner-wide open issues after cleanup | repeat platform:audit and owner-wide gh search before release |
|
||||
| Respond and manage repository discussions | scripts/platform-audit.js discussion summary | current | 0 need maintainer touch; 0 answerable discussions missing accepted answer | repeat before release |
|
||||
| Build ITO-44 completion dashboard into a repeatable command | npm run operator:dashboard | complete | operator:dashboard package script exists | keep generated dashboard attached to publication evidence |
|
||||
| ECC 2.0 preview pack ready | docs/releases/2.0.0-rc.1/preview-pack-manifest.md | current | preview pack manifest and deterministic smoke gate are in-tree | repeat clean-checkout preview-pack smoke before publication |
|
||||
| Include Hermes specialized skills safely | docs/HERMES-SETUP.md and skills/hermes-imports/SKILL.md | current | Hermes setup/import artifacts are covered by preview-pack smoke | repeat preview-pack smoke before release review |
|
||||
| Prepare name-change, Claude plugin, and Codex plugin paths | naming-and-publication-matrix plus release-name-plugin-publication checklist plus publication-readiness | in_progress | naming matrix, release publication checklist, and plugin readiness gates exist | real tag/push, marketplace submission, and final channel choice remain approval-gated |
|
||||
| Prepare release notes, articles, tweets, and push notifications | docs/releases/2.0.0-rc.1 social and release-copy files | in_progress | release notes, X thread, LinkedIn draft, and URL ledger are present | final live release/npm/plugin/billing URLs and publish approval still pending |
|
||||
| Advance AgentShield enterprise iteration | AgentShield PR evidence plus enterprise roadmap | in_progress | AgentShield policy promotion `reviewItems` landed in `87aec47`; package-manager hardening drift detection landed in `28d08c7`; workflow action runtime pins were refreshed in `659f569`; npm age-gate guidance was corrected in `ee585cd`; package-manager hardening Action outputs landed in `1124535`; policy-promotion Action outputs and runtime-smoke job-summary evidence landed in `1593925`; fleet review ticket payloads and current Mini Shai-Hulud IOC breadcrumbs landed in `840952a`; ECC-Tools consumes those outputs in `8658951`, surfaces operator-readable status/pack/count/digest telemetry in `16c537f`, and renders hosted promotion judge audit traces in `05d4e82`; all are mirrored in the GA roadmap | deepen live operator approval/readback after Marketplace/payment gates |
|
||||
| Advance ECC Tools native payments and AI-native harness-agnostic app | ECC Tools PR evidence, billing gate, hosted analysis lanes | in_progress | billing announcement gate, hosted analysis lanes, AgentShield fleet-summary consumption, hosted finding evidence paths, harness-route policy linking, policy-promotion Action-output telemetry, operator-visible promotion output details, hosted promotion judge audit traces, billing announcement preflight, aggregate production billing KV readback, Wrangler OAuth readback, target-account billing readback, provenance-aware Marketplace billing-state gates, sanitized Marketplace plan/action provenance counts, hosted team-learning feedback controls, and ECC-Tools Dependabot alert remediation are mirrored in the GA roadmap | create or verify Marketplace-managed Pro target billing-state with webhook provenance, configure the target account and INTERNAL_API_SECRET, then rerun target readback and the live announcement gate |
|
||||
| Audit, prune, or attach legacy work | docs/stale-pr-salvage-ledger.md and legacy inventory | current | legacy salvage ledger and inventory are current; all localization tails are attached to Linear ITO-55 for manual language-owner review | repeat legacy scan before release |
|
||||
| Keep Linear roadmap detailed and progress tracking synchronized | Linear project mirror plus progress-sync contract | current | Linear live sync and project progress surface are current; progress-sync contract defines the file-backed work-items/status path | repeat Linear/project status update and local work-items sync after each significant merge batch |
|
||||
| Provide ECC 2.0 observability for self-use | observability readiness gate | complete | observability:ready command and readiness doc exist | runtime/dashboard implementation can continue after release gates |
|
||||
| Keep Mini Shai-Hulud/TanStack protection loop current | supply-chain watch plus runbook plus AgentShield package-manager hardening | current | scheduled supply-chain watch emits IOC/advisory-source refresh artifacts; ECC scanner covers gh-token-monitor token-store persistence; AgentShield now detects known AI-tool persistence IOCs, npm lifecycle/token drift, unsupported npm age-key drift, and pnpm/Yarn cooldown drift; current-head watch evidence and ITO-57 May 18 Linear evidence updates are current | repeat advisory/source refresh and Linear sync after each significant supply-chain batch |
|
||||
|
||||
## Top Actions
|
||||
|
||||
- `naming-and-plugin-publication`: real tag/push, marketplace submission, and final channel choice remain approval-gated
|
||||
- `release-notes-and-notifications`: final live release/npm/plugin/billing URLs and publish approval still pending
|
||||
- `agentshield-enterprise-iteration`: deepen live operator approval/readback after Marketplace/payment gates
|
||||
- `ecc-tools-next-level`: create or verify Marketplace-managed Pro target billing-state with webhook provenance, configure the target account and INTERNAL_API_SECRET, then rerun target readback and the live announcement gate
|
||||
|
||||
## Next Work Order
|
||||
|
||||
1. Regenerate this dashboard from the final release commit before publication evidence is recorded.
|
||||
2. Repeat ITO-57 Linear/project status sync after the next significant merge batch or advisory-source refresh.
|
||||
3. Create or verify Marketplace-managed Pro target billing-state with webhook provenance, configure the target account and INTERNAL_API_SECRET, then rerun target readback and the live announcement gate before publishing native-payments copy.
|
||||
4. Resume ITO-45, ITO-46, and ITO-56 only after the generated dashboard and final release gates are refreshed.
|
||||
@@ -1,65 +0,0 @@
|
||||
# Owner-Wide Queue Cleanup - 2026-05-18
|
||||
|
||||
This note records the live GitHub queue cleanup outside the five ECC release
|
||||
repos tracked by `scripts/platform-audit.js`.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
gh search prs --owner affaan-m --state open --json repository,number,title,url,author,updatedAt --limit 100
|
||||
gh search issues --owner affaan-m --state open --json repository,number,title,url,updatedAt --limit 100
|
||||
```
|
||||
|
||||
## Result
|
||||
|
||||
- Owner-wide open PRs after cleanup: 0.
|
||||
- Owner-wide open issues after cleanup: 0.
|
||||
- Stale dependency-bot PRs closed: 24.
|
||||
- Stale legacy payments/0EM roadmap issues closed: 72.
|
||||
- Final stale/generated/manual-review PRs closed: 9.
|
||||
- Final legacy/outreach/placeholder issues closed: 5.
|
||||
- Archived repos temporarily unarchived for stale dependency PR closure and
|
||||
restored to archived state:
|
||||
`affaan-m/stoictradingAI`, `affaan-m/dprc-autotrader-v2`,
|
||||
`affaan-m/polycule-secure`, and `affaan-m/pragmAItism_defAInce`.
|
||||
- The final archived-repo sweep temporarily unarchived and restored
|
||||
`affaan-m/dprc-autotrader-v2` and `affaan-m/stoictradingAI`.
|
||||
|
||||
## Final PR Disposition
|
||||
|
||||
- `affaan-m/dprc-autotrader-v2#5`: closed stale generated ECC bundle with
|
||||
failing checks and dependency-update base.
|
||||
- `affaan-m/x-algorithm-score#2`: closed stale/conflicting external feature
|
||||
PR with accidental local AI-tool directories noted in the PR body.
|
||||
- `affaan-m/dexploy#28`: closed stale generated ECC skill PR with requested
|
||||
changes.
|
||||
- `affaan-m/zenith#5`: closed stale generated ECC skill PR.
|
||||
- `affaan-m/zenith#4`: closed test/noise PR whose diff only added a
|
||||
non-actionable script comment.
|
||||
- `affaan-m/affaan-m#1`: closed stale/conflicting third-party README-card PR.
|
||||
- `affaan-m/affaanmustafa.com#1`: closed stale Cloudflare Worker-name PR with
|
||||
requested changes.
|
||||
- `affaan-m/0em-payments-dashboard#11`: closed stale/conflicting Cloudflare
|
||||
Worker-name PR.
|
||||
- `affaan-m/0em-payments-dashboard#3`: closed stale/conflicting Cloudflare
|
||||
Worker-name PR.
|
||||
|
||||
## Final Issue Disposition
|
||||
|
||||
- `affaan-m/dprc-autotrader-v2#3`: closed public integration pitch as not
|
||||
planned for the archived repo.
|
||||
- `affaan-m/stoictradingAI#20`: closed public outreach question as not planned
|
||||
for the archived repo.
|
||||
- `affaan-m/dexploy#27`: closed stale internal skill-creator test issue.
|
||||
- `affaan-m/dexploy#25`: preserved useful deployment/localStorage and
|
||||
Cloudflare findings in Linear `ITO-62`, then closed the stale GitHub issue.
|
||||
- `affaan-m/telegram-mcp-ts#1`: closed stale empty placeholder issue.
|
||||
|
||||
## Disposition
|
||||
|
||||
The closed dependency PRs were stale generated version bumps and should be
|
||||
regenerated from current bases if still needed. The closed generated ECC bundle
|
||||
PRs should be regenerated from the current ECC Tools flow if those repositories
|
||||
become active again. The closed legacy payments/0EM issues were old planning
|
||||
items superseded by the ECC Tools native-payments, hosted analysis,
|
||||
billing-readback, and Linear/project roadmap lanes.
|
||||
@@ -15,7 +15,7 @@ surfaces, or posting announcements.
|
||||
| `docs/architecture/cross-harness.md` | Shared substrate model for Claude Code, Codex, OpenCode, Cursor, Gemini, Hermes, and terminal-only use | Names portability boundaries and does not claim unsupported native parity |
|
||||
| `docs/architecture/harness-adapter-compliance.md` | Adapter matrix and scorecard | Verified by `npm run harness:adapters -- --check` |
|
||||
| `docs/architecture/observability-readiness.md` | Local operator-readiness gate | Verified by `npm run observability:ready` |
|
||||
| `docs/architecture/progress-sync-contract.md` | GitHub, Linear, handoff, roadmap, and work-item sync boundary | Checked by `node scripts/platform-audit.js --json` |
|
||||
| `docs/architecture/progress-sync-contract.md` | GitHub, Linear, handoff, roadmap, and work-item sync boundary | Checked by `node scripts/platform-audit.js --format json --allow-untracked docs/drafts/` |
|
||||
| `scripts/preview-pack-smoke.js` | Deterministic preview-pack smoke gate | Verified by `npm run preview-pack:smoke` |
|
||||
| `docs/releases/2.0.0-rc.1/release-notes.md` | GitHub release copy source | Must be refreshed with final live release/package/plugin URLs before publication |
|
||||
| `docs/releases/2.0.0-rc.1/quickstart.md` | Clone-to-first-workflow path | Covers clone, install, verify, first skill, and harness switch |
|
||||
@@ -23,13 +23,9 @@ surfaces, or posting announcements.
|
||||
| `docs/releases/2.0.0-rc.1/publication-readiness.md` | Release gate | Requires fresh evidence from the exact release commit |
|
||||
| `docs/releases/2.0.0-rc.1/publication-evidence-2026-05-15.md` | Current May 15 queue, roadmap, security, supply-chain watch, no-lifecycle CI install hardening, AgentShield #86 evidence-pack provenance, ECC Tools billing-gate, Actions cache purge, and `ecc2` test evidence through PR #1941 | Must be superseded by a final clean-checkout evidence file before real publication |
|
||||
| `docs/releases/2.0.0-rc.1/publication-evidence-2026-05-16.md` | Current May 16/17 queue cleanup, recsys skill merge, GateGuard triage, PR #1947 supply-chain protection, AgentShield #87 plugin-cache confidence evidence, AgentShield #88 evidence-pack inspect/readback, AgentShield #89 evidence-pack fleet routing, AgentShield #90 fleet review items, AgentShield #91 policy export, AgentShield #92 policy promotion, ECC-Tools #76 fleet-summary consumption, ECC-Tools #77 hosted finding evidence paths, ECC-Tools #78 harness policy-route linking, dashboard refresh, and combined Node/Rust/release-surface gate evidence through the May 16 mirror | Must still be repeated from a strict clean checkout before real publication |
|
||||
| `docs/releases/2.0.0-rc.1/publication-evidence-2026-05-17.md` | May 17 queue-zero state, Japanese localization merge, Dependabot TypeScript and Node type merges, post-merge ja-JP lint repair, Mini Shai-Hulud/TanStack protection recheck, npm audit/signature checks, legacy and Linear progress routing, deterministic preview-pack smoke, operator dashboard refresh, Linear sync, and GitHub CI evidence for `27dc2918` | Superseded by the May 18 evidence snapshot; repeat from a strict clean checkout before real publication |
|
||||
| `docs/releases/2.0.0-rc.1/publication-evidence-2026-05-18.md` | Current May 18 queue-zero state, #1970/#1971/#1972 merge batch, #1978 review/closure, current-head Mini Shai-Hulud/TanStack protection recheck, no-lifecycle install, npm audit/signature checks, AgentShield `840952a` enterprise/IOC evidence mirror, work-items sync, Linear sync, operator dashboard refresh, latest current-head CI/security scan success for `4470e2e6`, and ITO-46 naming/plugin publication closure | Current strongest readiness snapshot; must still be repeated from a strict clean checkout before real publication |
|
||||
| `docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-17.md` | Previous prompt-to-artifact operator dashboard | Superseded by the May 18 generated dashboard |
|
||||
| `docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-18.md` | Current prompt-to-artifact operator dashboard | Shows PR/issue/discussion/platform/supply-chain gates current and publication, plugin, billing, AgentShield, ECC Tools, legacy, and Linear productization gaps still open |
|
||||
| `docs/releases/2.0.0-rc.1/release-url-ledger-2026-05-18.md` | Live URL and approval-gated URL ledger for release copy | Must be regenerated from the final release commit before public announcements |
|
||||
| `docs/releases/2.0.0-rc.1/publication-evidence-2026-05-17.md` | Current May 17 queue-zero state, Japanese localization merge, Dependabot TypeScript and Node type merges, post-merge ja-JP lint repair, Mini Shai-Hulud/TanStack protection recheck, npm audit/signature checks, legacy and Linear progress routing, deterministic preview-pack smoke, operator dashboard refresh, Linear sync, and GitHub CI evidence for `27dc2918` | Current strongest readiness snapshot; must still be repeated from a strict clean checkout before real publication |
|
||||
| `docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-17.md` | Current prompt-to-artifact operator dashboard | Shows PR/issue/discussion/platform/supply-chain gates current and publication, plugin, billing, AgentShield, ECC Tools, legacy, and Linear productization gaps still open |
|
||||
| `docs/releases/2.0.0-rc.1/naming-and-publication-matrix.md` | Naming, slug, and publication-path decision record | Keeps `Everything Claude Code / ECC`, npm `ecc-universal`, and plugin slug `ecc` for rc.1 |
|
||||
| `docs/releases/2.0.0-rc.1/release-name-plugin-publication-checklist-2026-05-18.md` | Release name, package, Claude plugin, Codex plugin, and publication-order checklist | Freezes rc.1 identity and requires final commit evidence before release, npm, plugin, billing, or announcement actions |
|
||||
| `docs/releases/2.0.0-rc.1/x-thread.md` | X launch draft | Must replace placeholders with live URLs after release/package/plugin publication |
|
||||
| `docs/releases/2.0.0-rc.1/linkedin-post.md` | LinkedIn launch draft | Must replace placeholders with live URLs after release/package/plugin publication |
|
||||
| `docs/releases/2.0.0-rc.1/article-outline.md` | Longform launch outline | Must stay release-candidate framed until GA evidence exists |
|
||||
@@ -73,7 +69,7 @@ Run these from the exact release commit before publication:
|
||||
|
||||
```bash
|
||||
git status --short --branch
|
||||
node scripts/platform-audit.js --json
|
||||
node scripts/platform-audit.js --format json --allow-untracked docs/drafts/
|
||||
npm run preview-pack:smoke
|
||||
npm run harness:adapters -- --check
|
||||
npm run harness:audit -- --format json
|
||||
@@ -91,9 +87,6 @@ cd ecc2 && cargo test
|
||||
The preview pack is assembled, but publication is still blocked until these live
|
||||
surfaces exist and are recorded in a final evidence file:
|
||||
|
||||
- final release URL ledger regenerated from the intended release commit;
|
||||
- final release name/plugin publication checklist rerun from the intended
|
||||
release commit;
|
||||
- GitHub prerelease `v2.0.0-rc.1`;
|
||||
- npm `ecc-universal@2.0.0-rc.1` on the `next` dist-tag;
|
||||
- Claude plugin tag / marketplace propagation for `ecc@ecc`;
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
# ECC v2.0.0-rc.1 Publication Evidence - 2026-05-18
|
||||
|
||||
This is release-readiness evidence only. It does not create a GitHub release,
|
||||
npm publication, plugin tag, marketplace submission, or announcement post.
|
||||
|
||||
## Source Commit
|
||||
|
||||
| Field | Evidence |
|
||||
| --- | --- |
|
||||
| Upstream main | `4470e2e6702f17099d6feb137ba03ff00582c202` |
|
||||
| Git remote | `https://github.com/affaan-m/everything-claude-code.git` |
|
||||
| Evidence scope | Current `main` after PR #1970 workflow-security validator bypass fixes, PR #1971 metrics bridge cost-reporting fixes, PR #1972 `uncloud` skill merge, PR #1973 stale script cleanup, issue #1974 cost-reporting verification/closure, PR #1976 OpenAI/AstraFlow provider response guards, PR #1978 review/closure, catalog/operator dashboard refresh, ECC-Tools Wrangler OAuth billing readback mirror, AgentShield `840952a` fleet-ticket and Mini Shai-Hulud IOC evidence mirror, Mini Shai-Hulud/TanStack protection recheck, defensive-deny IOC scanner hardening, release name/plugin publication checklist, readiness/smoke gate enforcement for that checklist, release OIDC publishing-scope hardening, workflow line-ending normalization, current-head CI/security scan, work-items sync, Linear progress sync, the ITO-46 publication-path dry-run refresh, ITO-46 Linear closure, and the post-closure operator dashboard refresh |
|
||||
| Local status caveat | `git status --short --branch` was clean at dashboard generation time; generated evidence files are committed after the source snapshot they describe |
|
||||
|
||||
The actual release operator should repeat all publish-facing checks from the
|
||||
final release commit with a strictly clean checkout before publishing.
|
||||
|
||||
## Queue And Discussion State
|
||||
|
||||
| Surface | Command | Result |
|
||||
| --- | --- | --- |
|
||||
| Trunk PRs | `gh pr list --limit 100 --json number,title,state,author,updatedAt,url` | 0 open PRs |
|
||||
| Trunk issues | `gh issue list --limit 100 --json number,title,state,updatedAt,url,labels` | 0 open issues |
|
||||
| Discussion audit | `npm run discussion:audit -- --json` | Ready; 58 sampled discussions in `affaan-m/everything-claude-code`, 0 needing maintainer touch, 0 answerable discussions missing accepted answer, and 0 fetch errors |
|
||||
| Platform audit | `node scripts/platform-audit.js --json --allow-untracked docs/drafts/` | Ready; tracked repos report 0 open PRs, 0 open issues, 0 discussion maintainer-touch gaps, 0 answerable Q&A missing accepted answers, and 0 blocking dirty files |
|
||||
| Work-items sync | `node scripts/work-items.js sync-github --repo <tracked-repo>` for five tracked repos; `node scripts/status.js --json`; `node scripts/work-items.js list --json` | All five tracked repos synced with 0 open PRs/issues and no changed work items; local status reports 0 open, 0 blocked, and 0 closed work items |
|
||||
| Operator dashboard | `npm run operator:dashboard -- --markdown --write docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-18.md` | Regenerated at `4470e2e6702f17099d6feb137ba03ff00582c202`; dashboard ready true, publication ready false because release, npm, plugin, billing, and announcement gates are approval-gated; 0 PRs, 0 issues, and 0 discussion gaps remain across tracked repos; AgentShield enterprise evidence includes `840952a`; ECC Tools native-payments gate now names the narrowed ITO-61 blocker: create or verify Marketplace-managed Pro target billing-state with webhook provenance, configure the target account and `INTERNAL_API_SECRET`, then rerun target readback and the live announcement gate |
|
||||
|
||||
Tracked repositories in the platform audit and work-items sync were:
|
||||
|
||||
- `affaan-m/everything-claude-code`
|
||||
- `affaan-m/agentshield`
|
||||
- `affaan-m/JARVIS`
|
||||
- `ECC-Tools/ECC-Tools`
|
||||
- `ECC-Tools/ECC-website`
|
||||
|
||||
## Merge And Triage Batch
|
||||
|
||||
| Item | Result |
|
||||
| --- | --- |
|
||||
| PR #1970 | Merged workflow-security validator fixes for quoted `write-all` and `refs/pull/*` checkout bypasses; main includes `e06d0382` and `7bb31720` from that slice |
|
||||
| PR #1971 | Merged metrics bridge cost-reporting fixes, full costs-file scan behavior, and persistent warning de-duplication across hook subprocesses; main includes commits through `9b1d8918` |
|
||||
| PR #1972 | Merged `skills/uncloud/SKILL.md` with activation structure and uncloud command references; main includes `8b6aed0`, `2e5f30f`, and `caee7cf` |
|
||||
| PR #1973 | Merged stale `skills/strategic-compact/suggest-compact.sh` removal after confirming the active hook is `scripts/hooks/suggest-compact.js`; remote main includes `812d4d06` |
|
||||
| Issue #1974 | Closed after verifying current `origin/main` already reads the latest cumulative metrics bridge cost row and focused cost/metrics tests pass |
|
||||
| Catalog/operator refresh | Pushed `81fca2ce` to refresh generated catalog count, URL ledger, and operator dashboard state after #1973/#1974 |
|
||||
| PR #1976 | Merged provider response hardening for OpenAI-compatible and AstraFlow providers; main includes `eb0d8939` follow-up guards for empty/filtered provider choices, missing OpenAI `response.usage`, shared filtered-response error text, and credential-less provider construction validation |
|
||||
| Provider guard validation | `uv run --extra dev pytest -q tests/test_provider_tools.py tests/test_astraflow_provider.py`, `uv run --extra dev pytest -q`, `node tests/run-all.js`, and `git diff --check` passed before merging #1976 follow-up into main: 11 provider-focused Python tests, 76 full Python tests, 2509 Node tests, and clean whitespace checks |
|
||||
| Defensive-deny IOC scanner hardening | Pushed `04d4d819` so explicit Claude `permissions.deny` IOC entries are treated as defensive controls while the same IOC still fails in hooks, tasks, scripts, locks, and payload files; local `npm test` passed 2511/2511 and current-head CI `26017368895` passed 37/37 |
|
||||
| Release name/plugin publication checklist | Pushed `6c0fbfb6` to add `docs/releases/2.0.0-rc.1/release-name-plugin-publication-checklist-2026-05-18.md`; the artifact freezes rc.1 as Everything Claude Code / ECC, keeps npm `ecc-universal`, keeps Claude/Codex plugin slug `ecc`, cites current Anthropic/OpenAI plugin publication paths, and blocks rename/npm publish/plugin tag/submission/billing/social actions until final release evidence exists; GitHub Actions CI `26034898420` passed |
|
||||
| Dashboard and preview-pack checklist enforcement | Added `680aeff0` so `scripts/operator-readiness-dashboard.js` and `scripts/preview-pack-smoke.js` require the release-name/plugin publication checklist; local dashboard and smoke tests passed and preview-pack smoke now enforces 26 required artifacts |
|
||||
| AgentShield enterprise evidence mirror | Added `2ba0c62d` and refreshed the dashboard generator/GA roadmap/AgentShield enterprise roadmap so the ECC release evidence names AgentShield `840952a` fleet review ticket payloads and current Mini Shai-Hulud IOC breadcrumb coverage |
|
||||
| PR #1978 | Closed broad/failing outside Excel harness PR after review; recorded a corrected split path for a future smaller Excel harness proposal, install-target/tooling PR, plugin-runtime PR, and translation-automation PR |
|
||||
| Announcement draft tracking | Added `docs/drafts/release-1.10.1-announcement.md` so the stabilization announcement draft is tracked instead of remaining as release-blocking untracked local state |
|
||||
| Clean-worktree preview-pack smoke | Detached worktree at `680aeff0fb9a8598858e3105ba4742973ef386ab`; `node scripts/preview-pack-smoke.js --root <worktree> --format json` passed 5/5 with digest `0ed831dbd0cf`; 26 required artifacts, final verification commands, Hermes public sanitization boundary, and approval-gated publication blockers were all preserved |
|
||||
| Public queues | Rechecked after the merge and issue-closure batch; 0 PRs, 0 issues, and 0 discussion gaps remain across tracked repos |
|
||||
| Release OIDC publishing scope | Pushed `7911af4a` to keep the release workflow's trusted-publishing path scoped to release publication instead of broadening OIDC permissions across unrelated jobs; local workflow security validation passed |
|
||||
| Release workflow normalization | Pushed `97567a91` to normalize release workflow line endings after the OIDC hardening slice; current-head CI `26050727969` passed for `97567a91e79e1ee4c291eb78f5f9c30c2046ac94` |
|
||||
| Operator readiness evidence refresh | Pushed `0f1775e3`, `fe7b4f2b`, and `67e63e63` to refresh blocker evidence, regenerate the operator dashboard, and align publication readiness to the latest CI/security evidence; pushed `4470e2e6` to close ITO-46 publication-path evidence, then regenerated the dashboard at `4470e2e6702f17099d6feb137ba03ff00582c202`; current-head CI `26057806361` passed for `4470e2e6702f17099d6feb137ba03ff00582c202` |
|
||||
|
||||
## Supply-Chain And Security Evidence
|
||||
|
||||
| Gate | Command | Result |
|
||||
| --- | --- | --- |
|
||||
| Repo IOC scan | `npm run security:ioc-scan` | Passed; 198 files inspected |
|
||||
| Home persistence IOC scan | `node scripts/ci/scan-supply-chain-iocs.js --home --json` | Passed; 200 files inspected; `findings: []` |
|
||||
| ECC workspace IOC recheck | `node scripts/ci/scan-supply-chain-iocs.js --root <local ECC root> --home --json` | Passed; 1212 files inspected; `findings: []`; exact local path is kept out of public release evidence |
|
||||
| Narrow active persistence sweep | Targeted search over user-level Claude, VS Code, LaunchAgent/systemd, local-bin, `/tmp`, and `/private/tmp` campaign paths | Existing active targets: 2; no campaign marker hits |
|
||||
| Scanner fixture tests | `node tests/ci/scan-supply-chain-iocs.test.js` | 20 passed, 0 failed, including defensive Claude deny-wall pass and hook-with-same-IOC fail-closed coverage |
|
||||
| Advisory source refresh | `node scripts/ci/supply-chain-advisory-sources.js --refresh --json` | Ready with 9 sources; live refresh produced 1 OpenAI URL warning from Node fetch while primary TanStack, GitHub advisory, StepSecurity, Wiz, Socket, npm, and CISA sources returned OK |
|
||||
| No-lifecycle install | `npm ci --ignore-scripts` | Completed cleanly; 213 packages installed, 0 vulnerabilities |
|
||||
| npm audit | `npm audit --audit-level=high` | 0 vulnerabilities |
|
||||
| npm signatures | `npm audit signatures` | 213 verified registry signatures; 17 verified attestations |
|
||||
| Workflow security | `node scripts/ci/validate-workflow-security.js` | Validated 8 workflow files after the release OIDC publishing-scope hardening |
|
||||
| AgentShield project scan | `npx --no-install ecc-agentshield scan --format json` | Grade A / 99; 0 critical, 0 high, 0 medium; 6 low docs-example skill telemetry/governance findings |
|
||||
| Current-head CI security scan | `gh run view 26057806361 --repo affaan-m/everything-claude-code --json status,conclusion,headSha,jobs,url` | Completed successfully for `4470e2e6702f17099d6feb137ba03ff00582c202`; 37/37 CI jobs passed, including lint, workflow/component validation, coverage, cross-platform package-manager tests, npm audit, and supply-chain IOC scan |
|
||||
| Latest Supply-Chain Watch | `gh run view 26010432490 --repo affaan-m/everything-claude-code --json status,conclusion,headSha,url` | Completed successfully for `25ac57ac40e9fc5a0606e76e6339e72c79748c99`; rerun from the final release commit before publication |
|
||||
|
||||
## ITO-46 Publication Path Refresh
|
||||
|
||||
| Gate | Command | Result |
|
||||
| --- | --- | --- |
|
||||
| Clean publication-path baseline | `git status --short --branch`; `git rev-parse HEAD`; `git remote get-url origin` | Clean `main` at `67e63e63f9bfd074bd6a21bf6bac71f3dfefa58b`; remote `https://github.com/affaan-m/everything-claude-code.git` |
|
||||
| Package/plugin identity readback | `node -p "JSON.stringify({pkg, claude, codex, opencode}, null, 2)"` | `ecc-universal@2.0.0-rc.1`; Claude plugin `ecc@2.0.0-rc.1`; Codex plugin `ecc@2.0.0-rc.1`; OpenCode package `ecc-universal@2.0.0-rc.1` |
|
||||
| Name availability | `npm view ecc name version description repository.url --json`; `npm view @affaan-m/ecc name version --json`; `npm view ecc-universal name version dist-tags --json` | `ecc` is occupied by unrelated `ecc@0.0.2`; `@affaan-m/ecc` returns 404; `ecc-universal` registry latest remains `1.10.0` with no `next` dist-tag |
|
||||
| Plugin manifest tests | `node tests/plugin-manifest.test.js` | 54 passed, 0 failed |
|
||||
| Release surface tests | `node tests/docs/ecc2-release-surface.test.js` | 21 passed, 0 failed |
|
||||
| Claude plugin validation | `claude plugin validate .claude-plugin/plugin.json`; `claude plugin validate .`; `claude plugin tag .claude-plugin --dry-run` | Claude Code `2.1.143`; manifest validation passed; full plugin validation passed with one expected root `CLAUDE.md` context warning; tag dry run would create `ecc--v2.0.0-rc.1` |
|
||||
| Claude marketplace source help | `claude plugin marketplace add --help`; `claude plugin marketplace update --help` | Marketplace add supports URL, local path, GitHub repo, `--scope`, and `--sparse`; update supports targeted or all-marketplace refresh |
|
||||
| Codex marketplace help | `codex plugin marketplace add --help` | Codex CLI `0.131.0`; marketplace add supports local paths, `owner/repo[@ref]`, HTTPS Git URL, SSH Git URL, `--ref`, and `--sparse` |
|
||||
| Codex local marketplace smoke | `HOME="$(mktemp -d)" codex plugin marketplace add ./` | Added marketplace `ecc` from the local checkout without touching the real Codex config |
|
||||
| Codex GitHub-ref marketplace smoke | `HOME="$(mktemp -d)" codex plugin marketplace add affaan-m/everything-claude-code --ref "$(git rev-parse HEAD)"` | Added marketplace `ecc` from the public GitHub repo pinned to `67e63e63f9bfd074bd6a21bf6bac71f3dfefa58b` without touching the real Codex config |
|
||||
| npm package dry-run | `NPM_CONFIG_USERCONFIG=/dev/null npm pack --dry-run --json`; `NPM_CONFIG_USERCONFIG=/dev/null npm publish --tag next --dry-run` | Pack produced `ecc-universal-2.0.0-rc.1.tgz`, 2228 files, 4,348,504 bytes packed, 13,024,929 bytes unpacked, shasum `29d6a17029d80f5cb1df068880ba86c55a5d60f1`; publish dry-run would publish `ecc-universal@2.0.0-rc.1` with tag `next` |
|
||||
| OpenCode package build | `npm run build:opencode` | Passed |
|
||||
| Preview pack smoke | `npm run preview-pack:smoke` | Ready yes; digest `0ed831dbd0cf`; 5 passed, 0 failed |
|
||||
| Official docs check | Anthropic `https://code.claude.com/docs/en/plugins` and `https://code.claude.com/docs/en/plugin-marketplaces`; OpenAI `https://developers.openai.com/codex/plugins/build` | Anthropic documents self-hosted marketplace sources; OpenAI documents repo/personal marketplaces and the official Plugin Directory. ECC has not created a real release tag, official listing, or npm publication in this pass |
|
||||
| ITO-46 closure | Linear ITO-46 comment `9ef92056-ab23-4eed-bfdb-932dddc2b056`; Linear issue status `Done`; GitHub Actions `26057806361` | Publication-path docs now record every channel, name conflicts, package/plugin dry-run commands, and blocker register; Codex repo-marketplace distribution is verified but official Plugin Directory listing is not claimed before OpenAI submission/listing evidence |
|
||||
|
||||
## Linear Progress Sync
|
||||
|
||||
| Surface | Evidence |
|
||||
| --- | --- |
|
||||
| ITO-57 issue comments | `0b9931b9-1556-4ebc-a70c-f3635557625d` records May 18 queue counts, #1970/#1971/#1972/#1976 merge evidence, supply-chain verification, current-head CI URL, deferred gates, and next slices; reply `6fa15367-d994-4e53-ade3-9462477e1100` records the expanded TanStack/Mini Shai-Hulud recheck, defensive-deny scanner fix, current-head CI `26017368895`, and post-push platform audit; comment `3fe5b2b7-c4fe-401c-a317-b40d72119cb3` records the final emergency refresh against `97567a91`, AgentShield `4e36aab`, clean ECC/Ito/Documents workspace IOC scans, absent dead-man/persistence artifacts, and package-manager/Claude deny-wall posture; comment `43837404-c01c-4aaa-b5e2-1e784c136d69` records ECC-Tools `brace-expansion` alert 44 fixed in `e56fc1a` with CI `26054671308` and Dependabot API `state: fixed` |
|
||||
| ITO-52 issue status | `f2e5a208-de91-4a3a-960b-5362d12aa5a4` records ECC-Tools `69ca535` team-learning feedback controls, local verification, and CI `26054455434`; Linear ITO-52 is Done |
|
||||
| ITO-61 issue status | `6904e4fb-bec7-4787-90e2-759f077a628c` records the narrowed native-payments readback blocker: Wrangler OAuth now works, aggregate readback is clean, but there is still no Marketplace-managed Pro target billing-state with webhook provenance and the local announcement preflight is missing the target account plus `INTERNAL_API_SECRET` |
|
||||
| ECC platform project comment | `e32e5b7a-287b-4bf4-9ed7-314389a157e1` records the earlier current public queue, security, #1976, and remaining-gate state at the project level; follow-up ITO-44 comments `a01eeef3-c69b-48c0-8804-a4682acfc1ef` and `6b0885cc-c4e9-40db-899b-f7b88b4aa046` record ITO-52 completion and the fixed ECC-Tools Dependabot alert |
|
||||
| Project status update caveat | Linear returned "Project status updates are not enabled for this workspace"; project comment was used as the supported status surface |
|
||||
|
||||
## Current Publication Blockers
|
||||
|
||||
- GitHub prerelease `v2.0.0-rc.1` is still not created in this pass.
|
||||
- npm `ecc-universal@2.0.0-rc.1` is still not published to the `next`
|
||||
dist-tag.
|
||||
- Claude plugin tag and marketplace propagation remain approval-gated.
|
||||
- Codex repo-marketplace distribution is verified for rc.1, but official
|
||||
Plugin Directory publishing remains blocked on OpenAI's self-serve publishing
|
||||
surface.
|
||||
- ECC Tools billing/native-payments copy remains blocked until a Marketplace
|
||||
Pro purchase/webhook path writes ready production `billing-state:*`
|
||||
provenance for the target Marketplace test account, then
|
||||
`npm run billing:kv-readback -- --account <github-login> --require-ready`
|
||||
with working Cloudflare API auth or repaired Wrangler OAuth, followed by
|
||||
`npm run billing:announcement-gate -- --account <github-login>`, return
|
||||
announcement-ready gates. The latest Wrangler OAuth aggregate readback found
|
||||
256 `account-billing:*` records, 256 `billing-state:*` records, 197
|
||||
Marketplace-source records, 59 Stripe-source records, 53 Pro records, 4
|
||||
Marketplace webhook-provenance records, all `Open Source`, 0 Marketplace Pro
|
||||
states, 0 ready-like Marketplace Pro states, and 0 parse failures. ECC-Tools
|
||||
commit `632e059` adds the follow-up target-account readback mode, redacts
|
||||
the account login and raw KV key names, and requires both target key families
|
||||
before `--require-ready` can pass. ECC-Tools commit `13cd3fc` normalizes
|
||||
billing-state key casing. The latest ITO-61 retry fails because no
|
||||
Marketplace-managed Pro state exists and the announcement preflight is
|
||||
missing the target account plus `INTERNAL_API_SECRET`; Linear ITO-61 tracks
|
||||
the exact target-account acceptance criteria.
|
||||
- Release notes, X, LinkedIn, GitHub release, and longform copy still need final
|
||||
live URLs after release/package/plugin URLs exist.
|
||||
- The local checkout is clean after the dashboard/evidence refresh, but a
|
||||
strict clean-checkout release pass remains required before real publication.
|
||||
|
||||
## Result
|
||||
|
||||
The tracked public PR queue, issue queue, discussion queue, local work-items
|
||||
bridge, release-name/plugin publication gate, and Mini Shai-Hulud/TanStack
|
||||
protection loop are current on May 18, 2026 for current `main` through
|
||||
`97567a91`, with follow-up ECC Tools billing-gate hardening in `632e059`
|
||||
and AgentShield enterprise/security hardening through `4e36aab`.
|
||||
This improves publication readiness but does not replace the approval-gated
|
||||
release, package, plugin, billing, and announcement steps in
|
||||
`publication-readiness.md`.
|
||||
@@ -6,9 +6,6 @@ URLs from the exact commit being released.
|
||||
|
||||
For the current rc.1 naming decision and package/plugin publication path, see
|
||||
[`naming-and-publication-matrix.md`](naming-and-publication-matrix.md).
|
||||
For the May 18 release name, package, Claude plugin, Codex plugin, and
|
||||
publication-order gate, see
|
||||
[`release-name-plugin-publication-checklist-2026-05-18.md`](release-name-plugin-publication-checklist-2026-05-18.md).
|
||||
For the assembled rc.1 preview pack boundary, see
|
||||
[`preview-pack-manifest.md`](preview-pack-manifest.md).
|
||||
For the May 12 dry-run evidence pass, see
|
||||
@@ -38,24 +35,11 @@ Shai-Hulud/TanStack local protection recheck, legacy-tail and Linear progress
|
||||
routing, deterministic preview-pack smoke gate, and current operator dashboard
|
||||
refresh, see
|
||||
[`publication-evidence-2026-05-17.md`](publication-evidence-2026-05-17.md).
|
||||
For the May 18 current-head queue, workflow-security/metrics/uncloud merge
|
||||
batch, PR #1978 review/closure, Mini Shai-Hulud/TanStack local and home
|
||||
protection recheck, npm no-lifecycle install/audit/signature gates,
|
||||
AgentShield project scan, AgentShield `840952a` enterprise/IOC evidence mirror,
|
||||
release OIDC publishing-scope hardening, workflow normalization, later
|
||||
dashboard/publication-readiness refreshes through `67e63e63`, work-items sync,
|
||||
Linear progress comments, ITO-46 closure, operator dashboard refresh, and
|
||||
current-head CI/security scan success for `4470e2e6`, see
|
||||
[`publication-evidence-2026-05-18.md`](publication-evidence-2026-05-18.md).
|
||||
For the operator-facing prompt-to-artifact readiness dashboard from the same
|
||||
May 16 pass, see
|
||||
[`operator-readiness-dashboard-2026-05-15.md`](operator-readiness-dashboard-2026-05-15.md).
|
||||
For the May 17 operator dashboard refresh, see
|
||||
[`operator-readiness-dashboard-2026-05-17.md`](operator-readiness-dashboard-2026-05-17.md).
|
||||
For the May 18 operator dashboard refresh, see
|
||||
[`operator-readiness-dashboard-2026-05-18.md`](operator-readiness-dashboard-2026-05-18.md).
|
||||
For the May 18 live/pending release URL ledger, see
|
||||
[`release-url-ledger-2026-05-18.md`](release-url-ledger-2026-05-18.md).
|
||||
|
||||
## Release Identity Matrix
|
||||
|
||||
@@ -70,7 +54,7 @@ For the May 18 live/pending release URL ledger, see
|
||||
| Claude plugin slug | `ecc` / `ecc@ecc` install path | `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json` | `node tests/hooks/hooks.test.js` | `publication-evidence-2026-05-12.md` | Plugin owner | Evidence recorded |
|
||||
| Claude plugin manifest | `2.0.0-rc.1`, no unsupported `agents` or explicit `hooks` fields | `.claude-plugin/plugin.json`, `.claude-plugin/PLUGIN_SCHEMA_NOTES.md` | `claude plugin validate .claude-plugin/plugin.json` | `publication-evidence-2026-05-12.md` | Plugin owner | Evidence recorded |
|
||||
| Codex plugin manifest | `2.0.0-rc.1` with shared skill source | `.codex-plugin/plugin.json` | `node tests/docs/ecc2-release-surface.test.js` | `publication-evidence-2026-05-12.md` | Plugin owner | Evidence recorded |
|
||||
| Codex repo marketplace | `ecc@2.0.0-rc.1` exposed through `.agents/plugins/marketplace.json` | `.agents/plugins/marketplace.json`, `.codex-plugin/README.md` | `HOME="$(mktemp -d)" codex plugin marketplace add <local-checkout>` | `publication-evidence-2026-05-15.md` | Plugin owner | Repo-marketplace path verified; do not claim official Plugin Directory listing before OpenAI submission evidence |
|
||||
| Codex repo marketplace | `ecc@2.0.0-rc.1` exposed through `.agents/plugins/marketplace.json` | `.agents/plugins/marketplace.json`, `.codex-plugin/README.md` | `HOME="$(mktemp -d)" codex plugin marketplace add <local-checkout>` | `publication-evidence-2026-05-15.md` | Plugin owner | Repo-marketplace path verified; official Plugin Directory publishing coming soon |
|
||||
| OpenCode package | `ecc-universal` plugin module | `.opencode/package.json`, `.opencode/index.ts` | `npm run build:opencode` | `publication-evidence-2026-05-12.md` | Package owner | Evidence recorded |
|
||||
| Agent metadata | `2.0.0-rc.1` | `agent.yaml`, `.agents/plugins/marketplace.json` | `node tests/scripts/catalog.test.js` | `publication-evidence-2026-05-12.md` | Release owner | Evidence recorded |
|
||||
| Migration copy | rc.1 upgrade path, not GA claim | `release-notes.md`, `quickstart.md`, `HERMES-SETUP.md` | `npx markdownlint-cli '**/*.md' --ignore node_modules` | `publication-evidence-2026-05-13.md` | Docs owner | Evidence recorded |
|
||||
@@ -82,10 +66,10 @@ For the May 18 live/pending release URL ledger, see
|
||||
| GitHub release | Tag exists, release notes use final URLs, assets attached if needed | `gh release view v2.0.0-rc.1 --json tagName,url,isPrerelease` | `Blocker: release not found on 2026-05-12` | Release owner | Pending approval |
|
||||
| npm package | `npm pack --dry-run` has expected files, version matches, rc goes to `next` | `npm pack --dry-run` and `npm publish --tag next --dry-run` where supported | `Blocker: actual publish requires approval; dry run passed with next tag` | Package owner | Dry-run passed |
|
||||
| Claude plugin | Manifest validates, marketplace JSON points to public repo, install docs match slug | `claude plugin validate .claude-plugin/plugin.json`; `claude plugin tag .claude-plugin --dry-run`; isolated temp-home install smoke | `Blocker: real tag creation/push requires approval` | Plugin owner | Clean-checkout dry-run and install smoke recorded |
|
||||
| Codex plugin | Manifest version matches package and docs, repo marketplace points at the plugin root, and OpenAI's current official Plugin Directory status is recorded | `node tests/docs/ecc2-release-surface.test.js`; `node tests/plugin-manifest.test.js`; `codex plugin marketplace add --help`; temp-home `codex plugin marketplace add <local-checkout>` | `Blocker: official Plugin Directory listing requires OpenAI submission/listing evidence` | Plugin owner | Repo-marketplace distribution verified; official directory pending |
|
||||
| Codex plugin | Manifest version matches package and docs, repo marketplace points at the plugin root, and OpenAI's current official Plugin Directory status is recorded | `node tests/docs/ecc2-release-surface.test.js`; `node tests/plugin-manifest.test.js`; `codex plugin marketplace add --help`; temp-home `codex plugin marketplace add <local-checkout>` | `Blocker: official Plugin Directory publishing and self-serve management are documented as coming soon` | Plugin owner | Repo-marketplace distribution verified; official directory pending |
|
||||
| OpenCode package | Build output is regenerated from source and package metadata is current | `npm run build:opencode` | `Blocker: none for local build; public distribution still follows npm/plugin release` | Package owner | Evidence recorded |
|
||||
| ECC Tools billing reference | Any billing claim links to verified Marketplace/App state | `env -u GITHUB_TOKEN gh repo view ECC-Tools/ECC-Tools --json nameWithOwner,isPrivate,viewerPermission` plus internal `/api/billing/readiness?accountLogin=<marketplace-test-account>` readback | `Blocker: ECC-Tools #73 added announcementGate; live Marketplace test-account readback must return announcementGate.ready === true before payment announcement` | ECC Tools owner | Code gate recorded; live billing readback pending |
|
||||
| Announcement copy | X, LinkedIn, GitHub release, and longform copy point to live URLs | placeholder-marker scan and `release-url-ledger-2026-05-18.md` | `Blocker: final live release/npm/plugin/billing URLs do not exist yet; live and pending URLs are separated in the May 18 ledger` | Release owner | URL ledger recorded; final URLs pending |
|
||||
| Announcement copy | X, LinkedIn, GitHub release, and longform copy point to live URLs | `rg -n "TODO" docs/releases/2.0.0-rc.1` and repeat for `TBD` | `Blocker: final live release/npm/plugin URLs do not exist yet` | Release owner | Pending |
|
||||
| Privileged workflow hardening | Release and maintenance workflows avoid persisted checkout tokens | `node scripts/ci/validate-workflow-security.js` | `Blocker:` | Release owner | Evidence recorded in post-hardening refresh |
|
||||
|
||||
## Required Command Evidence
|
||||
@@ -94,24 +78,22 @@ Record the exact commit SHA and command output before any publication action:
|
||||
|
||||
| Evidence | Command | Required result | Recorded output |
|
||||
| --- | --- | --- | --- |
|
||||
| Clean release branch | `git status --short --branch` | On intended release commit; no unrelated files | `4470e2e6`: `## main...origin/main`; repeat from the exact final publication commit before release |
|
||||
| Preview-pack smoke | `npm run preview-pack:smoke` | Preview pack artifacts, Hermes boundary, final verification command list, and publication blockers pass | `publication-evidence-2026-05-18.md`: ready yes, digest `0ed831dbd0cf`, 5 passed, 0 failed; repeat in the final strict clean-checkout release pass |
|
||||
| Harness audit | `npm run harness:audit -- --format json` | 70/70 passing | `99e01ded`: 70/70, 0 top actions |
|
||||
| Adapter scorecard | `npm run harness:adapters -- --check` | PASS | `99e01ded`: PASS, 11 adapters |
|
||||
| Observability readiness | `npm run observability:ready` | 21/21 passing | `publication-evidence-2026-05-18.md`: 21/21, ready yes |
|
||||
| Release safety gate | `npm run observability:ready -- --format json` | Release Safety category passing with publication readiness, supply-chain, workflow security, package surface, and release-surface evidence | May 18 evidence keeps release safety passing; repeat the JSON gate from the exact final release commit |
|
||||
| Supply-chain verification | `npm audit --json`; `npm audit signatures`; `cd ecc2 && cargo audit -q`; Dependabot alerts; GitGuardian Security Checks | 0 vulnerabilities/alerts, registry signatures verified, GitGuardian clean | `publication-evidence-2026-05-18.md` plus CI `26057806361`: npm registry signatures and attestations verified in the evidence pass, 0 high-or-higher npm vulnerabilities, repo/home IOC scans clean, supply-chain IOC scan passed |
|
||||
| Root suite | `node tests/run-all.js` | 0 failures | `99e01ded`: local `node tests/run-all.js` passed 2512/2512; current-head CI `26057806361` passed the full OS/runtime/package-manager matrix for `4470e2e6` |
|
||||
| Markdown lint | `npx markdownlint-cli '**/*.md' --ignore node_modules` | 0 failures | CI `26057806361`: markdownlint passed on current head; rerun after any release-copy edits |
|
||||
| Clean release branch | `git status --short --branch` | On intended release commit; no unrelated files | Pending final strict clean-checkout release pass; `publication-evidence-2026-05-17.md` records current `main` with unrelated untracked `docs/drafts/` |
|
||||
| Preview-pack smoke | `npm run preview-pack:smoke` | Preview pack artifacts, Hermes boundary, final verification command list, and publication blockers pass | `publication-evidence-2026-05-17.md`: ready yes, digest `dfb1ed014607`, 5 passed, 0 failed; repeat in a final strict clean-checkout release pass |
|
||||
| Harness audit | `npm run harness:audit -- --format json` | 70/70 passing | `publication-evidence-2026-05-17.md`: 70/70 |
|
||||
| Adapter scorecard | `npm run harness:adapters -- --check` | PASS | `publication-evidence-2026-05-16.md`: PASS, 11 adapters |
|
||||
| Observability readiness | `npm run observability:ready` | 21/21 passing | `publication-evidence-2026-05-17.md`: 21/21, ready yes |
|
||||
| Release safety gate | `npm run observability:ready -- --format json` | Release Safety category passing with publication readiness, supply-chain, workflow security, package surface, and release-surface evidence | `publication-evidence-2026-05-13-post-hardening.md`: Release Safety 3/3 |
|
||||
| Supply-chain verification | `npm audit --json`; `npm audit signatures`; `cd ecc2 && cargo audit -q`; Dependabot alerts; GitGuardian Security Checks | 0 vulnerabilities/alerts, registry signatures verified, GitGuardian clean | `publication-evidence-2026-05-17.md`: npm registry signatures and attestations verified, 0 high-or-higher npm vulnerabilities, supply-chain IOC scan clean |
|
||||
| Root suite | `node tests/run-all.js` | 0 failures | `publication-evidence-2026-05-17.md`: `npm test` passed 2487/2487, 0 failed |
|
||||
| Markdown lint | `npx markdownlint-cli '**/*.md' --ignore node_modules` | 0 failures | `publication-evidence-2026-05-17.md`: passed after ja-JP autonomous-loop anchor repair |
|
||||
| Package surface | `node tests/scripts/npm-publish-surface.test.js` | 0 failures; no Python bytecode in npm tarball | `2/2` passed in May 12 evidence pass |
|
||||
| Release surface | `node tests/docs/ecc2-release-surface.test.js` | 0 failures | May 18 evidence refresh: 21/21 passed after public-path sanitization, during the `0f1775e3` operator-readiness refresh, and again in the ITO-46 dry-run pass before `4470e2e6` |
|
||||
| Release surface | `node tests/docs/ecc2-release-surface.test.js` | 0 failures | `publication-evidence-2026-05-16.md`: 20/20 passed |
|
||||
| Optional Rust surface | `cd ecc2 && cargo test` | 0 failures or explicit deferral | `publication-evidence-2026-05-16.md`: 462/462 passed, existing warnings only |
|
||||
| Queue baseline | `node scripts/platform-audit.js --json` across trunk, AgentShield, JARVIS, ECC Tools, and ECC website | Under 20 open PRs and under 20 open issues | `4470e2e6`: platform audit ready, 0 open PRs, 0 open issues, 0 conflicting PRs, and 0 blocking dirty files in the regenerated dashboard snapshot |
|
||||
| Discussion baseline | `node scripts/platform-audit.js --json` and `node scripts/discussion-audit.js --json` | No unmanaged active discussion queue and no answerable Q&A missing an accepted answer | `4470e2e6`: platform audit sampled 58 trunk discussions, 0 needing maintainer touch, 0 answerable discussions missing accepted answer; `docs/architecture/discussion-response-playbook.md` records response templates and security escalation rules |
|
||||
| Linear roadmap | Linear project and issue readback | Detailed roadmap exists with release, security, AgentShield, ECC Tools, legacy, and observability lanes | May 18 Linear comments include ITO-57 `3fe5b2b7-c4fe-401c-a317-b40d72119cb3` and ITO-44 `fb4a4f33-6c2d-421a-bbdb-63cfad3e3ee4`; earlier evidence records the project and 16 issue lanes |
|
||||
| Operator readiness dashboard | `npm run operator:dashboard -- --json` | Current queue state mapped to macro-goal deliverables and incomplete gaps | `4470e2e6`: regenerated May 18 dashboard from current main; platform audit ready true, 0 open PRs, 0 open issues, 0 discussion gaps, 0 dirty files, and publication gates still approval-gated |
|
||||
| Release URL ledger | `docs/releases/2.0.0-rc.1/release-url-ledger-2026-05-18.md` plus placeholder-marker scan | Live links and approval-gated links are separated before announcement copy is posted | Ledger records public repo/docs/CI/supply-chain/npm/OpenAI Codex documentation URLs and blocks GitHub release/npm/plugin/billing/social URLs until approval-gated checks pass |
|
||||
| Release name and plugin publication checklist | `docs/releases/2.0.0-rc.1/release-name-plugin-publication-checklist-2026-05-18.md` | Name/package/plugin values are frozen, final-release commands are listed, and Claude/Codex publication paths cite current official docs | Checklist keeps `Everything Claude Code / ECC`, `ecc-universal`, and plugin slug `ecc` for rc.1; no rename, npm publish, plugin tag, official listing, billing claim, or announcement before final evidence |
|
||||
| Queue baseline | `gh pr list` / `gh issue list` across trunk, AgentShield, JARVIS, ECC Tools, and ECC website | Under 20 open PRs and under 20 open issues | `publication-evidence-2026-05-17.md`: platform audit ready, 0 open PRs and 0 open issues across checked repos |
|
||||
| Discussion baseline | `node scripts/discussion-audit.js --json` | No unmanaged active discussion queue and no answerable Q&A missing an accepted answer | `publication-evidence-2026-05-15.md`: 58 trunk discussions, 0 without maintainer touch; other tracked repos disabled or 0 |
|
||||
| Linear roadmap | Linear project and issue readback | Detailed roadmap exists with release, security, AgentShield, ECC Tools, legacy, and observability lanes | `publication-evidence-2026-05-15.md`: project and 16 issue lanes recorded |
|
||||
| Operator readiness dashboard | `npm run operator:dashboard -- --json --allow-untracked docs/drafts/` | Current queue state mapped to macro-goal deliverables and incomplete gaps | `publication-evidence-2026-05-17.md`: generated from `27dc2918`, platform ready true, dashboard ready true, 0 open PRs, 0 open issues, 0 discussion gaps |
|
||||
|
||||
## Do Not Publish If
|
||||
|
||||
@@ -132,7 +114,6 @@ Record the exact commit SHA and command output before any publication action:
|
||||
3. Create or verify the GitHub prerelease.
|
||||
4. Publish npm with the rc dist-tag.
|
||||
5. Submit or update plugin marketplace surfaces.
|
||||
6. Regenerate the release URL ledger and update release notes with final live
|
||||
URLs.
|
||||
6. Update release notes with final live URLs.
|
||||
7. Publish GitHub release copy.
|
||||
8. Publish X, LinkedIn, and longform copy only after the public URLs work.
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
# ECC v2.0.0-rc.1 Release Name And Plugin Publication Checklist
|
||||
|
||||
Snapshot date: 2026-05-18.
|
||||
|
||||
This checklist is the operator gate for release naming, package publication,
|
||||
and Claude/Codex plugin distribution. It is not a publication action by itself.
|
||||
Run it from the exact release commit before creating tags, publishing npm,
|
||||
submitting marketplace forms, or posting announcements.
|
||||
|
||||
## Fixed rc.1 Decision
|
||||
|
||||
Ship `v2.0.0-rc.1` as **Everything Claude Code (ECC)**.
|
||||
|
||||
- Keep the GitHub repo at `affaan-m/everything-claude-code`.
|
||||
- Keep the npm package as `ecc-universal`.
|
||||
- Keep Claude and Codex plugin slugs as `ecc`.
|
||||
- Publish the npm prerelease on the `next` dist-tag, not `latest`.
|
||||
- Do not rename to `affaan-m/ecc`, `ecc`, or `@affaan-m/ecc` before rc.1.
|
||||
|
||||
Reasons:
|
||||
|
||||
- `ecc-universal` is the current working install and package surface.
|
||||
- `ecc` on npm is occupied by an unrelated elliptic-curve package.
|
||||
- `@affaan-m/ecc` is unclaimed on npm, but would require a migration plan.
|
||||
- `affaan-m/ecc` is not available to the current GitHub auth context.
|
||||
- Claude and Codex already expose the desired short namespace as `ecc`.
|
||||
|
||||
## Current Surface Evidence
|
||||
|
||||
| Surface | Current value | Evidence command | 2026-05-18 result | Release action |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Git commit | `67e63e63f9bfd074bd6a21bf6bac71f3dfefa58b` | `git rev-parse HEAD` | Recorded from clean `main` before this ITO-46 evidence refresh | Re-run from final release commit |
|
||||
| GitHub repo | `affaan-m/everything-claude-code` | `git remote get-url origin` | `https://github.com/affaan-m/everything-claude-code.git` | Keep for rc.1 |
|
||||
| Possible short repo | `affaan-m/ecc` | `gh repo view affaan-m/ecc --json nameWithOwner,url,isPrivate` | GraphQL could not resolve repository | Do not depend on it for rc.1 |
|
||||
| npm package | `ecc-universal@2.0.0-rc.1` local, `1.10.0` registry latest | `node -p "require('./package.json').name + '@' + require('./package.json').version"` and `npm view ecc-universal name version dist-tags --json` | Local rc.1 ready; registry still latest `1.10.0` | Publish rc.1 with `--tag next` after approval |
|
||||
| Exact npm short name | `ecc` | `npm view ecc name version description repository.url --json` | Occupied by unrelated `ecc@0.0.2` | Do not use |
|
||||
| Scoped npm short name | `@affaan-m/ecc` | `npm view @affaan-m/ecc name version --json` | 404 | Candidate only after migration plan |
|
||||
| Claude plugin | `ecc@2.0.0-rc.1` | `claude plugin validate .claude-plugin/plugin.json`; `claude plugin validate .`; `claude plugin tag .claude-plugin --dry-run` | Validation passed on Claude Code `2.1.143`; full plugin validation has one expected root `CLAUDE.md` context warning; dry run would create `ecc--v2.0.0-rc.1` | Run dry-run tag again from the final commit, then tag/push only after approval |
|
||||
| Claude marketplace | `.claude-plugin/marketplace.json` | `claude plugin marketplace add --help`; Anthropic plugin marketplace docs | GitHub repo, git URL, remote marketplace JSON, and local path marketplace sources are supported | Verify post-tag marketplace install/update path after final evidence |
|
||||
| Codex plugin | `ecc@2.0.0-rc.1` | `node tests/plugin-manifest.test.js`; `codex plugin marketplace add --help`; OpenAI Codex plugin docs | Plugin manifest passed 54/54; local and GitHub-ref repo marketplace smokes passed on Codex CLI `0.131.0` | Use repo marketplace for rc.1; do not claim official directory listing until OpenAI publishing path is available |
|
||||
| OpenCode package | `ecc-universal@2.0.0-rc.1` | `node -p "require('./.opencode/package.json').name + '@' + require('./.opencode/package.json').version"` | Matches rc.1 package identity | Follow npm package publication |
|
||||
| Billing claim | Pending ECC Tools readiness | ECC Tools billing gate and Marketplace account readback | Code-side gate exists; live Marketplace account readback still pending | Do not announce native payments |
|
||||
|
||||
## Required Gate
|
||||
|
||||
Run these checks from the final release commit and paste the exact output into
|
||||
a fresh `publication-evidence-YYYY-MM-DD.md` file before release actions:
|
||||
|
||||
```bash
|
||||
git status --short --branch
|
||||
git rev-parse HEAD
|
||||
git remote get-url origin
|
||||
npm view ecc name version description repository.url --json
|
||||
npm view @affaan-m/ecc name version --json
|
||||
npm view ecc-universal name version dist-tags --json
|
||||
node tests/plugin-manifest.test.js
|
||||
node tests/docs/ecc2-release-surface.test.js
|
||||
claude plugin validate .claude-plugin/plugin.json
|
||||
claude plugin tag .claude-plugin --dry-run
|
||||
codex plugin marketplace add --help
|
||||
HOME="$(mktemp -d)" codex plugin marketplace add ./
|
||||
HOME="$(mktemp -d)" codex plugin marketplace add affaan-m/everything-claude-code --ref "$(git rev-parse HEAD)"
|
||||
npm pack --dry-run --json
|
||||
npm publish --tag next --dry-run
|
||||
npm run build:opencode
|
||||
npm run preview-pack:smoke
|
||||
```
|
||||
|
||||
If a command is unavailable on the release machine, record the exact error and
|
||||
keep the related publication action blocked.
|
||||
|
||||
## Publication Order
|
||||
|
||||
| Step | Action | Required evidence | Stop condition |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Freeze name and version | Package, Claude plugin, Codex plugin, OpenCode package, `VERSION`, and release docs all say `2.0.0-rc.1` | Any `preview`/`rc.1` mismatch |
|
||||
| 2 | Verify clean release branch | `git status --short --branch` shows only the intended release commit and no unrelated drift | Any unexplained dirty file |
|
||||
| 3 | Verify package and plugin manifests | `node tests/plugin-manifest.test.js` and `node tests/docs/ecc2-release-surface.test.js` pass | Manifest or release-surface failure |
|
||||
| 4 | Dry-run package surface | `npm pack --dry-run --json`; `npm publish --tag next --dry-run` | Missing files, wrong dist-tag, or publish dry-run failure |
|
||||
| 5 | Dry-run Claude distribution | `claude plugin validate`; `claude plugin tag .claude-plugin --dry-run`; marketplace source/help evidence | Validation, tag, or install-smoke failure |
|
||||
| 6 | Verify Codex repo marketplace | `codex plugin marketplace add --help`; temp-home local and GitHub-ref repo marketplace add smoke; OpenAI official directory status recorded | Missing repo marketplace or unverified official-directory status |
|
||||
| 7 | Verify OpenCode package | `npm run build:opencode` | Build failure |
|
||||
| 8 | Regenerate release URL ledger | Live and approval-gated URLs separated in `release-url-ledger-YYYY-MM-DD.md` | Placeholder, private URL, or announcement URL drift |
|
||||
| 9 | Create GitHub prerelease | `gh release view v2.0.0-rc.1 --json tagName,url,isPrerelease` | Missing URL or wrong prerelease flag |
|
||||
| 10 | Publish npm rc | `npm view ecc-universal version dist-tags --json` shows rc.1 on `next` | rc.1 lands on `latest` or registry output is unclear |
|
||||
| 11 | Publish/plugin-submit | Claude official submission and Codex repo marketplace evidence recorded | Form not submitted, listing not visible, or docs status changed |
|
||||
| 12 | Announce | X, LinkedIn, GitHub release, and longform copy use final live URLs | Any final URL is still pending |
|
||||
|
||||
## Do Not Proceed
|
||||
|
||||
- Do not publish npm before `npm pack --dry-run --json` is captured from the
|
||||
final release commit.
|
||||
- Do not create or push Claude plugin tags before `claude plugin tag
|
||||
.claude-plugin --dry-run` passes from the final release commit.
|
||||
- Do not claim an official Codex Plugin Directory listing unless OpenAI
|
||||
documents a public submission path or confirms the plugin has been listed.
|
||||
- Do not announce billing, Marketplace, or native payments until ECC Tools live
|
||||
Marketplace account readback returns ready.
|
||||
- Do not rename the repo or package until rc.1 is published and a migration
|
||||
guide maps old names to new names.
|
||||
- Do not post social copy while any release, npm, plugin, or billing URL is
|
||||
still approval-gated.
|
||||
|
||||
## External Distribution Sources
|
||||
|
||||
- Anthropic Claude Code plugin docs: `https://code.claude.com/docs/en/plugins`
|
||||
- Anthropic Claude Code marketplace docs:
|
||||
`https://code.claude.com/docs/en/plugin-marketplaces`
|
||||
- OpenAI Codex plugin docs:
|
||||
`https://developers.openai.com/codex/plugins/build#add-a-marketplace-from-the-cli`
|
||||
|
||||
As of this snapshot, Anthropic documents self-hosted marketplace distribution
|
||||
through GitHub, git URL, remote marketplace JSON, and local path sources.
|
||||
OpenAI documents repo/personal marketplace distribution for Codex and describes
|
||||
an official Plugin Directory, but ECC has not submitted or received an official
|
||||
directory listing in this pass.
|
||||
@@ -16,11 +16,7 @@ Claude Code remains a core target. Codex, OpenCode, Cursor, Gemini, and other ha
|
||||
- Added Zed as a project-local planning/install target while keeping BYOK and OpenRouter secrets outside ECC-managed project files.
|
||||
- Added command-registry coverage, platform audit, discussion audit, operator dashboard, Linear progress readiness, and preview-pack smoke gates.
|
||||
- Added a local [observability readiness gate](../../architecture/observability-readiness.md) for loop status, session traces, harness audit, and ECC2 tool-risk logs.
|
||||
- Refreshed the release-readiness evidence after the May 2026 Mini
|
||||
Shai-Hulud/TanStack campaign follow-up, including full-campaign AgentShield
|
||||
IOC coverage, queue-zero/discussion checks, a detailed Linear roadmap gate,
|
||||
the May 18 operator dashboard snapshot, and a live/pending release URL
|
||||
ledger for announcement gating.
|
||||
- Refreshed the release-readiness evidence after the May 2026 Mini Shai-Hulud/TanStack campaign follow-up, including full-campaign AgentShield IOC coverage, queue-zero/discussion checks, a detailed Linear roadmap gate, and the May 17 operator dashboard snapshot.
|
||||
|
||||
## Since v1.10.0
|
||||
|
||||
@@ -48,9 +44,6 @@ feature branch:
|
||||
- launch collateral for GitHub release copy, X, LinkedIn, article outline,
|
||||
Telegram/Hermes handoff, demo prompts, and the approval-gated launch
|
||||
checklist.
|
||||
- a release URL ledger that separates links which already resolve from links
|
||||
that must wait for the GitHub release, npm rc package, plugin tag/directory,
|
||||
and ECC Tools billing readback.
|
||||
|
||||
## Why This Matters
|
||||
|
||||
@@ -91,12 +84,9 @@ What stays local:
|
||||
2. Read the [Hermes setup guide](../../HERMES-SETUP.md).
|
||||
3. Review the [cross-harness architecture](../../architecture/cross-harness.md).
|
||||
4. Run the [observability readiness gate](../../architecture/observability-readiness.md).
|
||||
5. Check the [release URL ledger](release-url-ledger-2026-05-18.md) before
|
||||
using any announcement links.
|
||||
6. Start with one workflow lane: engineering, research, content, or outreach.
|
||||
7. Import only sanitized operator patterns into ECC skills.
|
||||
8. Treat `ecc2/` as an alpha control plane until release packaging and installer
|
||||
behavior is finalized.
|
||||
5. Start with one workflow lane: engineering, research, content, or outreach.
|
||||
6. Import only sanitized operator patterns into ECC skills.
|
||||
7. Treat `ecc2/` as an alpha control plane until release packaging and installer behavior are finalized.
|
||||
|
||||
## Do Not Treat This As Published Yet
|
||||
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
# ECC v2.0.0-rc.1 Release URL Ledger
|
||||
|
||||
This ledger separates links that are already public from links that only become
|
||||
valid after the approval-gated release, package, plugin, and announcement
|
||||
steps. Regenerate it from the final release commit before posting any public
|
||||
announcement.
|
||||
|
||||
Captured from source snapshot
|
||||
`81fca2cea6f1399c52c8faa70f9a17e42f0bd447` on 2026-05-18. The ledger file
|
||||
may be committed in a later docs-only refresh after the evidence snapshot it
|
||||
describes.
|
||||
|
||||
## Live Now
|
||||
|
||||
| Surface | URL | Verification |
|
||||
| --- | --- | --- |
|
||||
| Repository | <https://github.com/affaan-m/everything-claude-code> | `git remote get-url origin` |
|
||||
| Evidence source commit | <https://github.com/affaan-m/everything-claude-code/commit/81fca2cea6f1399c52c8faa70f9a17e42f0bd447> | `git rev-parse HEAD` at evidence capture |
|
||||
| Release pack folder | <https://github.com/affaan-m/everything-claude-code/tree/main/docs/releases/2.0.0-rc.1> | Release pack evidence captured from `81fca2ce` |
|
||||
| Release notes draft | <https://github.com/affaan-m/everything-claude-code/blob/main/docs/releases/2.0.0-rc.1/release-notes.md> | In-tree release copy |
|
||||
| Hermes setup guide | <https://github.com/affaan-m/everything-claude-code/blob/main/docs/HERMES-SETUP.md> | In-tree sanitized Hermes guide |
|
||||
| May 18 evidence snapshot | <https://github.com/affaan-m/everything-claude-code/blob/main/docs/releases/2.0.0-rc.1/publication-evidence-2026-05-18.md> | Current strongest readiness evidence |
|
||||
| May 18 operator dashboard | <https://github.com/affaan-m/everything-claude-code/blob/main/docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-18.md> | Prompt-to-artifact dashboard |
|
||||
| Pushed-head CI | <https://github.com/affaan-m/everything-claude-code/actions/runs/26011460500> | CI passed 37/37 jobs for `81fca2ce`, including the supply-chain IOC scan job |
|
||||
| Latest Supply-Chain Watch | <https://github.com/affaan-m/everything-claude-code/actions/runs/26010432490> | Supply-Chain Watch passed for `25ac57ac`; rerun from the final release commit before publication |
|
||||
| npm package page | <https://www.npmjs.com/package/ecc-universal> | `npm view ecc-universal name version dist-tags --json` returned `latest: 1.10.0`; rc.1 is not published yet |
|
||||
| Codex marketplace CLI docs | <https://developers.openai.com/codex/cli/reference#codex-plugin-marketplace> | Official docs list `codex plugin marketplace add` for GitHub shorthand, Git URLs, SSH URLs, and local marketplace roots |
|
||||
| Codex official Plugin Directory status | <https://developers.openai.com/codex/plugins/build#publish-official-public-plugins> | Official docs say public Plugin Directory publishing and self-serve management are coming soon |
|
||||
|
||||
## Approval-Gated URLs
|
||||
|
||||
| Surface | Intended URL or command | Gate before use |
|
||||
| --- | --- | --- |
|
||||
| GitHub prerelease | <https://github.com/affaan-m/everything-claude-code/releases/tag/v2.0.0-rc.1> | `gh release view v2.0.0-rc.1 --repo affaan-m/everything-claude-code --json tagName,url,isPrerelease` must return the prerelease |
|
||||
| npm rc package | <https://www.npmjs.com/package/ecc-universal/v/2.0.0-rc.1> | `npm publish --tag next` approval and post-publish `npm view ecc-universal dist-tags --json` |
|
||||
| Claude plugin tag | `claude plugin tag .claude-plugin --dry-run`, then real tag only after approval | Clean release commit and plugin tag/push approval |
|
||||
| Codex repo marketplace install | `codex plugin marketplace add affaan-m/everything-claude-code --ref v2.0.0-rc.1` | GitHub tag must exist; official Plugin Directory submission remains separate |
|
||||
| ECC Tools native-payments announcement | ECC Tools Marketplace/App URL plus billing readiness readback | Marketplace-managed test account must return `announcementGate.ready === true` |
|
||||
| Public announcements | X, LinkedIn, GitHub release, and longform URLs | GitHub release, npm, plugin, and billing URLs must resolve first |
|
||||
|
||||
## Pre-Post Check
|
||||
|
||||
Run these immediately before publication:
|
||||
|
||||
```bash
|
||||
git status --short --branch
|
||||
gh release view v2.0.0-rc.1 --repo affaan-m/everything-claude-code --json tagName,url,isPrerelease
|
||||
npm view ecc-universal name version dist-tags --json
|
||||
codex plugin marketplace add --help
|
||||
rg -n "TODO|TBD|PLACEHOLDER" docs/releases/2.0.0-rc.1
|
||||
npm run preview-pack:smoke
|
||||
```
|
||||
|
||||
Do not post the social or notification copy until the approval-gated URLs above
|
||||
resolve from a clean release commit.
|
||||
@@ -78,6 +78,3 @@ Hermes x ECC setup:
|
||||
|
||||
12/ Release notes:
|
||||
<https://github.com/affaan-m/everything-claude-code/blob/main/docs/releases/2.0.0-rc.1/release-notes.md>
|
||||
|
||||
URL ledger:
|
||||
<https://github.com/affaan-m/everything-claude-code/blob/main/docs/releases/2.0.0-rc.1/release-url-ledger-2026-05-18.md>
|
||||
|
||||
@@ -108,24 +108,6 @@ porting.
|
||||
| #1682/#1701 | Strategic compact hook-path fixes were merged directly or superseded by current docs fixes. |
|
||||
| JARVIS #4/#5/#6 | Stale failing dependency-only PRs; future dependency state should be regenerated by Dependabot. |
|
||||
|
||||
## 2026-05-18 Owner-Wide Queue Cleanup
|
||||
|
||||
The ECC release repos were already clean, but an owner-wide `gh search` sweep
|
||||
found stale queues in older public/private projects. The cleanup closed 24
|
||||
stale dependency-bot PRs and 72 stale legacy payments/0EM roadmap issues,
|
||||
then closed the final 9 stale/generated/conflicting/test PRs and 5
|
||||
legacy/outreach/placeholder issues. The `affaan-m` owner namespace is now at 0
|
||||
open PRs and 0 open issues by live `gh search`. The detailed before/after
|
||||
evidence and final queue disposition are recorded in
|
||||
`docs/releases/2.0.0-rc.1/owner-queue-cleanup-2026-05-18.md`.
|
||||
|
||||
| Scope | Disposition |
|
||||
| --- | --- |
|
||||
| Dependabot PRs in `stoictradingAI`, `Behavioral_RL`, `dprc-autotrader-v2`, `x-algorithm-score`, `polycule-secure`, and `pragmAItism_defAInce` | Skipped as stale generated dependency bumps; regenerate from current base if still needed. |
|
||||
| Legacy issues in `payments0-api`, `payments0-sdk`, `agent-payments-gateway`, `0EM_Frontend`, `0em-payments-dashboard`, and `yield-optimizer` | Superseded by ECC Tools native-payments, hosted analysis, billing-readback, and Linear/project roadmap lanes. |
|
||||
| Archived repos touched for PR closure | `stoictradingAI`, `dprc-autotrader-v2`, `polycule-secure`, and `pragmAItism_defAInce` were restored to archived state after stale PR closure. |
|
||||
| Final PR/issue sweep | Closed the remaining generated ECC bundles, stale Cloudflare rename PRs, stale README-card PR, test/noise PR, public outreach issues, and empty placeholder issue. Preserved `dexploy#25` findings in Linear `ITO-62` before closure. |
|
||||
|
||||
## Skipped
|
||||
|
||||
| Source PR | Reason |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Everything Claude Code (ECC) — 智能体指令
|
||||
|
||||
这是一个**生产就绪的 AI 编码插件**,提供 60 个专业代理、232 项技能、75 条命令以及自动化钩子工作流,用于软件开发。
|
||||
这是一个**生产就绪的 AI 编码插件**,提供 60 个专业代理、230 项技能、75 条命令以及自动化钩子工作流,用于软件开发。
|
||||
|
||||
**版本:** 2.0.0-rc.1
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
|
||||
```
|
||||
agents/ — 60 个专业子代理
|
||||
skills/ — 232 个工作流技能和领域知识
|
||||
skills/ — 230 个工作流技能和领域知识
|
||||
commands/ — 75 个斜杠命令
|
||||
hooks/ — 基于触发的自动化
|
||||
rules/ — 始终遵循的指导方针(通用 + 每种语言)
|
||||
|
||||
@@ -224,7 +224,7 @@ Copy-Item -Recurse rules/typescript "$HOME/.claude/rules/"
|
||||
/plugin list ecc@ecc
|
||||
```
|
||||
|
||||
**搞定!** 你现在可以使用 60 个智能体、232 项技能和 75 个命令了。
|
||||
**搞定!** 你现在可以使用 60 个智能体、230 项技能和 75 个命令了。
|
||||
|
||||
***
|
||||
|
||||
@@ -1138,7 +1138,7 @@ opencode
|
||||
|---------|-------------|----------|--------|
|
||||
| 智能体 | PASS: 60 个 | PASS: 12 个 | **Claude Code 领先** |
|
||||
| 命令 | PASS: 75 个 | PASS: 35 个 | **Claude Code 领先** |
|
||||
| 技能 | PASS: 232 项 | PASS: 37 项 | **Claude Code 领先** |
|
||||
| 技能 | PASS: 230 项 | PASS: 37 项 | **Claude Code 领先** |
|
||||
| 钩子 | PASS: 8 种事件类型 | PASS: 11 种事件 | **OpenCode 更多!** |
|
||||
| 规则 | PASS: 29 条 | PASS: 13 条指令 | **Claude Code 领先** |
|
||||
| MCP 服务器 | PASS: 14 个 | PASS: 完整 | **完全对等** |
|
||||
@@ -1246,7 +1246,7 @@ ECC 是**第一个最大化利用每个主要 AI 编码工具的插件**。以
|
||||
|---------|------------|------------|-----------|----------|
|
||||
| **智能体** | 60 | 共享 (AGENTS.md) | 共享 (AGENTS.md) | 12 |
|
||||
| **命令** | 75 | 共享 | 基于指令 | 35 |
|
||||
| **技能** | 232 | 共享 | 10 (原生格式) | 37 |
|
||||
| **技能** | 230 | 共享 | 10 (原生格式) | 37 |
|
||||
| **钩子事件** | 8 种类型 | 15 种类型 | 暂无 | 11 种类型 |
|
||||
| **钩子脚本** | 20+ 个脚本 | 16 个脚本 (DRY 适配器) | N/A | 插件钩子 |
|
||||
| **规则** | 34 (通用 + 语言) | 34 (YAML 前页) | 基于指令 | 13 条指令 |
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ const globals = require('globals');
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
ignores: ['.opencode/dist/**', '.cursor/**', 'node_modules/**', '.venv/**', 'venv/**', 'coverage/**']
|
||||
ignores: ['.opencode/dist/**', '.cursor/**', 'node_modules/**']
|
||||
},
|
||||
js.configs.recommended,
|
||||
{
|
||||
|
||||
@@ -525,70 +525,6 @@
|
||||
"modules": [
|
||||
"machine-learning"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "locale:ja",
|
||||
"family": "locale",
|
||||
"description": "Japanese (ja-JP) translated reference docs installed to ~/.claude/docs/ja-JP/.",
|
||||
"modules": [
|
||||
"docs-ja-jp"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "locale:zh-cn",
|
||||
"family": "locale",
|
||||
"description": "Simplified Chinese (zh-CN) translated reference docs installed to ~/.claude/docs/zh-CN/.",
|
||||
"modules": [
|
||||
"docs-zh-cn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "locale:ko-kr",
|
||||
"family": "locale",
|
||||
"description": "Korean (ko-KR) translated reference docs installed to ~/.claude/docs/ko-KR/.",
|
||||
"modules": [
|
||||
"docs-ko-kr"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "locale:pt-br",
|
||||
"family": "locale",
|
||||
"description": "Brazilian Portuguese (pt-BR) translated reference docs installed to ~/.claude/docs/pt-BR/.",
|
||||
"modules": [
|
||||
"docs-pt-br"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "locale:ru",
|
||||
"family": "locale",
|
||||
"description": "Russian (ru) translated reference docs installed to ~/.claude/docs/ru/.",
|
||||
"modules": [
|
||||
"docs-ru"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "locale:tr",
|
||||
"family": "locale",
|
||||
"description": "Turkish (tr) translated reference docs installed to ~/.claude/docs/tr/.",
|
||||
"modules": [
|
||||
"docs-tr"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "locale:vi-vn",
|
||||
"family": "locale",
|
||||
"description": "Vietnamese (vi-VN) translated reference docs installed to ~/.claude/docs/vi-VN/.",
|
||||
"modules": [
|
||||
"docs-vi-vn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "locale:zh-tw",
|
||||
"family": "locale",
|
||||
"description": "Traditional Chinese (zh-TW) translated reference docs installed to ~/.claude/docs/zh-TW/.",
|
||||
"modules": [
|
||||
"docs-zh-tw"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -449,7 +449,6 @@
|
||||
"kind": "skills",
|
||||
"description": "Media generation, technical explainers, and AI-assisted editing skills.",
|
||||
"paths": [
|
||||
"skills/blender-motion-state-inspection",
|
||||
"skills/fal-ai-media",
|
||||
"skills/manim-video",
|
||||
"skills/remotion-video-creation",
|
||||
@@ -694,126 +693,6 @@
|
||||
"defaultInstall": false,
|
||||
"cost": "medium",
|
||||
"stability": "stable"
|
||||
},
|
||||
{
|
||||
"id": "docs-ja-jp",
|
||||
"kind": "docs",
|
||||
"description": "Japanese (ja-JP) translated reference docs for agents, commands, skills, and rules.",
|
||||
"paths": [
|
||||
"docs/ja-JP"
|
||||
],
|
||||
"targets": [
|
||||
"claude"
|
||||
],
|
||||
"dependencies": [],
|
||||
"defaultInstall": false,
|
||||
"cost": "heavy",
|
||||
"stability": "stable"
|
||||
},
|
||||
{
|
||||
"id": "docs-zh-cn",
|
||||
"kind": "docs",
|
||||
"description": "Simplified Chinese (zh-CN) translated reference docs for agents, commands, skills, and rules.",
|
||||
"paths": [
|
||||
"docs/zh-CN"
|
||||
],
|
||||
"targets": [
|
||||
"claude"
|
||||
],
|
||||
"dependencies": [],
|
||||
"defaultInstall": false,
|
||||
"cost": "heavy",
|
||||
"stability": "stable"
|
||||
},
|
||||
{
|
||||
"id": "docs-ko-kr",
|
||||
"kind": "docs",
|
||||
"description": "Korean (ko-KR) translated reference docs for agents, commands, skills, and rules.",
|
||||
"paths": [
|
||||
"docs/ko-KR"
|
||||
],
|
||||
"targets": [
|
||||
"claude"
|
||||
],
|
||||
"dependencies": [],
|
||||
"defaultInstall": false,
|
||||
"cost": "heavy",
|
||||
"stability": "stable"
|
||||
},
|
||||
{
|
||||
"id": "docs-pt-br",
|
||||
"kind": "docs",
|
||||
"description": "Brazilian Portuguese (pt-BR) translated reference docs for agents, commands, skills, and rules.",
|
||||
"paths": [
|
||||
"docs/pt-BR"
|
||||
],
|
||||
"targets": [
|
||||
"claude"
|
||||
],
|
||||
"dependencies": [],
|
||||
"defaultInstall": false,
|
||||
"cost": "heavy",
|
||||
"stability": "stable"
|
||||
},
|
||||
{
|
||||
"id": "docs-ru",
|
||||
"kind": "docs",
|
||||
"description": "Russian (ru) translated reference docs for agents, commands, skills, and rules.",
|
||||
"paths": [
|
||||
"docs/ru"
|
||||
],
|
||||
"targets": [
|
||||
"claude"
|
||||
],
|
||||
"dependencies": [],
|
||||
"defaultInstall": false,
|
||||
"cost": "heavy",
|
||||
"stability": "stable"
|
||||
},
|
||||
{
|
||||
"id": "docs-tr",
|
||||
"kind": "docs",
|
||||
"description": "Turkish (tr) translated reference docs for agents, commands, skills, and rules.",
|
||||
"paths": [
|
||||
"docs/tr"
|
||||
],
|
||||
"targets": [
|
||||
"claude"
|
||||
],
|
||||
"dependencies": [],
|
||||
"defaultInstall": false,
|
||||
"cost": "heavy",
|
||||
"stability": "stable"
|
||||
},
|
||||
{
|
||||
"id": "docs-vi-vn",
|
||||
"kind": "docs",
|
||||
"description": "Vietnamese (vi-VN) translated reference docs for agents, commands, skills, and rules.",
|
||||
"paths": [
|
||||
"docs/vi-VN"
|
||||
],
|
||||
"targets": [
|
||||
"claude"
|
||||
],
|
||||
"dependencies": [],
|
||||
"defaultInstall": false,
|
||||
"cost": "heavy",
|
||||
"stability": "stable"
|
||||
},
|
||||
{
|
||||
"id": "docs-zh-tw",
|
||||
"kind": "docs",
|
||||
"description": "Traditional Chinese (zh-TW) translated reference docs for agents, commands, skills, and rules.",
|
||||
"paths": [
|
||||
"docs/zh-TW"
|
||||
],
|
||||
"targets": [
|
||||
"claude"
|
||||
],
|
||||
"dependencies": [],
|
||||
"defaultInstall": false,
|
||||
"cost": "heavy",
|
||||
"stability": "stable"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -56,14 +56,6 @@
|
||||
"agent.yaml",
|
||||
"agents/",
|
||||
"commands/",
|
||||
"docs/ja-JP/",
|
||||
"docs/ko-KR/",
|
||||
"docs/pt-BR/",
|
||||
"docs/ru/",
|
||||
"docs/tr/",
|
||||
"docs/vi-VN/",
|
||||
"docs/zh-CN/",
|
||||
"docs/zh-TW/",
|
||||
"hooks/",
|
||||
"install.ps1",
|
||||
"install.sh",
|
||||
@@ -122,7 +114,6 @@
|
||||
"skills/automation-audit-ops/",
|
||||
"skills/autonomous-loops/",
|
||||
"skills/backend-patterns/",
|
||||
"skills/blender-motion-state-inspection/",
|
||||
"skills/blueprint/",
|
||||
"skills/brand-voice/",
|
||||
"skills/carrier-relationship-management/",
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"pattern": "^(baseline|lang|framework|capability|agent|skill|locale):[a-z0-9-]+$"
|
||||
"pattern": "^(baseline|lang|framework|capability|agent|skill):[a-z0-9-]+$"
|
||||
},
|
||||
"family": {
|
||||
"type": "string",
|
||||
@@ -36,8 +36,7 @@
|
||||
"framework",
|
||||
"capability",
|
||||
"agent",
|
||||
"skill",
|
||||
"locale"
|
||||
"skill"
|
||||
]
|
||||
},
|
||||
"description": {
|
||||
|
||||
@@ -26,8 +26,7 @@
|
||||
"hooks",
|
||||
"platform",
|
||||
"orchestration",
|
||||
"skills",
|
||||
"docs"
|
||||
"skills"
|
||||
]
|
||||
},
|
||||
"description": {
|
||||
|
||||
@@ -580,51 +580,12 @@ function addFinding(findings, severity, filePath, line, indicator, message) {
|
||||
findings.push({ severity, filePath, line, indicator, message });
|
||||
}
|
||||
|
||||
function isClaudeSettingsFile(filePath) {
|
||||
const normalized = normalizedPath(filePath);
|
||||
return /\/\.claude\/settings(?:\.local)?\.json$/.test(normalized);
|
||||
}
|
||||
|
||||
function claudePermissionDenyRanges(filePath, text) {
|
||||
if (!isClaudeSettingsFile(filePath)) return [];
|
||||
|
||||
let parsed;
|
||||
try {
|
||||
parsed = JSON.parse(text);
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
|
||||
const denyEntries = parsed?.permissions?.deny;
|
||||
if (!Array.isArray(denyEntries)) return [];
|
||||
|
||||
const ranges = [];
|
||||
for (const entry of denyEntries) {
|
||||
if (typeof entry !== 'string' || entry.length === 0) continue;
|
||||
|
||||
for (const needle of [...new Set([JSON.stringify(entry), entry])]) {
|
||||
let index = text.indexOf(needle);
|
||||
while (index !== -1) {
|
||||
ranges.push([index, index + needle.length]);
|
||||
index = text.indexOf(needle, index + needle.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ranges;
|
||||
}
|
||||
|
||||
function indexInRanges(index, ranges) {
|
||||
return ranges.some(([start, end]) => index >= start && index < end);
|
||||
}
|
||||
|
||||
function scanFile(filePath, rootDir, findings) {
|
||||
const base = path.basename(filePath);
|
||||
const relativePath = path.relative(rootDir, filePath) || filePath;
|
||||
const text = readText(filePath);
|
||||
const lowerText = normalizeForMatch(text);
|
||||
const hashFinding = MALICIOUS_FILE_HASHES[sha256File(filePath)];
|
||||
const defensiveClaudeDenyRanges = claudePermissionDenyRanges(filePath, text);
|
||||
|
||||
if (hashFinding) {
|
||||
addFinding(
|
||||
@@ -660,22 +621,16 @@ function scanFile(filePath, rootDir, findings) {
|
||||
}
|
||||
|
||||
for (const indicator of CRITICAL_TEXT_INDICATORS) {
|
||||
const normalizedIndicator = normalizeForMatch(indicator);
|
||||
let index = lowerText.indexOf(normalizedIndicator);
|
||||
while (index !== -1) {
|
||||
if (!indexInRanges(index, defensiveClaudeDenyRanges)) {
|
||||
addFinding(
|
||||
findings,
|
||||
'critical',
|
||||
relativePath,
|
||||
lineForIndex(text, index),
|
||||
indicator,
|
||||
'Known active supply-chain IOC is present',
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
index = lowerText.indexOf(normalizedIndicator, index + normalizedIndicator.length);
|
||||
const index = lowerText.indexOf(normalizeForMatch(indicator));
|
||||
if (index !== -1) {
|
||||
addFinding(
|
||||
findings,
|
||||
'critical',
|
||||
relativePath,
|
||||
lineForIndex(text, index),
|
||||
indicator,
|
||||
'Known active supply-chain IOC is present',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ const COMPONENT_FAMILY_PREFIXES = {
|
||||
language: 'lang:',
|
||||
framework: 'framework:',
|
||||
capability: 'capability:',
|
||||
locale: 'locale:',
|
||||
};
|
||||
|
||||
function readJson(filePath, label) {
|
||||
@@ -164,12 +163,9 @@ function validateInstallManifests() {
|
||||
|
||||
if (profiles.full) {
|
||||
const fullModules = new Set(profiles.full.modules);
|
||||
for (const module of modules) {
|
||||
if (module.kind === 'docs' && module.defaultInstall === false) {
|
||||
continue;
|
||||
}
|
||||
if (!fullModules.has(module.id)) {
|
||||
console.error(`ERROR: full profile is missing module ${module.id}`);
|
||||
for (const moduleId of moduleIds) {
|
||||
if (!fullModules.has(moduleId)) {
|
||||
console.error(`ERROR: full profile is missing module ${moduleId}`);
|
||||
hasErrors = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,31 +21,14 @@ const RULES = [
|
||||
eventPattern: /\bpull_request_target\s*:/m,
|
||||
description: 'pull_request_target must not checkout an untrusted pull_request head ref/repository',
|
||||
expressionPattern: /\$\{\{\s*github\.event\.pull_request\.head\.(?:ref|sha|repo\.full_name)\s*\}\}/g,
|
||||
// Even without the standard `github.event.pull_request.head.*` expression,
|
||||
// a checkout under `pull_request_target` that fetches a `refs/pull/<N>/{head,merge}`
|
||||
// ref pulls attacker-controlled code into a workflow with write-scoped
|
||||
// tokens. GitHub's security guidance treats both forms equivalently;
|
||||
// we match the ref value directly so any interpolation that resolves
|
||||
// to such a ref (`refs/pull/${{ github.event.pull_request.number }}/merge`,
|
||||
// a hardcoded `refs/pull/123/head`, a `${{ env.X }}` that the maintainer
|
||||
// assumes is safe, etc.) trips the same rule.
|
||||
refPattern: /^\s*ref:\s*['"]?[^'"\n]*refs\/(?:remotes\/)?pull\/[^'"\n\s]+/m,
|
||||
},
|
||||
];
|
||||
|
||||
const WRITE_PERMISSION_PATTERN = /^\s*(?:contents|issues|pull-requests|actions|checks|deployments|discussions|id-token|packages|pages|repository-projects|security-events|statuses):\s*write\b/m;
|
||||
// `permissions: write-all` is GitHub Actions' shorthand for granting every
|
||||
// scope write access. The named-scope pattern above misses it because there
|
||||
// is no scope name on the left of the colon — just the literal `write-all`
|
||||
// value at the permissions key. Treat both as equivalent for the purposes
|
||||
// of the persist-credentials gate below. The optional single/double quotes
|
||||
// match valid YAML `permissions: "write-all"` / `'write-all'` forms.
|
||||
const WRITE_ALL_PATTERN = /^\s*permissions:\s*["']?write-all["']?\s*$/m;
|
||||
const NPM_AUDIT_PATTERN = /\bnpm\s+audit\b(?!\s+signatures\b)/;
|
||||
const NPM_AUDIT_SIGNATURES_PATTERN = /\bnpm\s+audit\s+signatures\b/;
|
||||
const ACTIONS_CACHE_PATTERN = /uses:\s*['"]?actions\/cache@/m;
|
||||
const ID_TOKEN_WRITE_PATTERN = /^\s*id-token:\s*write\b/m;
|
||||
const TOP_LEVEL_JOBS_PATTERN = /^jobs:\s*$/m;
|
||||
const UNSAFE_INSTALL_PATTERNS = [
|
||||
{
|
||||
pattern: /\bnpm\s+ci\b(?![^\n]*--ignore-scripts)/g,
|
||||
@@ -122,8 +105,6 @@ function extractCheckoutSteps(source) {
|
||||
function findViolations(filePath, source) {
|
||||
const violations = [];
|
||||
const checkoutSteps = extractCheckoutSteps(source);
|
||||
const jobsIndex = source.search(TOP_LEVEL_JOBS_PATTERN);
|
||||
const workflowHeader = jobsIndex >= 0 ? source.slice(0, jobsIndex) : source;
|
||||
|
||||
for (const rule of RULES) {
|
||||
if (!rule.eventPattern.test(source)) {
|
||||
@@ -131,13 +112,6 @@ function findViolations(filePath, source) {
|
||||
}
|
||||
|
||||
for (const step of checkoutSteps) {
|
||||
// Track whether the expression-based rule already produced a
|
||||
// violation for this step. If it did, skip the refPattern fallback
|
||||
// — a `refs/pull/${{ github.event.pull_request.head.sha }}/merge`
|
||||
// value matches both patterns under the same rule, and the second
|
||||
// push would print a duplicate ERROR line that says exactly the
|
||||
// same thing with a different `expression:` echo.
|
||||
let stepFlagged = false;
|
||||
for (const match of step.text.matchAll(rule.expressionPattern)) {
|
||||
violations.push({
|
||||
filePath,
|
||||
@@ -146,24 +120,11 @@ function findViolations(filePath, source) {
|
||||
expression: match[0],
|
||||
line: step.startLine + getLineNumber(step.text, match.index) - 1,
|
||||
});
|
||||
stepFlagged = true;
|
||||
}
|
||||
if (rule.refPattern && !stepFlagged) {
|
||||
const refMatch = step.text.match(rule.refPattern);
|
||||
if (refMatch) {
|
||||
violations.push({
|
||||
filePath,
|
||||
event: rule.event,
|
||||
description: rule.description,
|
||||
expression: refMatch[0].trim(),
|
||||
line: step.startLine + getLineNumber(step.text, refMatch.index) - 1,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (WRITE_PERMISSION_PATTERN.test(source) || WRITE_ALL_PATTERN.test(source)) {
|
||||
if (WRITE_PERMISSION_PATTERN.test(source)) {
|
||||
for (const step of checkoutSteps) {
|
||||
if (!/persist-credentials:\s*['"]?false['"]?\b/m.test(step.text)) {
|
||||
violations.push({
|
||||
@@ -178,16 +139,6 @@ function findViolations(filePath, source) {
|
||||
|
||||
}
|
||||
|
||||
if (ID_TOKEN_WRITE_PATTERN.test(workflowHeader)) {
|
||||
violations.push({
|
||||
filePath,
|
||||
event: 'workflow-scoped id-token',
|
||||
description: 'id-token: write must be scoped to a publish-only job, not the entire workflow',
|
||||
expression: 'top-level id-token: write',
|
||||
line: getLineNumber(source, source.search(ID_TOKEN_WRITE_PATTERN)),
|
||||
});
|
||||
}
|
||||
|
||||
for (const installRule of UNSAFE_INSTALL_PATTERNS) {
|
||||
for (const match of source.matchAll(installRule.pattern)) {
|
||||
violations.push({
|
||||
|
||||
@@ -9,11 +9,10 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const crypto = require('crypto');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const { sanitizeSessionId, readBridge, renameWithRetry } = require('../lib/session-bridge');
|
||||
const { sanitizeSessionId, readBridge } = require('../lib/session-bridge');
|
||||
|
||||
const CONTEXT_WARNING_PCT = 35;
|
||||
const CONTEXT_CRITICAL_PCT = 25;
|
||||
@@ -62,30 +61,15 @@ function readWarnState(sessionId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Write debounce state atomically (unique-suffix tmp then rename).
|
||||
*
|
||||
* The tmp path includes `process.pid` plus a random nonce so concurrent
|
||||
* PostToolUse subprocesses writing to the same session's warn-state
|
||||
* file do not clobber each other's tmp mid-write. Without the unique
|
||||
* suffix, two writers race over a shared `${target}.tmp` and produce
|
||||
* either a corrupted payload or an ENOENT throw on the second rename.
|
||||
*
|
||||
* Same pattern as `writeBridgeAtomic` in `scripts/lib/session-bridge.js`
|
||||
* and `writeCostWarningIfChanged` in `scripts/hooks/ecc-metrics-bridge.js`.
|
||||
*
|
||||
* Write debounce state.
|
||||
* @param {string} sessionId
|
||||
* @param {object} state
|
||||
*/
|
||||
function writeWarnState(sessionId, state) {
|
||||
const target = getWarnPath(sessionId);
|
||||
const tmp = `${target}.${process.pid}.${crypto.randomBytes(4).toString('hex')}.tmp`;
|
||||
const tmp = `${target}.tmp`;
|
||||
fs.writeFileSync(tmp, JSON.stringify(state), 'utf8');
|
||||
try {
|
||||
renameWithRetry(tmp, target);
|
||||
} catch (err) {
|
||||
try { fs.unlinkSync(tmp); } catch { /* ignore */ }
|
||||
throw err;
|
||||
}
|
||||
fs.renameSync(tmp, target);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,10 +26,8 @@ const DEFAULT_BACKOFF_MS = 30 * 1000;
|
||||
const MAX_BACKOFF_MS = 10 * 60 * 1000;
|
||||
// The preflight HTTP probe only checks reachability; it does not have access to
|
||||
// Claude Code's stored OAuth bearer token. Treat auth-gated responses as
|
||||
// reachable so the real MCP client can attempt the authenticated call. A
|
||||
// Streamable HTTP MCP server can also return 406 to a bare GET that omits
|
||||
// Accept: text/event-stream; that still proves the endpoint is alive.
|
||||
const HEALTHY_HTTP_CODES = new Set([200, 201, 202, 204, 301, 302, 303, 304, 307, 308, 400, 401, 403, 405, 406]);
|
||||
// reachable so the real MCP client can attempt the authenticated call.
|
||||
const HEALTHY_HTTP_CODES = new Set([200, 201, 202, 204, 301, 302, 303, 304, 307, 308, 400, 401, 403, 405]);
|
||||
const RECONNECT_STATUS_CODES = new Set([401, 403, 429, 503]);
|
||||
const FAILURE_PATTERNS = [
|
||||
{ code: 401, pattern: /\b401\b|unauthori[sz]ed|auth(?:entication)?\s+(?:failed|expired|invalid)/i },
|
||||
|
||||
@@ -10,7 +10,6 @@ const os = require('os');
|
||||
const {
|
||||
SUPPORTED_INSTALL_TARGETS,
|
||||
listLegacyCompatibilityLanguages,
|
||||
listSupportedLocales,
|
||||
} = require('./lib/install-manifests');
|
||||
const {
|
||||
LEGACY_INSTALL_TARGETS,
|
||||
@@ -20,14 +19,12 @@ const {
|
||||
|
||||
function getHelpText() {
|
||||
const languages = listLegacyCompatibilityLanguages();
|
||||
const locales = listSupportedLocales();
|
||||
|
||||
return `
|
||||
Usage: install.sh [--target <${LEGACY_INSTALL_TARGETS.join('|')}>] [--dry-run] [--json] <language> [<language> ...]
|
||||
install.sh [--target <${SUPPORTED_INSTALL_TARGETS.join('|')}>] [--dry-run] [--json] --profile <name> [--with <component>]... [--without <component>]...
|
||||
install.sh [--target <${SUPPORTED_INSTALL_TARGETS.join('|')}>] [--dry-run] [--json] --modules <id,id,...> [--with <component>]... [--without <component>]...
|
||||
install.sh [--target <${SUPPORTED_INSTALL_TARGETS.join('|')}>] [--dry-run] [--json] --skills <skill-id[,skill-id...]>
|
||||
install.sh [--target claude] [--dry-run] [--json] --locale <locale-code>
|
||||
install.sh [--dry-run] [--json] --config <path>
|
||||
|
||||
Targets:
|
||||
@@ -49,8 +46,6 @@ Options:
|
||||
--skills <ids> Install one or more skill directories by ID, e.g. continuous-learning-v2
|
||||
--without <component>
|
||||
Exclude a user-facing install component
|
||||
--locale <code> Install translated docs to ~/.claude/docs/<locale>/
|
||||
(claude target only; can be combined with --profile or --with)
|
||||
--config <path> Load install intent from ecc-install.json
|
||||
--dry-run Show the install plan without copying files
|
||||
--json Emit machine-readable plan/result JSON
|
||||
@@ -58,9 +53,6 @@ Options:
|
||||
|
||||
Available languages:
|
||||
${languages.map(language => ` - ${language}`).join('\n')}
|
||||
|
||||
Available locales (--locale):
|
||||
${locales.map(locale => ` - ${locale}`).join('\n')}
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ const { spawnSync } = require('child_process');
|
||||
|
||||
const DEFAULT_DISCUSSION_FIRST = 100;
|
||||
const MAINTAINER_ASSOCIATIONS = new Set(['OWNER', 'MEMBER', 'COLLABORATOR']);
|
||||
const DISCUSSION_ENABLED_QUERY = 'query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } }';
|
||||
const DISCUSSION_QUERY = 'query($owner: String!, $name: String!, $first: Int!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled discussions(first: $first, orderBy: {field: UPDATED_AT, direction: DESC}) { totalCount nodes { number title url updatedAt authorAssociation category { name isAnswerable } answer { url authorAssociation } comments(first: 20) { nodes { authorAssociation } } } } } }';
|
||||
|
||||
function splitRepo(repo) {
|
||||
@@ -92,22 +91,6 @@ function summarizeDiscussion(discussion) {
|
||||
function fetchDiscussionSummary(repo, options = {}) {
|
||||
const { owner, name } = splitRepo(repo);
|
||||
const first = Number.isFinite(options.first) ? options.first : DEFAULT_DISCUSSION_FIRST;
|
||||
const enabledPayload = runGhJson([
|
||||
'api',
|
||||
'graphql',
|
||||
'-f',
|
||||
`owner=${owner}`,
|
||||
'-f',
|
||||
`name=${name}`,
|
||||
'-f',
|
||||
`query=${DISCUSSION_ENABLED_QUERY}`,
|
||||
], options);
|
||||
const enabledRepository = enabledPayload && enabledPayload.data && enabledPayload.data.repository;
|
||||
|
||||
if (!enabledRepository || !enabledRepository.hasDiscussionsEnabled) {
|
||||
return emptyDiscussionSummary();
|
||||
}
|
||||
|
||||
const payload = runGhJson([
|
||||
'api',
|
||||
'graphql',
|
||||
@@ -147,7 +130,6 @@ function emptyDiscussionSummary() {
|
||||
|
||||
module.exports = {
|
||||
DEFAULT_DISCUSSION_FIRST,
|
||||
DISCUSSION_ENABLED_QUERY,
|
||||
DISCUSSION_QUERY,
|
||||
MAINTAINER_ASSOCIATIONS,
|
||||
discussionNeedsAcceptedAnswer,
|
||||
|
||||
@@ -555,12 +555,6 @@ function createLegacyCompatInstallPlan(options = {}) {
|
||||
const sourceRoot = options.sourceRoot || getSourceRoot();
|
||||
const projectRoot = options.projectRoot || process.cwd();
|
||||
const target = options.target || 'claude';
|
||||
const includeComponentIds = Array.isArray(options.includeComponentIds)
|
||||
? [...options.includeComponentIds]
|
||||
: [];
|
||||
const excludeComponentIds = Array.isArray(options.excludeComponentIds)
|
||||
? [...options.excludeComponentIds]
|
||||
: [];
|
||||
|
||||
validateLegacyTarget(target);
|
||||
|
||||
@@ -577,14 +571,14 @@ function createLegacyCompatInstallPlan(options = {}) {
|
||||
target,
|
||||
profileId: null,
|
||||
moduleIds: selection.moduleIds,
|
||||
includeComponentIds,
|
||||
excludeComponentIds,
|
||||
includeComponentIds: [],
|
||||
excludeComponentIds: [],
|
||||
legacyLanguages: selection.legacyLanguages,
|
||||
legacyMode: true,
|
||||
requestProfileId: null,
|
||||
requestModuleIds: [],
|
||||
requestIncludeComponentIds: includeComponentIds,
|
||||
requestExcludeComponentIds: excludeComponentIds,
|
||||
requestIncludeComponentIds: [],
|
||||
requestExcludeComponentIds: [],
|
||||
mode: 'legacy-compat',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,28 +12,7 @@ const COMPONENT_FAMILY_PREFIXES = {
|
||||
capability: 'capability:',
|
||||
agent: 'agent:',
|
||||
skill: 'skill:',
|
||||
locale: 'locale:',
|
||||
};
|
||||
const SUPPORTED_LOCALES = Object.freeze(['ja', 'zh-CN', 'ko-KR', 'pt-BR', 'ru', 'tr', 'vi-VN', 'zh-TW']);
|
||||
const LOCALE_ALIAS_TO_COMPONENT_ID = Object.freeze({
|
||||
'ja': 'locale:ja',
|
||||
'ja-JP': 'locale:ja',
|
||||
'zh-CN': 'locale:zh-cn',
|
||||
'zh': 'locale:zh-cn',
|
||||
'ko-KR': 'locale:ko-kr',
|
||||
'ko': 'locale:ko-kr',
|
||||
'pt-BR': 'locale:pt-br',
|
||||
'pt': 'locale:pt-br',
|
||||
'ru': 'locale:ru',
|
||||
'tr': 'locale:tr',
|
||||
'vi-VN': 'locale:vi-vn',
|
||||
'vi': 'locale:vi-vn',
|
||||
'zh-TW': 'locale:zh-tw',
|
||||
});
|
||||
|
||||
function listSupportedLocales() {
|
||||
return [...SUPPORTED_LOCALES];
|
||||
}
|
||||
const LEGACY_COMPAT_BASE_MODULE_IDS_BY_TARGET = Object.freeze({
|
||||
claude: [
|
||||
'rules-core',
|
||||
@@ -628,14 +607,11 @@ function resolveInstallPlan(options = {}) {
|
||||
module.exports = {
|
||||
DEFAULT_REPO_ROOT,
|
||||
SUPPORTED_INSTALL_TARGETS,
|
||||
SUPPORTED_LOCALES,
|
||||
LOCALE_ALIAS_TO_COMPONENT_ID,
|
||||
getManifestPaths,
|
||||
loadInstallManifests,
|
||||
getInstallComponent,
|
||||
listInstallComponents,
|
||||
listLegacyCompatibilityLanguages,
|
||||
listSupportedLocales,
|
||||
listInstallModules,
|
||||
listInstallProfiles,
|
||||
resolveInstallPlan,
|
||||
|
||||
@@ -39,10 +39,6 @@ function getClaudeManagedDestinationPath(adapter, sourceRelativePath, input) {
|
||||
);
|
||||
}
|
||||
|
||||
if (normalizedSourcePath === 'docs' || normalizedSourcePath.startsWith('docs/')) {
|
||||
return path.join(targetRoot, normalizedSourcePath);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const { validateInstallModuleIds, LOCALE_ALIAS_TO_COMPONENT_ID, listSupportedLocales } = require('../install-manifests');
|
||||
const { validateInstallModuleIds } = require('../install-manifests');
|
||||
|
||||
const LEGACY_INSTALL_TARGETS = ['claude', 'cursor', 'antigravity'];
|
||||
|
||||
@@ -27,7 +27,6 @@ function parseInstallArgs(argv) {
|
||||
includeComponentIds: [],
|
||||
excludeComponentIds: [],
|
||||
languages: [],
|
||||
locale: null,
|
||||
};
|
||||
|
||||
for (let index = 0; index < args.length; index += 1) {
|
||||
@@ -61,13 +60,6 @@ function parseInstallArgs(argv) {
|
||||
parsed.excludeComponentIds.push(componentId.trim());
|
||||
}
|
||||
index += 1;
|
||||
} else if (arg === '--locale') {
|
||||
const locale = args[index + 1] || '';
|
||||
if (!locale || locale.startsWith('--')) {
|
||||
throw new Error('Missing value for --locale');
|
||||
}
|
||||
parsed.locale = locale;
|
||||
index += 1;
|
||||
} else if (arg === '--dry-run') {
|
||||
parsed.dryRun = true;
|
||||
} else if (arg === '--json') {
|
||||
@@ -89,28 +81,13 @@ function normalizeInstallRequest(options = {}) {
|
||||
? options.config
|
||||
: null;
|
||||
const profileId = options.profileId || config?.profileId || null;
|
||||
const target = options.target || config?.target || 'claude';
|
||||
const moduleIds = validateInstallModuleIds(
|
||||
dedupeStrings([...(config?.moduleIds || []), ...(options.moduleIds || [])])
|
||||
);
|
||||
const locale = options.locale || config?.locale || null;
|
||||
const localeComponentId = locale ? LOCALE_ALIAS_TO_COMPONENT_ID[locale] : null;
|
||||
if (locale && !localeComponentId) {
|
||||
throw new Error(
|
||||
`Unsupported locale: "${locale}". Supported locales: ${listSupportedLocales().join(', ')}`
|
||||
);
|
||||
}
|
||||
if (locale && target !== 'claude') {
|
||||
throw new Error('--locale can only be used with --target claude');
|
||||
}
|
||||
const requestedIncludeComponentIds = dedupeStrings([
|
||||
const includeComponentIds = dedupeStrings([
|
||||
...(config?.includeComponentIds || []),
|
||||
...(options.includeComponentIds || []),
|
||||
]);
|
||||
const includeComponentIds = dedupeStrings([
|
||||
...requestedIncludeComponentIds,
|
||||
...(localeComponentId ? [localeComponentId] : []),
|
||||
]);
|
||||
const excludeComponentIds = dedupeStrings([
|
||||
...(config?.excludeComponentIds || []),
|
||||
...(options.excludeComponentIds || []),
|
||||
@@ -119,14 +96,11 @@ function normalizeInstallRequest(options = {}) {
|
||||
...(Array.isArray(options.legacyLanguages) ? options.legacyLanguages : []),
|
||||
...(Array.isArray(options.languages) ? options.languages : []),
|
||||
]).map(language => language.toLowerCase()));
|
||||
const target = options.target || config?.target || 'claude';
|
||||
const hasManifestBaseSelection = Boolean(profileId) || moduleIds.length > 0 || includeComponentIds.length > 0;
|
||||
const hasNonLocaleManifestSelection = Boolean(profileId)
|
||||
|| moduleIds.length > 0
|
||||
|| requestedIncludeComponentIds.length > 0
|
||||
|| excludeComponentIds.length > 0;
|
||||
const usingManifestMode = hasManifestBaseSelection || excludeComponentIds.length > 0;
|
||||
|
||||
if (hasNonLocaleManifestSelection && legacyLanguages.length > 0) {
|
||||
if (usingManifestMode && legacyLanguages.length > 0) {
|
||||
throw new Error(
|
||||
'Legacy language arguments cannot be combined with --profile, --modules, --with, --without, or manifest config selections'
|
||||
);
|
||||
@@ -137,9 +111,7 @@ function normalizeInstallRequest(options = {}) {
|
||||
}
|
||||
|
||||
return {
|
||||
mode: legacyLanguages.length > 0
|
||||
? 'legacy-compat'
|
||||
: (usingManifestMode ? 'manifest' : 'legacy-compat'),
|
||||
mode: usingManifestMode ? 'manifest' : 'legacy-compat',
|
||||
target,
|
||||
profileId,
|
||||
moduleIds,
|
||||
|
||||
@@ -28,8 +28,6 @@ function createInstallPlanFromRequest(request, options = {}) {
|
||||
return createLegacyCompatInstallPlan({
|
||||
target: request.target,
|
||||
legacyLanguages: request.legacyLanguages,
|
||||
includeComponentIds: request.includeComponentIds,
|
||||
excludeComponentIds: request.excludeComponentIds,
|
||||
projectRoot: options.projectRoot,
|
||||
homeDir: options.homeDir,
|
||||
claudeRulesDir: options.claudeRulesDir,
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
* without scanning large JSONL logs on every invocation.
|
||||
*/
|
||||
|
||||
const crypto = require('crypto');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
@@ -52,80 +51,15 @@ function readBridge(sessionId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Write bridge data atomically (write unique-suffix tmp then rename).
|
||||
*
|
||||
* The tmp path includes `process.pid` plus a random nonce so concurrent
|
||||
* writers (e.g. PostToolUse `ecc-metrics-bridge` and the background
|
||||
* `ecc-statusline`, both writing to the same session bridge) do not
|
||||
* clobber each other's tmp file mid-write. With a fixed `.tmp` suffix
|
||||
* two writers could both call `writeFileSync` against the same path
|
||||
* before either reaches `renameSync`, causing one writer's payload to
|
||||
* silently overwrite the other and the second `renameSync` to throw
|
||||
* ENOENT once the rename consumes the file.
|
||||
*
|
||||
* Same pattern already used by `writeCostWarningIfChanged` in
|
||||
* `scripts/hooks/ecc-metrics-bridge.js` (commit 9b1d8918) for the
|
||||
* cost-warning cache; this commit applies it to the session-bridge
|
||||
* primitive too.
|
||||
*
|
||||
* Write bridge data atomically (write .tmp then rename).
|
||||
* @param {string} sessionId - Already-sanitized session ID
|
||||
* @param {object} data
|
||||
*/
|
||||
function writeBridgeAtomic(sessionId, data) {
|
||||
const target = getBridgePath(sessionId);
|
||||
const tmp = `${target}.${process.pid}.${crypto.randomBytes(4).toString('hex')}.tmp`;
|
||||
const tmp = `${target}.tmp`;
|
||||
fs.writeFileSync(tmp, JSON.stringify(data), 'utf8');
|
||||
try {
|
||||
renameWithRetry(tmp, target);
|
||||
} catch (err) {
|
||||
try { fs.unlinkSync(tmp); } catch { /* ignore */ }
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a file via rename, retrying briefly on transient OS-level errors.
|
||||
*
|
||||
* POSIX `rename(2)` is atomic between source and destination, so concurrent
|
||||
* writers each rename onto the same target without conflict. Windows
|
||||
* `MoveFileExW` is different: it fails with EPERM/EACCES/EBUSY if the
|
||||
* target is currently being renamed by *another* process — a short race
|
||||
* window that fires reliably under our PostToolUse + statusline concurrency.
|
||||
*
|
||||
* To stay portable, retry up to 5 times with exponential backoff (20 ms,
|
||||
* 40, 80, 160, 320) on the Windows-only transient codes. POSIX runs hit
|
||||
* the first try and exit immediately. Other error codes (ENOENT, ENOSPC,
|
||||
* EROFS, …) re-throw without retry — they are not transient.
|
||||
*
|
||||
* Sleep uses `Atomics.wait` on a throwaway SharedArrayBuffer so the
|
||||
* retry path does not busy-spin the CPU. This works on the main thread
|
||||
* in Node ≥ 17 (and on workers in earlier versions).
|
||||
*
|
||||
* @param {string} tmp
|
||||
* @param {string} target
|
||||
*/
|
||||
function renameWithRetry(tmp, target) {
|
||||
const RETRY_CODES = new Set(['EPERM', 'EACCES', 'EBUSY']);
|
||||
const MAX_ATTEMPTS = 5;
|
||||
for (let attempt = 0; ; attempt++) {
|
||||
try {
|
||||
fs.renameSync(tmp, target);
|
||||
return;
|
||||
} catch (err) {
|
||||
if (attempt + 1 >= MAX_ATTEMPTS || !RETRY_CODES.has(err.code)) {
|
||||
throw err;
|
||||
}
|
||||
const delayMs = 20 << attempt;
|
||||
try {
|
||||
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, delayMs);
|
||||
} catch {
|
||||
// Atomics.wait throws on the main thread in some older runtimes;
|
||||
// fall back to a brief busy-wait so the retry path still has a delay.
|
||||
const until = Date.now() + delayMs;
|
||||
while (Date.now() < until) { /* spin */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
fs.renameSync(tmp, target);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,7 +76,6 @@ module.exports = {
|
||||
getBridgePath,
|
||||
readBridge,
|
||||
writeBridgeAtomic,
|
||||
renameWithRetry,
|
||||
resolveSessionId,
|
||||
MAX_SESSION_ID_LENGTH
|
||||
};
|
||||
|
||||
@@ -335,44 +335,13 @@ function agentShieldEnterpriseGap(roadmap) {
|
||||
function agentShieldEnterpriseEvidence(roadmap) {
|
||||
if (roadmap.includes('hosted promotion judge audit traces')
|
||||
|| roadmap.includes('operator-visible promotion output values')) {
|
||||
return 'AgentShield policy promotion `reviewItems` landed in `87aec47`; package-manager hardening drift detection landed in `28d08c7`; workflow action runtime pins were refreshed in `659f569`; npm age-gate guidance was corrected in `ee585cd`; package-manager hardening Action outputs landed in `1124535`; policy-promotion Action outputs and runtime-smoke job-summary evidence landed in `1593925`; fleet review ticket payloads and current Mini Shai-Hulud IOC breadcrumbs landed in `840952a`; ECC-Tools consumes those outputs in `8658951`, surfaces operator-readable status/pack/count/digest telemetry in `16c537f`, and renders hosted promotion judge audit traces in `05d4e82`; all are mirrored in the GA roadmap';
|
||||
return 'AgentShield policy promotion `reviewItems` landed in `87aec47`; package-manager hardening drift detection landed in `28d08c7`; workflow action runtime pins were refreshed in `659f569`; npm age-gate guidance was corrected in `ee585cd`; package-manager hardening Action outputs landed in `1124535`; policy-promotion Action outputs and runtime-smoke job-summary evidence landed in `1593925`; ECC-Tools consumes those outputs in `8658951`, surfaces operator-readable status/pack/count/digest telemetry in `16c537f`, and renders hosted promotion judge audit traces in `05d4e82`; all are mirrored in the GA roadmap';
|
||||
}
|
||||
|
||||
return 'AgentShield enterprise PR evidence is mirrored in the GA roadmap';
|
||||
}
|
||||
|
||||
function eccToolsNextLevelEvidence(roadmap) {
|
||||
if (roadmap.includes('69ca535')
|
||||
|| roadmap.includes('team feedback controls')
|
||||
|| roadmap.includes('e56fc1a')) {
|
||||
return 'billing announcement gate, hosted analysis lanes, AgentShield fleet-summary consumption, hosted finding evidence paths, harness-route policy linking, policy-promotion Action-output telemetry, operator-visible promotion output details, hosted promotion judge audit traces, billing announcement preflight, aggregate production billing KV readback, Wrangler OAuth readback, target-account billing readback, provenance-aware Marketplace billing-state gates, sanitized Marketplace plan/action provenance counts, hosted team-learning feedback controls, and ECC-Tools Dependabot alert remediation are mirrored in the GA roadmap';
|
||||
}
|
||||
|
||||
if (roadmap.includes('d5f60db')
|
||||
|| roadmap.includes('Marketplace-source provenance counts')) {
|
||||
return 'billing announcement gate, hosted analysis lanes, AgentShield fleet-summary consumption, hosted finding evidence paths, harness-route policy linking, policy-promotion Action-output telemetry, operator-visible promotion output details, hosted promotion judge audit traces, billing announcement preflight, aggregate production billing KV readback, Wrangler OAuth readback, target-account billing readback, provenance-aware Marketplace billing-state gates, and sanitized Marketplace plan/action provenance counts are mirrored in the GA roadmap';
|
||||
}
|
||||
|
||||
if (roadmap.includes('target account billing readback')
|
||||
|| roadmap.includes('632e059')) {
|
||||
return 'billing announcement gate, hosted analysis lanes, AgentShield fleet-summary consumption, hosted finding evidence paths, harness-route policy linking, policy-promotion Action-output telemetry, operator-visible promotion output details, hosted promotion judge audit traces, billing announcement preflight, aggregate production billing KV readback, Wrangler OAuth readback, target-account billing readback, and provenance-aware Marketplace billing-state gates are mirrored in the GA roadmap';
|
||||
}
|
||||
|
||||
if (roadmap.includes('Wrangler OAuth readback')
|
||||
|| roadmap.includes('42653f9')) {
|
||||
return 'billing announcement gate, hosted analysis lanes, AgentShield fleet-summary consumption, hosted finding evidence paths, harness-route policy linking, policy-promotion Action-output telemetry, operator-visible promotion output details, hosted promotion judge audit traces, billing announcement preflight, aggregate production billing KV readback, Wrangler OAuth readback, and provenance-aware Marketplace billing-state gates are mirrored in the GA roadmap';
|
||||
}
|
||||
|
||||
if (roadmap.includes('Marketplace webhook provenance')
|
||||
|| roadmap.includes('2859678')) {
|
||||
return 'billing announcement gate, hosted analysis lanes, AgentShield fleet-summary consumption, hosted finding evidence paths, harness-route policy linking, policy-promotion Action-output telemetry, operator-visible promotion output details, hosted promotion judge audit traces, billing announcement preflight, aggregate production billing KV readback, and provenance-aware Marketplace billing-state gates are mirrored in the GA roadmap';
|
||||
}
|
||||
|
||||
if (roadmap.includes('billing:kv-readback')
|
||||
|| roadmap.includes('95d0bec')) {
|
||||
return 'billing announcement gate, hosted analysis lanes, AgentShield fleet-summary consumption, hosted finding evidence paths, harness-route policy linking, policy-promotion Action-output telemetry, operator-visible promotion output details, hosted promotion judge audit traces, billing announcement preflight, and aggregate production billing KV readback are mirrored in the GA roadmap';
|
||||
}
|
||||
|
||||
if (roadmap.includes('production Marketplace readback state')
|
||||
|| roadmap.includes('eb69412')) {
|
||||
return 'billing announcement gate, hosted analysis lanes, AgentShield fleet-summary consumption, hosted finding evidence paths, harness-route policy linking, policy-promotion Action-output telemetry, operator-visible promotion output details, hosted promotion judge audit traces, billing announcement preflight, and production KV readback state are mirrored in the GA roadmap';
|
||||
@@ -387,41 +356,6 @@ function eccToolsNextLevelEvidence(roadmap) {
|
||||
}
|
||||
|
||||
function eccToolsNextLevelGap(roadmap) {
|
||||
if (roadmap.includes('1Password CLI authorization timed out')
|
||||
|| roadmap.includes('Cloudflare API auth returned `Authentication error [code: 10000]`')) {
|
||||
return 'authorize Cloudflare API or 1Password CLI access, configure the target Marketplace Pro account and INTERNAL_API_SECRET, create or replay Marketplace Pro webhook state, then rerun target readback and the live announcement gate';
|
||||
}
|
||||
|
||||
if (roadmap.includes('Wrangler OAuth now works')
|
||||
|| roadmap.includes('6904e4fb-bec7-4787-90e2-759f077a628c')) {
|
||||
return 'create or verify Marketplace-managed Pro target billing-state with webhook provenance, configure the target account and INTERNAL_API_SECRET, then rerun target readback and the live announcement gate';
|
||||
}
|
||||
|
||||
if (roadmap.includes('d5f60db')
|
||||
|| roadmap.includes('Marketplace-source provenance counts')) {
|
||||
return 'create or verify Marketplace-managed Pro target billing-state with webhook provenance, then run `billing:kv-readback -- --wrangler --wrangler-bin ./node_modules/.bin/wrangler --account <github-login> --require-ready`, followed by the live announcement gate';
|
||||
}
|
||||
|
||||
if (roadmap.includes('target account billing readback')
|
||||
|| roadmap.includes('632e059')) {
|
||||
return 'create or verify Marketplace-managed Pro target billing-state with webhook provenance, then run `billing:kv-readback -- --account <github-login> --require-ready` with working Cloudflare API auth or repaired Wrangler OAuth, followed by the live announcement gate';
|
||||
}
|
||||
|
||||
if (roadmap.includes('Wrangler OAuth readback')
|
||||
|| roadmap.includes('42653f9')) {
|
||||
return 'create or verify Marketplace-managed Pro billing-state with webhook provenance, then run `billing:kv-readback -- --require-ready` with working Cloudflare API auth or repaired Wrangler OAuth, followed by the live announcement gate';
|
||||
}
|
||||
|
||||
if (roadmap.includes('Marketplace webhook provenance')
|
||||
|| roadmap.includes('2859678')) {
|
||||
return 'replace the invalid Cloudflare credential, create or verify Marketplace-managed Pro billing-state with webhook provenance, then run `billing:kv-readback -- --require-ready` and the live announcement gate';
|
||||
}
|
||||
|
||||
if (roadmap.includes('billing:kv-readback')
|
||||
|| roadmap.includes('95d0bec')) {
|
||||
return 'create or verify a Marketplace-managed Pro billing-state, then run the official live announcement gate';
|
||||
}
|
||||
|
||||
if (roadmap.includes('production Marketplace readback state')
|
||||
|| roadmap.includes('eb69412')) {
|
||||
return 'complete Marketplace purchase/webhook readback, then run the live announcement gate';
|
||||
@@ -438,7 +372,7 @@ function eccToolsNextLevelGap(roadmap) {
|
||||
function supplyChainLocalProtectionEvidence({ roadmap, scripts }) {
|
||||
if (scripts['security:advisory-sources'] === 'node scripts/ci/supply-chain-advisory-sources.js'
|
||||
&& roadmap.includes('package-manager hardening Action outputs')) {
|
||||
return 'scheduled supply-chain watch emits IOC/advisory-source refresh artifacts; ECC scanner covers gh-token-monitor token-store persistence; AgentShield now detects known AI-tool persistence IOCs, npm lifecycle/token drift, unsupported npm age-key drift, and pnpm/Yarn cooldown drift; current-head watch evidence and ITO-57 May 18 Linear evidence updates are current';
|
||||
return 'scheduled supply-chain watch emits IOC/advisory-source refresh artifacts; ECC scanner covers gh-token-monitor token-store persistence; AgentShield now detects known AI-tool persistence IOCs, npm lifecycle/token drift, unsupported npm age-key drift, and pnpm/Yarn cooldown drift; ITO-57 has May 17 Linear evidence updates';
|
||||
}
|
||||
|
||||
return scripts['security:advisory-sources'] === 'node scripts/ci/supply-chain-advisory-sources.js'
|
||||
@@ -456,12 +390,10 @@ function supplyChainLocalProtectionGap({ roadmap, scripts }) {
|
||||
}
|
||||
|
||||
function hasCurrentLinearProgressSync({ roadmap, progressSync }) {
|
||||
const hasOperatorProgressSurface = roadmap.includes('operator progress snapshot')
|
||||
|| roadmap.includes('operator progress comment');
|
||||
|
||||
return roadmap.includes('Linear live sync is current')
|
||||
&& hasOperatorProgressSurface
|
||||
&& includesAll(progressSync, [
|
||||
return includesAll(roadmap, [
|
||||
'Linear live sync is current',
|
||||
'operator progress snapshot',
|
||||
]) && includesAll(progressSync, [
|
||||
'node scripts/work-items.js sync-github --repo <owner/repo>',
|
||||
'node scripts/status.js --json',
|
||||
'Linear remains the external status surface',
|
||||
@@ -483,7 +415,7 @@ function linearProgressStatus(context) {
|
||||
|
||||
function linearProgressEvidence(context) {
|
||||
if (hasCurrentLinearProgressSync(context)) {
|
||||
return 'Linear live sync and project progress surface are current; progress-sync contract defines the file-backed work-items/status path';
|
||||
return 'Linear live sync and project progress snapshot are current; progress-sync contract defines the file-backed work-items/status path';
|
||||
}
|
||||
|
||||
return 'repo mirror and progress-sync contract are present';
|
||||
@@ -528,17 +460,6 @@ function buildRequirement(id, requirement, artifact, status, evidence, gap) {
|
||||
return { id, requirement, artifact, status, evidence, gap };
|
||||
}
|
||||
|
||||
function extractLabeledCount(text, label) {
|
||||
const pattern = new RegExp(`${label.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}:\\s*(\\d+)`, 'i');
|
||||
const match = text.match(pattern);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const parsed = Number.parseInt(match[1], 10);
|
||||
return Number.isFinite(parsed) ? parsed : null;
|
||||
}
|
||||
|
||||
function isCurrentOrComplete(status) {
|
||||
return status === 'current' || status === 'complete';
|
||||
}
|
||||
@@ -547,9 +468,6 @@ function buildRequirements(rootDir, platformReport) {
|
||||
const roadmap = readText(rootDir, 'docs/ECC-2.0-GA-ROADMAP.md');
|
||||
const publicationReadiness = readText(rootDir, 'docs/releases/2.0.0-rc.1/publication-readiness.md');
|
||||
const namingMatrix = readText(rootDir, 'docs/releases/2.0.0-rc.1/naming-and-publication-matrix.md');
|
||||
const releasePublicationChecklist = readText(rootDir, 'docs/releases/2.0.0-rc.1/release-name-plugin-publication-checklist-2026-05-18.md');
|
||||
const releaseUrlLedger = readText(rootDir, 'docs/releases/2.0.0-rc.1/release-url-ledger-2026-05-18.md');
|
||||
const ownerQueueCleanup = readText(rootDir, 'docs/releases/2.0.0-rc.1/owner-queue-cleanup-2026-05-18.md');
|
||||
const previewManifest = readText(rootDir, 'docs/releases/2.0.0-rc.1/preview-pack-manifest.md');
|
||||
const previewPackSmoke = readText(rootDir, 'scripts/preview-pack-smoke.js');
|
||||
const progressSync = readText(rootDir, 'docs/architecture/progress-sync-contract.md');
|
||||
@@ -579,22 +497,9 @@ function buildRequirements(rootDir, platformReport) {
|
||||
&& fileExists(rootDir, 'skills/hermes-imports/SKILL.md');
|
||||
|
||||
const githubLive = !platformReport.github.skipped && platformReport.github.totals.errors === 0;
|
||||
const ownerWideOpenPrs = extractLabeledCount(ownerQueueCleanup, 'Owner-wide open PRs after cleanup');
|
||||
const ownerWideOpenIssues = extractLabeledCount(ownerQueueCleanup, 'Owner-wide open issues after cleanup');
|
||||
const trackedPrQueueCurrent = githubLive
|
||||
&& platformReport.github.totals.openPrs <= platformReport.thresholds.maxOpenPrs;
|
||||
const trackedIssueQueueCurrent = githubLive
|
||||
const queuesCurrent = githubLive
|
||||
&& platformReport.github.totals.openPrs <= platformReport.thresholds.maxOpenPrs
|
||||
&& platformReport.github.totals.openIssues <= platformReport.thresholds.maxOpenIssues;
|
||||
const ownerPrQueueCurrent = ownerWideOpenPrs === null
|
||||
|| ownerWideOpenPrs <= platformReport.thresholds.maxOpenPrs;
|
||||
const ownerIssueQueueCurrent = ownerWideOpenIssues === null
|
||||
|| ownerWideOpenIssues <= platformReport.thresholds.maxOpenIssues;
|
||||
const ownerPrEvidence = ownerWideOpenPrs === null
|
||||
? ''
|
||||
: `; ${ownerWideOpenPrs} owner-wide open PRs after cleanup`;
|
||||
const ownerIssueEvidence = ownerWideOpenIssues === null
|
||||
? ''
|
||||
: `; ${ownerWideOpenIssues} owner-wide open issues after cleanup`;
|
||||
const discussionsCurrent = githubLive
|
||||
&& platformReport.github.totals.discussionsNeedingMaintainerTouch === 0
|
||||
&& platformReport.github.totals.discussionsMissingAcceptedAnswer === 0;
|
||||
@@ -603,30 +508,22 @@ function buildRequirements(rootDir, platformReport) {
|
||||
buildRequirement(
|
||||
'public-pr-budget',
|
||||
'Keep public PRs below 20',
|
||||
ownerWideOpenPrs === null
|
||||
? 'scripts/platform-audit.js live GitHub sweep'
|
||||
: 'scripts/platform-audit.js live GitHub sweep plus owner-wide queue cleanup ledger',
|
||||
trackedPrQueueCurrent && ownerPrQueueCurrent ? 'current' : 'in_progress',
|
||||
'scripts/platform-audit.js live GitHub sweep',
|
||||
queuesCurrent ? 'current' : 'in_progress',
|
||||
githubLive
|
||||
? `${platformReport.github.totals.openPrs} open PRs across ${platformReport.github.repos.length} tracked repos${ownerPrEvidence}`
|
||||
? `${platformReport.github.totals.openPrs} open PRs across ${platformReport.github.repos.length} tracked repos`
|
||||
: 'live GitHub queue readback was skipped or failed',
|
||||
trackedPrQueueCurrent && ownerPrQueueCurrent
|
||||
? 'repeat platform:audit and owner-wide gh search before release'
|
||||
: 'run live platform:audit and owner-wide gh search, then drain PR queue'
|
||||
queuesCurrent ? 'repeat before release' : 'run live platform:audit and drain PR queue'
|
||||
),
|
||||
buildRequirement(
|
||||
'public-issue-budget',
|
||||
'Keep public issues below 20',
|
||||
ownerWideOpenIssues === null
|
||||
? 'scripts/platform-audit.js live GitHub sweep'
|
||||
: 'scripts/platform-audit.js live GitHub sweep plus owner-wide queue cleanup ledger',
|
||||
trackedIssueQueueCurrent && ownerIssueQueueCurrent ? 'current' : 'in_progress',
|
||||
'scripts/platform-audit.js live GitHub sweep',
|
||||
queuesCurrent ? 'current' : 'in_progress',
|
||||
githubLive
|
||||
? `${platformReport.github.totals.openIssues} open issues across ${platformReport.github.repos.length} tracked repos${ownerIssueEvidence}`
|
||||
? `${platformReport.github.totals.openIssues} open issues across ${platformReport.github.repos.length} tracked repos`
|
||||
: 'live GitHub queue readback was skipped or failed',
|
||||
trackedIssueQueueCurrent && ownerIssueQueueCurrent
|
||||
? 'repeat platform:audit and owner-wide gh search before release'
|
||||
: 'run live platform:audit and owner-wide gh search, then drain issue queue'
|
||||
queuesCurrent ? 'repeat before release' : 'run live platform:audit and drain issue queue'
|
||||
),
|
||||
buildRequirement(
|
||||
'repository-discussions',
|
||||
@@ -682,19 +579,12 @@ function buildRequirements(rootDir, platformReport) {
|
||||
buildRequirement(
|
||||
'naming-and-plugin-publication',
|
||||
'Prepare name-change, Claude plugin, and Codex plugin paths',
|
||||
'naming-and-publication-matrix plus release-name-plugin-publication checklist plus publication-readiness',
|
||||
'naming-and-publication-matrix plus publication-readiness',
|
||||
includesAll(namingMatrix, ['Claude plugin', 'Codex plugin', 'npm package', 'Publication Paths'])
|
||||
&& includesAll(releasePublicationChecklist, [
|
||||
'Everything Claude Code (ECC)',
|
||||
'ecc-universal',
|
||||
'claude plugin tag .claude-plugin --dry-run',
|
||||
'codex plugin marketplace add',
|
||||
'Do not rename the repo or package until rc.1 is published'
|
||||
])
|
||||
&& includesAll(publicationReadiness, ['Claude plugin', 'Codex plugin'])
|
||||
? 'in_progress'
|
||||
: 'not_complete',
|
||||
'naming matrix, release publication checklist, and plugin readiness gates exist',
|
||||
'naming matrix and plugin readiness gates exist',
|
||||
'real tag/push, marketplace submission, and final channel choice remain approval-gated'
|
||||
),
|
||||
buildRequirement(
|
||||
@@ -706,12 +596,8 @@ function buildRequirements(rootDir, platformReport) {
|
||||
&& fileExists(rootDir, 'docs/releases/2.0.0-rc.1/linkedin-post.md')
|
||||
? 'in_progress'
|
||||
: 'not_complete',
|
||||
includesAll(releaseUrlLedger, ['Live Now', 'Approval-Gated URLs', 'Codex marketplace CLI docs'])
|
||||
? 'release notes, X thread, LinkedIn draft, and URL ledger are present'
|
||||
: 'release notes, X thread, and LinkedIn draft are present',
|
||||
includesAll(releaseUrlLedger, ['Live Now', 'Approval-Gated URLs', 'Codex marketplace CLI docs'])
|
||||
? 'final live release/npm/plugin/billing URLs and publish approval still pending'
|
||||
: 'URL-backed refresh and publish approval still pending'
|
||||
'release notes, X thread, and LinkedIn draft are present',
|
||||
'URL-backed refresh and publish approval still pending'
|
||||
),
|
||||
buildRequirement(
|
||||
'agentshield-enterprise-iteration',
|
||||
@@ -827,7 +713,7 @@ function buildReport(options) {
|
||||
next_work_order: [
|
||||
'Regenerate this dashboard from the final release commit before publication evidence is recorded.',
|
||||
'Repeat ITO-57 Linear/project status sync after the next significant merge batch or advisory-source refresh.',
|
||||
'Create or verify Marketplace-managed Pro target billing-state with webhook provenance, configure the target account and INTERNAL_API_SECRET, then rerun target readback and the live announcement gate before publishing native-payments copy.',
|
||||
'Complete ECC Tools Marketplace purchase/webhook readback, then run preflight and the live announcement gate before publishing native-payments copy.',
|
||||
'Resume ITO-45, ITO-46, and ITO-56 only after the generated dashboard and final release gates are refreshed.',
|
||||
],
|
||||
};
|
||||
|
||||
@@ -426,8 +426,8 @@ function buildLocalEvidenceChecks(rootDir) {
|
||||
const roadmap = readText(rootDir, 'docs/ECC-2.0-GA-ROADMAP.md');
|
||||
const progressSync = readText(rootDir, 'docs/architecture/progress-sync-contract.md');
|
||||
const supplyChain = readText(rootDir, 'docs/security/supply-chain-incident-response.md');
|
||||
const evidence = readText(rootDir, 'docs/releases/2.0.0-rc.1/publication-evidence-2026-05-18.md');
|
||||
const operatorDashboard = readText(rootDir, 'docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-18.md');
|
||||
const evidence = readText(rootDir, 'docs/releases/2.0.0-rc.1/publication-evidence-2026-05-15.md');
|
||||
const operatorDashboard = readText(rootDir, 'docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-15.md');
|
||||
|
||||
return [
|
||||
buildCheck(
|
||||
@@ -472,9 +472,9 @@ function buildLocalEvidenceChecks(rootDir) {
|
||||
),
|
||||
buildCheck(
|
||||
'release-evidence-current',
|
||||
includesAll(evidence, ['TanStack', 'Mini Shai-Hulud', 'Home persistence IOC scan', 'Supply-Chain Watch', 'npm signatures']) ? 'pass' : 'fail',
|
||||
includesAll(evidence, ['TanStack', 'Mini Shai-Hulud', 'Node IPC follow-up', 'node-ipc', 'IOC scan']) ? 'pass' : 'fail',
|
||||
'rc.1 evidence includes current supply-chain verification artifacts',
|
||||
{ path: 'docs/releases/2.0.0-rc.1/publication-evidence-2026-05-18.md' }
|
||||
{ path: 'docs/releases/2.0.0-rc.1/publication-evidence-2026-05-15.md' }
|
||||
),
|
||||
buildCheck(
|
||||
'operator-readiness-dashboard',
|
||||
@@ -486,7 +486,7 @@ function buildLocalEvidenceChecks(rootDir) {
|
||||
'Next Work Order',
|
||||
]) ? 'pass' : 'fail',
|
||||
'operator dashboard maps macro-goal requirements to current evidence and open gaps',
|
||||
{ path: 'docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-18.md' }
|
||||
{ path: 'docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-15.md' }
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -25,12 +25,8 @@ const REQUIRED_ARTIFACTS = [
|
||||
`${RELEASE_DIR}/publication-evidence-2026-05-15.md`,
|
||||
`${RELEASE_DIR}/publication-evidence-2026-05-16.md`,
|
||||
`${RELEASE_DIR}/publication-evidence-2026-05-17.md`,
|
||||
`${RELEASE_DIR}/publication-evidence-2026-05-18.md`,
|
||||
`${RELEASE_DIR}/operator-readiness-dashboard-2026-05-17.md`,
|
||||
`${RELEASE_DIR}/operator-readiness-dashboard-2026-05-18.md`,
|
||||
`${RELEASE_DIR}/release-url-ledger-2026-05-18.md`,
|
||||
`${RELEASE_DIR}/naming-and-publication-matrix.md`,
|
||||
`${RELEASE_DIR}/release-name-plugin-publication-checklist-2026-05-18.md`,
|
||||
`${RELEASE_DIR}/x-thread.md`,
|
||||
`${RELEASE_DIR}/linkedin-post.md`,
|
||||
`${RELEASE_DIR}/article-outline.md`,
|
||||
@@ -40,7 +36,7 @@ const REQUIRED_ARTIFACTS = [
|
||||
|
||||
const REQUIRED_VERIFICATION_COMMANDS = [
|
||||
'git status --short --branch',
|
||||
'node scripts/platform-audit.js --json',
|
||||
'node scripts/platform-audit.js --format json --allow-untracked docs/drafts/',
|
||||
'npm run preview-pack:smoke',
|
||||
'npm run harness:adapters -- --check',
|
||||
'npm run harness:audit -- --format json',
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
---
|
||||
name: blender-motion-state-inspection
|
||||
description: Use this skill when inspecting Blender characters, rigs, poses, animation retargeting, ground contact, facing direction, or model-vs-motion alignment where screenshots alone are not enough.
|
||||
origin: ECC
|
||||
tools: Read, Write, Edit, Bash, Grep, Glob
|
||||
---
|
||||
|
||||
# Blender Motion State Inspection
|
||||
|
||||
## When to Use
|
||||
|
||||
- A Blender character looks twisted, mirrored, flattened, offset, or foot-sliding in an animation.
|
||||
- A user asks whether an imported avatar, armature, or retargeted motion matches an expected pose.
|
||||
- You need to compare rendered evidence with structured facts such as bones, bounding boxes, contacts, and facing vectors.
|
||||
- A workflow depends on deciding whether a model is a character, prop, proxy mesh, control rig, or broken import.
|
||||
|
||||
## Core Principle
|
||||
|
||||
Do not judge animated 3D assets only from screenshots. Screenshots are review evidence, but they hide axis conventions, bone names, object scale, local transforms, parented meshes, material slots, and frame-by-frame contact state.
|
||||
|
||||
First extract structured Blender state, then use viewport screenshots or renders to confirm what the facts imply.
|
||||
|
||||
## How It Works
|
||||
|
||||
1. Establish the clean scene and asset baseline before judging motion.
|
||||
2. Extract structured facts from Blender using an exporter or Blender Python run inside Blender's own interpreter.
|
||||
3. Sample the frames most likely to expose contact, orientation, scale, and retargeting errors.
|
||||
4. Compare the measured facts against the user's expected pose, direction, ground plane, and render goal.
|
||||
5. Return a concise report that separates confirmed facts, likely causes, and required fixes.
|
||||
|
||||
## Inspection Workflow
|
||||
|
||||
1. Inventory the scene.
|
||||
- List meshes, armatures, empties, cameras, lights, modifiers, parent relationships, and hidden objects.
|
||||
- Separate character meshes from helper/proxy geometry before judging the avatar.
|
||||
- Record object-space and world-space bounding boxes.
|
||||
|
||||
2. Identify the skeleton.
|
||||
- Capture armature names, pose bones, bone heads/tails, roll, parent chains, constraints, and rest-pose axes.
|
||||
- Map semantic bones such as hips, spine, neck, head, shoulders, elbows, hands, thighs, knees, ankles, and feet.
|
||||
- Flag missing left/right pairs and unusual naming schemes.
|
||||
|
||||
3. Determine forward, up, and side axes.
|
||||
- Use the pelvis, spine, shoulders, hips, head, and feet together; do not rely on a single mesh normal.
|
||||
- Compare local armature axes with world axes and imported file conventions such as glTF Y-up vs Blender Z-up.
|
||||
- Mark likely mirrored or backwards imports when face/head/feet direction conflicts with root motion.
|
||||
|
||||
4. Sample animation frames.
|
||||
- Inspect first, middle, contact, airborne, and extreme frames.
|
||||
- Record root location, root heading, pelvis height, torso lean, limb directions, foot clearance, and mesh bounds.
|
||||
- For long or fast motion, sample more densely around flips, landings, turns, collisions, and floor contacts.
|
||||
|
||||
5. Check model integrity before retargeting blame.
|
||||
- Confirm the clean baseline shape before applying animation.
|
||||
- Preserve original mesh, materials, armature, and skinning unless the user explicitly asks for repair.
|
||||
- Treat unexplained sphere-like blobs, giant proxy meshes, or crushed bodies as import/selection issues until proven otherwise.
|
||||
|
||||
6. Diagnose contact and motion issues.
|
||||
- Ground penetration: compare lowest foot or shoe vertices with floor height per frame.
|
||||
- Foot sliding: compare foot world positions across planted frames.
|
||||
- Leg crossover: compare left/right thigh, knee, ankle, and foot side ordering.
|
||||
- Twist damage: compare bone swing direction separately from roll/twist around the limb axis.
|
||||
- Scale drift: compare animated mesh bounds against the clean baseline bounds.
|
||||
|
||||
7. Report facts before opinions.
|
||||
- Include frame numbers, object names, bone names, world coordinates, and thresholds.
|
||||
- Separate confirmed failures from visual suspicions.
|
||||
- Attach screenshots only after the structured state explains what to look for.
|
||||
|
||||
## Recommended Report Shape
|
||||
|
||||
```markdown
|
||||
## Blender Motion Inspection
|
||||
|
||||
### Scene Inventory
|
||||
- Character candidates:
|
||||
- Armatures:
|
||||
- Helper/proxy objects:
|
||||
- Cameras/lights:
|
||||
|
||||
### Orientation
|
||||
- World up:
|
||||
- Character forward:
|
||||
- Root heading:
|
||||
- Mirrored/backwards risk:
|
||||
|
||||
### Baseline Integrity
|
||||
- Clean mesh bounds:
|
||||
- Animated mesh bounds:
|
||||
- Materials/skin preserved:
|
||||
- Suspicious non-character meshes:
|
||||
|
||||
### Frame Findings
|
||||
| Frame | Finding | Evidence |
|
||||
| --- | --- | --- |
|
||||
| 1 | Clean baseline pose | hips/spine/feet aligned |
|
||||
| 96 | Foot penetrates floor | left_foot min_z = -0.04 |
|
||||
|
||||
### Verdict
|
||||
- Pass/fail:
|
||||
- Required fix:
|
||||
- Render readiness:
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Walk Cycle With Foot Sliding
|
||||
|
||||
Scenario: a retargeted character appears to skate during a walk cycle, but the front camera angle makes the foot contact hard to judge.
|
||||
|
||||
Apply the workflow:
|
||||
- Inventory the scene: character mesh `HeroBody`, armature `HeroRig`, ground plane `Floor`, no hidden proxy meshes.
|
||||
- Identify the skeleton: semantic feet are `foot.L` and `foot.R`; hips are `pelvis`; root bone is `root`.
|
||||
- Sample animation frames: inspect frames 1, 18, 24, 30, 42, and 48 around planted-foot moments.
|
||||
- Diagnose contact and motion issues: compare world-space foot locations during planted frames.
|
||||
|
||||
Extracted facts:
|
||||
|
||||
| Frame | Fact | Evidence |
|
||||
| --- | --- | --- |
|
||||
| 18 | Left foot is planted | `foot.L min_z = 0.004`, toe and heel both near floor |
|
||||
| 24 | Left foot slides while planted | `foot.L x = 0.21 -> 0.28` over six frames |
|
||||
| 30 | Pelvis keeps moving forward | `pelvis y = 1.14 -> 1.31` |
|
||||
|
||||
Verdict: fail for render readiness. The motion needs foot-lock cleanup or retargeting constraint review; the body mesh does not need proportion changes.
|
||||
|
||||
### Backwards Imported Character
|
||||
|
||||
Scenario: a character looks correct in a still frame, but the animation moves opposite the expected travel direction.
|
||||
|
||||
Apply the workflow:
|
||||
- Determine forward, up, and side axes: compare head, chest, feet, and root motion.
|
||||
- Sample animation frames: inspect frame 1 and the midpoint of the travel path.
|
||||
- Report facts before opinions: include the root heading and model-facing direction separately.
|
||||
|
||||
Extracted facts:
|
||||
|
||||
| Frame | Fact | Evidence |
|
||||
| --- | --- | --- |
|
||||
| 1 | Character face points toward world `-Y` | head/chest vector from `neck` to `head` resolves to `-Y` |
|
||||
| 72 | Root motion travels toward world `+Y` | `root y = 0.0 -> 2.8` |
|
||||
| 72 | Feet remain visually forward-facing opposite travel | toe bones point `-Y` while displacement is `+Y` |
|
||||
|
||||
Verdict: likely backwards import or retargeting forward-axis mismatch. Fix the import/retarget axis mapping before editing animation curves.
|
||||
|
||||
## Practical Thresholds
|
||||
|
||||
- Assume Blender's default meter-scale units unless the scene unit scale says otherwise.
|
||||
- Treat ground penetration above 1-2 cm as visible unless the floor is soft or intentionally stylized.
|
||||
- Treat a sudden scale change above 5% as a likely rig, constraint, or transform inheritance problem.
|
||||
- Treat left/right ankle side-order flips during airborne inverted motion as leg crossover risk even if it recovers later.
|
||||
- Treat root heading jumps above 30 degrees per frame as suspicious unless the source motion includes a snap turn.
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
- Do not modify body proportions to force pose matching unless the task is explicitly mesh repair.
|
||||
- Do not bake away the clean baseline before recording it.
|
||||
- Do not use one rendered camera angle as proof that a pose is correct.
|
||||
- Do not delete helper objects until you have recorded why they are not part of the character.
|
||||
- Do not assume an avatar faces +Y, -Y, +X, or -X without checking head, feet, torso, and root motion together.
|
||||
|
||||
## Tooling Notes
|
||||
|
||||
If a Blender state exporter is available, prefer JSON that includes meshes, armatures, pose bones, materials, contacts, bounding boxes, and sampled animation frames. If no exporter exists, run a small Blender Python script through Blender itself, for example `blender --background scene.blend --python collect_motion_state.py`, because `bpy` is not available in a normal system Python interpreter.
|
||||
Executable
+54
@@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
# Strategic Compact Suggester
|
||||
# Runs on PreToolUse or periodically to suggest manual compaction at logical intervals
|
||||
#
|
||||
# Why manual over auto-compact:
|
||||
# - Auto-compact happens at arbitrary points, often mid-task
|
||||
# - Strategic compacting preserves context through logical phases
|
||||
# - Compact after exploration, before execution
|
||||
# - Compact after completing a milestone, before starting next
|
||||
#
|
||||
# Hook config (in ~/.claude/settings.json):
|
||||
# {
|
||||
# "hooks": {
|
||||
# "PreToolUse": [{
|
||||
# "matcher": "Edit|Write",
|
||||
# "hooks": [{
|
||||
# "type": "command",
|
||||
# "command": "~/.claude/skills/strategic-compact/suggest-compact.sh"
|
||||
# }]
|
||||
# }]
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# Criteria for suggesting compact:
|
||||
# - Session has been running for extended period
|
||||
# - Large number of tool calls made
|
||||
# - Transitioning from research/exploration to implementation
|
||||
# - Plan has been finalized
|
||||
|
||||
# Track tool call count (increment in a temp file)
|
||||
# Use CLAUDE_SESSION_ID for session-specific counter (not $$ which changes per invocation)
|
||||
SESSION_ID="${CLAUDE_SESSION_ID:-${PPID:-default}}"
|
||||
COUNTER_FILE="/tmp/claude-tool-count-${SESSION_ID}"
|
||||
THRESHOLD=${COMPACT_THRESHOLD:-50}
|
||||
|
||||
# Initialize or increment counter
|
||||
if [ -f "$COUNTER_FILE" ]; then
|
||||
count=$(cat "$COUNTER_FILE")
|
||||
count=$((count + 1))
|
||||
echo "$count" > "$COUNTER_FILE"
|
||||
else
|
||||
echo "1" > "$COUNTER_FILE"
|
||||
count=1
|
||||
fi
|
||||
|
||||
# Suggest compact after threshold tool calls
|
||||
if [ "$count" -eq "$THRESHOLD" ]; then
|
||||
echo "[StrategicCompact] $THRESHOLD tool calls reached - consider /compact if transitioning phases" >&2
|
||||
fi
|
||||
|
||||
# Suggest at regular intervals after threshold
|
||||
if [ "$count" -gt "$THRESHOLD" ] && [ $((count % 25)) -eq 0 ]; then
|
||||
echo "[StrategicCompact] $count tool calls - good checkpoint for /compact if context is stale" >&2
|
||||
fi
|
||||
@@ -1,343 +0,0 @@
|
||||
---
|
||||
name: uncloud
|
||||
description: Use when managing an Uncloud cluster — deploying services, configuring Caddy ingress, adding static proxy routes for non-cluster devices, publishing ports, scaling, inspecting logs, or managing machines and volumes with the `uc` CLI.
|
||||
origin: ECC
|
||||
---
|
||||
|
||||
# Uncloud Cluster Management
|
||||
|
||||
Reference for the `uc` CLI — a decentralised self-hosting platform using Docker containers, WireGuard mesh networking, and Caddy reverse proxy.
|
||||
|
||||
## When to Activate
|
||||
|
||||
Use this skill when working with Uncloud clusters, especially when:
|
||||
- Bootstrapping or joining machines with `uc machine`
|
||||
- Deploying services from Compose files with `uc deploy`
|
||||
- Publishing HTTP, HTTPS, TCP, or UDP ports through Uncloud
|
||||
- Configuring Caddy ingress with `x-caddy`, `x-ports`, or `--caddyfile`
|
||||
- Routing external LAN devices through the cluster proxy
|
||||
- Inspecting logs, service state, volumes, DNS, or machine placement
|
||||
|
||||
## How It Works
|
||||
|
||||
Uncloud runs Docker services across peer machines connected by a WireGuard mesh. Each machine is an equal cluster member; services communicate on the overlay network and Caddy runs globally to terminate public HTTP/HTTPS traffic. Compose files can use Uncloud extensions for ingress, placement, and generated Caddy configuration, while the `uc` CLI handles image distribution, scheduling, scaling, logs, and cluster state.
|
||||
|
||||
## Examples
|
||||
|
||||
```bash
|
||||
uc machine init user@host --name machine-1
|
||||
uc service run --name web -p app.example.com:8080/https nginx:latest
|
||||
uc deploy
|
||||
```
|
||||
|
||||
## Core Concepts
|
||||
|
||||
- **No central control plane** — all machines are equal peers connected by WireGuard
|
||||
- **Caddy** runs as a global service on every machine; auto-obtains TLS from Let's Encrypt
|
||||
- **Overlay network** — services communicate via `10.210.0.0/16` by default; DNS provided inside the mesh
|
||||
- **Caddyfile is autogenerated** — never edit it directly; use `x-caddy` / `--caddyfile` instead
|
||||
|
||||
---
|
||||
|
||||
## CLI Quick Reference
|
||||
|
||||
### Machines
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `uc machine init user@host` | Bootstrap first machine / new cluster |
|
||||
| `uc machine add user@host` | Join machine to existing cluster |
|
||||
| `uc machine ls` | List machines |
|
||||
| `uc machine update NAME --public-ip IP` | Update public IP for ingress |
|
||||
| `uc machine rm NAME` | Remove machine |
|
||||
|
||||
Key `init` flags: `--name`, `--network 10.210.0.0/16`, `--no-caddy`, `--no-dns`, `--public-ip auto\|IP\|none`
|
||||
|
||||
### Services
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `uc service ls` / `uc ls` | List services |
|
||||
| `uc service run IMAGE` | Run a single container service |
|
||||
| `uc deploy` | Deploy from `compose.yaml` |
|
||||
| `uc deploy --no-build` | Deploy already-pushed images without rebuilding |
|
||||
| `uc deploy --recreate` | Force service recreation |
|
||||
| `uc scale SERVICE N` | Set replica count |
|
||||
| `uc service logs SERVICE` | View logs |
|
||||
| `uc service exec SERVICE` | Shell into container |
|
||||
| `uc service inspect SERVICE` | Detailed info |
|
||||
| `uc service rm SERVICE` | Remove service (keeps named volumes) |
|
||||
| `uc ps` | All containers across cluster |
|
||||
|
||||
### Images
|
||||
|
||||
```bash
|
||||
uc image push myapp:latest # Push local image to all machines
|
||||
uc image push myapp:latest -m machine1,machine2 # Push to specific machines
|
||||
uc images # List images in cluster
|
||||
```
|
||||
|
||||
### Volumes
|
||||
|
||||
```bash
|
||||
uc volume ls # All volumes
|
||||
uc volume ls -m machine1 # On specific machine
|
||||
uc volume create NAME -m MACHINE
|
||||
uc volume rm NAME
|
||||
```
|
||||
|
||||
### Caddy
|
||||
|
||||
```bash
|
||||
uc caddy config # Show current generated Caddyfile (read-only)
|
||||
uc caddy deploy # Deploy/upgrade Caddy across cluster
|
||||
```
|
||||
|
||||
### DNS & Context
|
||||
|
||||
```bash
|
||||
uc dns show # Show reserved *.uncld.dev domain
|
||||
uc dns reserve # Reserve a new domain
|
||||
uc ctx ls # List cluster contexts
|
||||
uc ctx use prod # Switch context
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Port Publishing
|
||||
|
||||
### HTTP/HTTPS (via Caddy reverse proxy)
|
||||
|
||||
```
|
||||
-p [hostname:]container_port[/protocol]
|
||||
```
|
||||
|
||||
| Example | Meaning |
|
||||
|---------|---------|
|
||||
| `-p 8080/https` | HTTPS with auto `service-name.cluster-domain` hostname |
|
||||
| `-p app.example.com:8080/https` | HTTPS with custom hostname |
|
||||
| `-p 8080/http` | HTTP only, no TLS |
|
||||
|
||||
### TCP/UDP (host-bound, bypasses Caddy)
|
||||
|
||||
```
|
||||
-p [host_ip:]host_port:container_port[/protocol]@host
|
||||
```
|
||||
|
||||
| Example | Meaning |
|
||||
|---------|---------|
|
||||
| `-p 5432:5432@host` | TCP 5432 on all interfaces |
|
||||
| `-p 127.0.0.1:5432:5432@host` | TCP 5432 loopback only |
|
||||
| `-p 53:5353/udp@host` | UDP |
|
||||
|
||||
---
|
||||
|
||||
## Compose File Extensions
|
||||
|
||||
Uncloud adds these extensions on top of Docker Compose:
|
||||
|
||||
### `x-ports` — publish ports with domains
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
image: app:latest
|
||||
x-ports:
|
||||
- example.com:8000/https
|
||||
- www.example.com:8000/https
|
||||
- api.example.com:9000/https
|
||||
```
|
||||
|
||||
### `x-caddy` — custom Caddy config for service
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
image: app:latest
|
||||
x-caddy: |
|
||||
example.com {
|
||||
redir https://www.example.com{uri} permanent
|
||||
}
|
||||
www.example.com {
|
||||
reverse_proxy {{upstreams 8000}} {
|
||||
import common_proxy
|
||||
}
|
||||
basic_auth /admin/* {
|
||||
admin $2a$14$...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Template functions available inside `x-caddy`:
|
||||
- `{{upstreams [service] [port]}}` — healthy container IPs
|
||||
- `{{.Name}}` — service name
|
||||
- `{{.Upstreams}}` — map of all services → IPs
|
||||
|
||||
### `x-machines` — placement constraints
|
||||
|
||||
```yaml
|
||||
services:
|
||||
db:
|
||||
image: postgres:18
|
||||
x-machines: db-machine # Single machine name
|
||||
app:
|
||||
image: app:latest
|
||||
x-machines:
|
||||
- machine-1
|
||||
- machine-2
|
||||
```
|
||||
|
||||
### Full multi-service example
|
||||
|
||||
```yaml
|
||||
services:
|
||||
api:
|
||||
build: ./api
|
||||
x-ports:
|
||||
- api.example.com:3000/https
|
||||
environment:
|
||||
DATABASE_URL: postgres://db:5432/mydb
|
||||
|
||||
web:
|
||||
build: ./web
|
||||
x-ports:
|
||||
- example.com:8000/https
|
||||
- www.example.com:8000/https
|
||||
environment:
|
||||
API_URL: http://api:3000
|
||||
|
||||
db:
|
||||
image: postgres:18
|
||||
environment:
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql/data
|
||||
x-machines: db-machine
|
||||
|
||||
volumes:
|
||||
db-data:
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Routing to External (Non-Cluster) Devices
|
||||
|
||||
To expose an external device (e.g. BMC, NAS, router UI) via Caddy without running a real container:
|
||||
|
||||
**1. Create a Caddyfile snippet** (e.g. `~/device.caddyfile`):
|
||||
|
||||
```caddyfile
|
||||
https://device.example.com {
|
||||
reverse_proxy https://192.168.1.x {
|
||||
transport http {
|
||||
tls_insecure_skip_verify # needed for self-signed BMC certs
|
||||
}
|
||||
}
|
||||
log
|
||||
}
|
||||
```
|
||||
|
||||
For plaintext upstream: `reverse_proxy http://192.168.1.x:port`
|
||||
|
||||
**2. Register as a named service with no-op container:**
|
||||
|
||||
```bash
|
||||
uc service run \
|
||||
--name device-bmc \
|
||||
--caddyfile ~/device.caddyfile \
|
||||
registry.k8s.io/pause:3.9
|
||||
```
|
||||
|
||||
`pause` is a minimal no-op container — it does nothing, but gives Uncloud a service entry to attach the Caddyfile to.
|
||||
|
||||
**3. Verify:**
|
||||
|
||||
```bash
|
||||
uc caddy config # device.example.com block should appear
|
||||
```
|
||||
|
||||
> `--caddyfile` cannot be combined with non-`@host` published ports.
|
||||
|
||||
**DNS tip:** A wildcard record (`*.yourdomain.com → cluster-public-ip`) means any new subdomain works immediately — no DNS change needed per service.
|
||||
|
||||
---
|
||||
|
||||
## Service DNS (Internal)
|
||||
|
||||
Services inside the cluster resolve each other by name:
|
||||
|
||||
| DNS name | Resolves to |
|
||||
|----------|------------|
|
||||
| `service-name` | Any healthy container |
|
||||
| `service-name.internal` | Same |
|
||||
| `rr.service-name.internal` | Round-robin |
|
||||
| `nearest.service-name.internal` | Machine-local first |
|
||||
|
||||
---
|
||||
|
||||
## Scaling & Global Services
|
||||
|
||||
```bash
|
||||
uc scale web 5 # 5 replicas (spread across machines)
|
||||
uc scale web 1 # Scale down
|
||||
```
|
||||
|
||||
```yaml
|
||||
services:
|
||||
caddy:
|
||||
deploy:
|
||||
mode: global # One container on every machine
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Image Tag Templates (in compose.yaml)
|
||||
|
||||
```yaml
|
||||
image: myapp:{{gitdate "20060102"}}.{{gitsha 7}}
|
||||
image: myapp:{{gitsha 7}}.${GITHUB_RUN_ID:-local}
|
||||
```
|
||||
|
||||
| Function | Output |
|
||||
|----------|--------|
|
||||
| `{{gitsha N}}` | First N chars of commit SHA |
|
||||
| `{{gitdate "format"}}` | Git commit date in Go format |
|
||||
| `{{date "format"}}` | Current date |
|
||||
|
||||
---
|
||||
|
||||
## Common Workflows
|
||||
|
||||
**Deploy from source:**
|
||||
```bash
|
||||
uc deploy # Build + push + deploy
|
||||
uc build --push && uc deploy --no-build # Separate steps
|
||||
```
|
||||
|
||||
**Inspect a service:**
|
||||
```bash
|
||||
uc inspect web
|
||||
uc logs -f web
|
||||
uc logs --since 1h web
|
||||
uc exec web # Opens shell
|
||||
uc exec web /bin/sh -c "env" # Run specific command
|
||||
```
|
||||
|
||||
**Zero-downtime deploys** happen automatically; Uncloud waits for health checks before terminating old containers.
|
||||
|
||||
**Force recreate:**
|
||||
```bash
|
||||
uc deploy --recreate
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
| Mistake | Fix |
|
||||
|---------|-----|
|
||||
| Editing the Caddyfile directly | Use `x-caddy` in compose or `--caddyfile` on `uc service run` |
|
||||
| Proxying an HTTPS upstream with self-signed cert | Add `transport http { tls_insecure_skip_verify }` |
|
||||
| `uc caddy config` shows no user-defined blocks | Caddy admin socket unreachable — check `uc inspect caddy` and `uc logs caddy` |
|
||||
| Service can't reach external LAN IP from container | Verify Caddy container's host can route to target network |
|
||||
| Volumes lost after `uc service rm` | Named volumes persist; only anonymous volumes are auto-removed |
|
||||
@@ -15,7 +15,6 @@ from llm.core.interface import (
|
||||
RateLimitError,
|
||||
)
|
||||
from llm.core.types import LLMInput, LLMOutput, ModelInfo, ProviderType, ToolCall
|
||||
from llm.providers.constants import EMPTY_FILTERED_RESPONSE_ERROR
|
||||
|
||||
ASTRAFLOW_BASE_URL = "https://api.umodelverse.ai/v1"
|
||||
ASTRAFLOW_CN_BASE_URL = "https://api.modelverse.cn/v1"
|
||||
@@ -56,7 +55,7 @@ class _AstraflowBaseProvider(LLMProvider):
|
||||
env_model = os.environ.get(self.model_env)
|
||||
fallback_model = os.environ.get(self.fallback_model_env) if self.fallback_model_env else None
|
||||
self.default_model = default_model or env_model or fallback_model or DEFAULT_ASTRAFLOW_MODEL
|
||||
self.client = OpenAI(api_key=self.api_key, base_url=self.base_url, _enforce_credentials=False)
|
||||
self.client = OpenAI(api_key=self.api_key, base_url=self.base_url)
|
||||
self._models = [
|
||||
ModelInfo(
|
||||
name=self.default_model,
|
||||
@@ -80,8 +79,6 @@ class _AstraflowBaseProvider(LLMProvider):
|
||||
params["tools"] = [tool.to_openai_tool() for tool in llm_input.tools]
|
||||
|
||||
response = self.client.chat.completions.create(**params)
|
||||
if not response.choices or response.choices[0].message is None:
|
||||
raise ValueError(EMPTY_FILTERED_RESPONSE_ERROR)
|
||||
choice = response.choices[0]
|
||||
|
||||
tool_calls = None
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
"""Shared provider constants."""
|
||||
|
||||
EMPTY_FILTERED_RESPONSE_ERROR = "LLM returned empty or filtered response"
|
||||
+113
-124
@@ -1,125 +1,114 @@
|
||||
"""OpenAI provider adapter."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
from openai import OpenAI
|
||||
|
||||
from llm.core.interface import (
|
||||
AuthenticationError,
|
||||
ContextLengthError,
|
||||
LLMProvider,
|
||||
RateLimitError,
|
||||
)
|
||||
from llm.core.types import LLMInput, LLMOutput, Message, ModelInfo, ProviderType, ToolCall
|
||||
from llm.providers.constants import EMPTY_FILTERED_RESPONSE_ERROR
|
||||
|
||||
|
||||
class OpenAIProvider(LLMProvider):
|
||||
provider_type = ProviderType.OPENAI
|
||||
|
||||
def __init__(self, api_key: str | None = None, base_url: str | None = None) -> None:
|
||||
self.client = OpenAI(
|
||||
api_key=api_key or os.environ.get("OPENAI_API_KEY"),
|
||||
base_url=base_url,
|
||||
_enforce_credentials=False,
|
||||
)
|
||||
self._models = [
|
||||
ModelInfo(
|
||||
name="gpt-4o",
|
||||
provider=ProviderType.OPENAI,
|
||||
supports_tools=True,
|
||||
supports_vision=True,
|
||||
max_tokens=4096,
|
||||
context_window=128000,
|
||||
),
|
||||
ModelInfo(
|
||||
name="gpt-4o-mini",
|
||||
provider=ProviderType.OPENAI,
|
||||
supports_tools=True,
|
||||
supports_vision=True,
|
||||
max_tokens=4096,
|
||||
context_window=128000,
|
||||
),
|
||||
ModelInfo(
|
||||
name="gpt-4-turbo",
|
||||
provider=ProviderType.OPENAI,
|
||||
supports_tools=True,
|
||||
supports_vision=True,
|
||||
max_tokens=4096,
|
||||
context_window=128000,
|
||||
),
|
||||
ModelInfo(
|
||||
name="gpt-3.5-turbo",
|
||||
provider=ProviderType.OPENAI,
|
||||
supports_tools=True,
|
||||
supports_vision=False,
|
||||
max_tokens=4096,
|
||||
context_window=16385,
|
||||
),
|
||||
]
|
||||
|
||||
def generate(self, input: LLMInput) -> LLMOutput:
|
||||
try:
|
||||
params: dict[str, Any] = {
|
||||
"model": input.model or "gpt-4o-mini",
|
||||
"messages": [msg.to_dict() for msg in input.messages],
|
||||
"temperature": input.temperature,
|
||||
}
|
||||
if input.max_tokens:
|
||||
params["max_tokens"] = input.max_tokens
|
||||
if input.tools:
|
||||
"""OpenAI provider adapter."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
from openai import OpenAI
|
||||
|
||||
from llm.core.interface import (
|
||||
AuthenticationError,
|
||||
ContextLengthError,
|
||||
LLMProvider,
|
||||
RateLimitError,
|
||||
)
|
||||
from llm.core.types import LLMInput, LLMOutput, Message, ModelInfo, ProviderType, ToolCall
|
||||
|
||||
|
||||
class OpenAIProvider(LLMProvider):
|
||||
provider_type = ProviderType.OPENAI
|
||||
|
||||
def __init__(self, api_key: str | None = None, base_url: str | None = None) -> None:
|
||||
self.client = OpenAI(api_key=api_key or os.environ.get("OPENAI_API_KEY"), base_url=base_url)
|
||||
self._models = [
|
||||
ModelInfo(
|
||||
name="gpt-4o",
|
||||
provider=ProviderType.OPENAI,
|
||||
supports_tools=True,
|
||||
supports_vision=True,
|
||||
max_tokens=4096,
|
||||
context_window=128000,
|
||||
),
|
||||
ModelInfo(
|
||||
name="gpt-4o-mini",
|
||||
provider=ProviderType.OPENAI,
|
||||
supports_tools=True,
|
||||
supports_vision=True,
|
||||
max_tokens=4096,
|
||||
context_window=128000,
|
||||
),
|
||||
ModelInfo(
|
||||
name="gpt-4-turbo",
|
||||
provider=ProviderType.OPENAI,
|
||||
supports_tools=True,
|
||||
supports_vision=True,
|
||||
max_tokens=4096,
|
||||
context_window=128000,
|
||||
),
|
||||
ModelInfo(
|
||||
name="gpt-3.5-turbo",
|
||||
provider=ProviderType.OPENAI,
|
||||
supports_tools=True,
|
||||
supports_vision=False,
|
||||
max_tokens=4096,
|
||||
context_window=16385,
|
||||
),
|
||||
]
|
||||
|
||||
def generate(self, input: LLMInput) -> LLMOutput:
|
||||
try:
|
||||
params: dict[str, Any] = {
|
||||
"model": input.model or "gpt-4o-mini",
|
||||
"messages": [msg.to_dict() for msg in input.messages],
|
||||
"temperature": input.temperature,
|
||||
}
|
||||
if input.max_tokens:
|
||||
params["max_tokens"] = input.max_tokens
|
||||
if input.tools:
|
||||
params["tools"] = [tool.to_openai_tool() for tool in input.tools]
|
||||
|
||||
response = self.client.chat.completions.create(**params)
|
||||
if not response.choices or response.choices[0].message is None:
|
||||
raise ValueError(EMPTY_FILTERED_RESPONSE_ERROR)
|
||||
choice = response.choices[0]
|
||||
|
||||
tool_calls = None
|
||||
if choice.message.tool_calls:
|
||||
tool_calls = [
|
||||
ToolCall(
|
||||
id=tc.id or "",
|
||||
name=tc.function.name,
|
||||
arguments={} if not tc.function.arguments else json.loads(tc.function.arguments),
|
||||
)
|
||||
for tc in choice.message.tool_calls
|
||||
]
|
||||
|
||||
usage = None
|
||||
if response.usage:
|
||||
usage = {
|
||||
"prompt_tokens": response.usage.prompt_tokens,
|
||||
"completion_tokens": response.usage.completion_tokens,
|
||||
"total_tokens": response.usage.total_tokens,
|
||||
}
|
||||
|
||||
return LLMOutput(
|
||||
content=choice.message.content or "",
|
||||
tool_calls=tool_calls,
|
||||
model=response.model,
|
||||
usage=usage,
|
||||
stop_reason=choice.finish_reason,
|
||||
)
|
||||
except Exception as e:
|
||||
msg = str(e)
|
||||
if "401" in msg or "authentication" in msg.lower():
|
||||
raise AuthenticationError(msg, provider=ProviderType.OPENAI) from e
|
||||
if "429" in msg or "rate_limit" in msg.lower():
|
||||
raise RateLimitError(msg, provider=ProviderType.OPENAI) from e
|
||||
if "context" in msg.lower() and "length" in msg.lower():
|
||||
raise ContextLengthError(msg, provider=ProviderType.OPENAI) from e
|
||||
raise
|
||||
|
||||
def list_models(self) -> list[ModelInfo]:
|
||||
return self._models.copy()
|
||||
|
||||
def validate_config(self) -> bool:
|
||||
return bool(self.client.api_key)
|
||||
|
||||
def get_default_model(self) -> str:
|
||||
return "gpt-4o-mini"
|
||||
|
||||
response = self.client.chat.completions.create(**params)
|
||||
choice = response.choices[0]
|
||||
|
||||
tool_calls = None
|
||||
if choice.message.tool_calls:
|
||||
tool_calls = [
|
||||
ToolCall(
|
||||
id=tc.id or "",
|
||||
name=tc.function.name,
|
||||
arguments={} if not tc.function.arguments else json.loads(tc.function.arguments),
|
||||
)
|
||||
for tc in choice.message.tool_calls
|
||||
]
|
||||
|
||||
return LLMOutput(
|
||||
content=choice.message.content or "",
|
||||
tool_calls=tool_calls,
|
||||
model=response.model,
|
||||
usage={
|
||||
"prompt_tokens": response.usage.prompt_tokens,
|
||||
"completion_tokens": response.usage.completion_tokens,
|
||||
"total_tokens": response.usage.total_tokens,
|
||||
},
|
||||
stop_reason=choice.finish_reason,
|
||||
)
|
||||
except Exception as e:
|
||||
msg = str(e)
|
||||
if "401" in msg or "authentication" in msg.lower():
|
||||
raise AuthenticationError(msg, provider=ProviderType.OPENAI) from e
|
||||
if "429" in msg or "rate_limit" in msg.lower():
|
||||
raise RateLimitError(msg, provider=ProviderType.OPENAI) from e
|
||||
if "context" in msg.lower() and "length" in msg.lower():
|
||||
raise ContextLengthError(msg, provider=ProviderType.OPENAI) from e
|
||||
raise
|
||||
|
||||
def list_models(self) -> list[ModelInfo]:
|
||||
return self._models.copy()
|
||||
|
||||
def validate_config(self) -> bool:
|
||||
return bool(self.client.api_key)
|
||||
|
||||
def get_default_model(self) -> str:
|
||||
return "gpt-4o-mini"
|
||||
|
||||
@@ -251,45 +251,6 @@ function run() {
|
||||
});
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('ignores explicit Claude Code deny-wall IOC entries', () => {
|
||||
withFixture({
|
||||
'home/.claude/settings.local.json': JSON.stringify({
|
||||
permissions: {
|
||||
deny: [
|
||||
'Bash(*filev2.getsession.org*)',
|
||||
'Bash(*router_runtime.js*)',
|
||||
'Bash(*gh-token-monitor*)',
|
||||
],
|
||||
},
|
||||
}, null, 2),
|
||||
}, rootDir => {
|
||||
const homeDir = path.join(rootDir, 'home');
|
||||
const result = scanSupplyChainIocs({ rootDir, home: true, homeDir });
|
||||
assert.deepStrictEqual(result.findings, []);
|
||||
});
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('still rejects Claude Code hooks when matching IOCs also appear in deny entries', () => {
|
||||
withFixture({
|
||||
'home/.claude/settings.local.json': JSON.stringify({
|
||||
permissions: {
|
||||
deny: [
|
||||
'Bash(*router_runtime.js*)',
|
||||
],
|
||||
},
|
||||
hooks: {
|
||||
PostToolUse: [{
|
||||
hooks: [{ command: 'node ~/.claude/router_runtime.js' }],
|
||||
}],
|
||||
},
|
||||
}, null, 2),
|
||||
}, rootDir => {
|
||||
const homeDir = path.join(rootDir, 'home');
|
||||
const result = scanSupplyChainIocs({ rootDir, home: true, homeDir });
|
||||
assert.ok(result.findings.some(finding => finding.indicator === 'router_runtime.js'));
|
||||
});
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('rejects current dead-drop and import-time payload markers', () => {
|
||||
withFixture({
|
||||
'.vscode/tasks.json': JSON.stringify({
|
||||
|
||||
@@ -99,50 +99,6 @@ function run() {
|
||||
assert.match(result.stderr, /pull_request\.head\.sha/);
|
||||
})) passed++; else failed++;
|
||||
|
||||
// `refs/pull/<N>/{head,merge}` under `pull_request_target` is the canonical
|
||||
// privilege-escalation pattern that the standard `github.event.pull_request.head.*`
|
||||
// expression check did not cover. Either form pulls attacker-controlled code
|
||||
// into a privileged workflow.
|
||||
|
||||
if (test('rejects pull_request_target checkout fetching refs/pull/N/merge', () => {
|
||||
const result = runValidator({
|
||||
'unsafe-pr-target-merge-ref.yml': `name: Unsafe\non:\n pull_request_target:\n types: [opened]\njobs:\n inspect:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n with:\n ref: refs/pull/\${{ github.event.pull_request.number }}/merge\n persist-credentials: false\n`,
|
||||
});
|
||||
assert.notStrictEqual(result.status, 0, 'Expected validator to fail on refs/pull/N/merge under pull_request_target');
|
||||
assert.match(result.stderr, /pull_request_target must not checkout an untrusted pull_request head ref/);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('rejects pull_request_target checkout fetching hardcoded refs/pull/N/head', () => {
|
||||
const result = runValidator({
|
||||
'unsafe-pr-target-head-ref.yml': `name: Unsafe\non:\n pull_request_target:\njobs:\n inspect:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n with:\n ref: refs/pull/123/head\n persist-credentials: false\n`,
|
||||
});
|
||||
assert.notStrictEqual(result.status, 0, 'Expected validator to fail on hardcoded refs/pull/N/head');
|
||||
assert.match(result.stderr, /pull_request_target must not checkout an untrusted pull_request head ref/);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('allows pull_request_target checkout of the base ref (no with.ref)', () => {
|
||||
const result = runValidator({
|
||||
'safe-pr-target-base.yml': `name: Safe\non:\n pull_request_target:\njobs:\n inspect:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n with:\n persist-credentials: false\n - run: echo inspecting base\n`,
|
||||
});
|
||||
assert.strictEqual(result.status, 0, result.stderr || result.stdout);
|
||||
})) passed++; else failed++;
|
||||
|
||||
// When a checkout step matches both the expression-based rule
|
||||
// (`github.event.pull_request.head.sha`) and the refPattern fallback
|
||||
// (`refs/pull/...`), only one violation should be emitted — the
|
||||
// expression match is the more specific signal and printing both would
|
||||
// duplicate an otherwise identical ERROR line.
|
||||
|
||||
if (test('emits a single violation when both expressionPattern and refPattern match the same step', () => {
|
||||
const result = runValidator({
|
||||
'unsafe-pr-target-both.yml': `name: Unsafe\non:\n pull_request_target:\njobs:\n inspect:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n with:\n ref: refs/pull/\${{ github.event.pull_request.head.sha }}/merge\n persist-credentials: false\n`,
|
||||
});
|
||||
assert.notStrictEqual(result.status, 0, 'Expected validator to fail');
|
||||
// Count ERROR: lines for this rule's description. Should be exactly 1.
|
||||
const matches = (result.stderr || '').match(/ERROR:.*pull_request_target must not checkout an untrusted pull_request head ref/g) || [];
|
||||
assert.strictEqual(matches.length, 1, `Expected exactly 1 violation, got ${matches.length}: ${result.stderr}`);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('rejects shared cache use in pull_request_target workflows', () => {
|
||||
const result = runValidator({
|
||||
'unsafe-pr-target-cache.yml': `name: Unsafe\non:\n pull_request_target:\n branches: [main]\njobs:\n inspect:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/cache@v5\n with:\n path: ~/.npm\n key: cache\n - run: echo inspect\n`,
|
||||
@@ -199,72 +155,14 @@ function run() {
|
||||
assert.strictEqual(result.status, 0, result.stderr || result.stdout);
|
||||
})) passed++; else failed++;
|
||||
|
||||
// `permissions: write-all` is GitHub Actions' shorthand for granting every
|
||||
// scope write access. The named-scope pattern only catches `contents: write`,
|
||||
// `issues: write`, etc., so workflows that opt into write-all were silently
|
||||
// exempted from the persist-credentials gate (the lifecycle-script gate
|
||||
// already fires unconditionally for every workflow). The tests below
|
||||
// exercise the persist-credentials path specifically — that's the gate the
|
||||
// WRITE_ALL_PATTERN OR-clause newly activates.
|
||||
|
||||
if (test('rejects checkout credential persistence in workflows with permissions: write-all', () => {
|
||||
const result = runValidator({
|
||||
'unsafe-write-all-checkout.yml': `name: Unsafe\non:\n workflow_dispatch:\npermissions: write-all\njobs:\n release:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - run: npm ci --ignore-scripts\n`,
|
||||
});
|
||||
assert.notStrictEqual(result.status, 0, 'Expected validator to fail on write-all + credential-persisting checkout');
|
||||
assert.match(result.stderr, /write permissions must disable checkout credential persistence/);
|
||||
})) passed++; else failed++;
|
||||
|
||||
// Quoted YAML forms (`"write-all"` and `'write-all'`) are valid YAML for the
|
||||
// same scalar value. Verify the WRITE_ALL_PATTERN regex covers them — without
|
||||
// the quote markers it silently slips the same persist-credentials gate.
|
||||
|
||||
if (test('rejects double-quoted permissions: "write-all"', () => {
|
||||
const result = runValidator({
|
||||
'unsafe-write-all-double.yml': `name: Unsafe\non:\n workflow_dispatch:\npermissions: "write-all"\njobs:\n release:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - run: npm ci --ignore-scripts\n`,
|
||||
});
|
||||
assert.notStrictEqual(result.status, 0, 'Expected validator to fail on quoted write-all + credential-persisting checkout');
|
||||
assert.match(result.stderr, /write permissions must disable checkout credential persistence/);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('rejects single-quoted permissions: \'write-all\'', () => {
|
||||
const result = runValidator({
|
||||
'unsafe-write-all-single.yml': `name: Unsafe\non:\n workflow_dispatch:\npermissions: 'write-all'\njobs:\n release:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - run: npm ci --ignore-scripts\n`,
|
||||
});
|
||||
assert.notStrictEqual(result.status, 0, 'Expected validator to fail on single-quoted write-all + credential-persisting checkout');
|
||||
assert.match(result.stderr, /write permissions must disable checkout credential persistence/);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('allows compliant workflow with permissions: write-all (persist-credentials: false)', () => {
|
||||
const result = runValidator({
|
||||
'safe-write-all.yml': `name: Safe\non:\n workflow_dispatch:\npermissions: write-all\njobs:\n release:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n with:\n persist-credentials: false\n - run: npm ci --ignore-scripts\n`,
|
||||
});
|
||||
assert.strictEqual(result.status, 0, result.stderr || result.stdout);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('rejects actions/cache in workflows with id-token write', () => {
|
||||
const result = runValidator({
|
||||
'unsafe-oidc-cache.yml': `name: Unsafe\non:\n push:\npermissions:\n contents: read\njobs:\n release:\n runs-on: ubuntu-latest\n permissions:\n contents: read\n id-token: write\n steps:\n - uses: actions/cache@v5\n with:\n path: ~/.npm\n key: cache\n`,
|
||||
'unsafe-oidc-cache.yml': `name: Unsafe\non:\n push:\npermissions:\n contents: read\n id-token: write\njobs:\n release:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/cache@v5\n with:\n path: ~/.npm\n key: cache\n`,
|
||||
});
|
||||
assert.notStrictEqual(result.status, 0, 'Expected validator to fail on id-token workflow cache use');
|
||||
assert.match(result.stderr, /id-token: write must not restore or save shared dependency caches/);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('rejects workflow-scoped id-token write', () => {
|
||||
const result = runValidator({
|
||||
'unsafe-workflow-oidc.yml': `name: Unsafe\non:\n push:\npermissions:\n contents: read\n id-token: write\njobs:\n verify:\n runs-on: ubuntu-latest\n steps:\n - run: npm ci --ignore-scripts\n`,
|
||||
});
|
||||
assert.notStrictEqual(result.status, 0, 'Expected validator to fail on workflow-level id-token write');
|
||||
assert.match(result.stderr, /id-token: write must be scoped to a publish-only job/);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('allows job-scoped id-token for publish-only jobs', () => {
|
||||
const result = runValidator({
|
||||
'safe-publish-oidc.yml': `name: Safe\non:\n push:\npermissions:\n contents: read\njobs:\n publish:\n runs-on: ubuntu-latest\n permissions:\n contents: write\n id-token: write\n steps:\n - run: npm publish package.tgz --access public --provenance\n`,
|
||||
});
|
||||
assert.strictEqual(result.status, 0, result.stderr || result.stdout);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('rejects npm audit without registry signature verification', () => {
|
||||
const result = runValidator({
|
||||
'unsafe-audit.yml': `name: Unsafe\non:\n push:\njobs:\n audit:\n runs-on: ubuntu-latest\n steps:\n - run: npm audit --audit-level=high\n`,
|
||||
|
||||
@@ -52,7 +52,6 @@ const expectedReleaseFiles = [
|
||||
'quickstart.md',
|
||||
'preview-pack-manifest.md',
|
||||
'publication-readiness.md',
|
||||
'release-name-plugin-publication-checklist-2026-05-18.md',
|
||||
];
|
||||
|
||||
test('release candidate directory includes the public launch pack', () => {
|
||||
@@ -175,7 +174,6 @@ test('preview pack manifest assembles release, Hermes, and publication gates', (
|
||||
'scripts/preview-pack-smoke.js',
|
||||
'docs/releases/2.0.0-rc.1/publication-readiness.md',
|
||||
'docs/releases/2.0.0-rc.1/naming-and-publication-matrix.md',
|
||||
'docs/releases/2.0.0-rc.1/release-name-plugin-publication-checklist-2026-05-18.md',
|
||||
]) {
|
||||
assert.ok(manifest.includes(artifact), `preview pack manifest missing ${artifact}`);
|
||||
}
|
||||
@@ -231,7 +229,6 @@ test('launch checklist records the ecc2 alpha version policy', () => {
|
||||
test('publication readiness checklist gates public release actions on evidence', () => {
|
||||
const source = read('docs/releases/2.0.0-rc.1/publication-readiness.md');
|
||||
const may15Evidence = read('docs/releases/2.0.0-rc.1/publication-evidence-2026-05-15.md');
|
||||
const discussionPlaybook = read('docs/architecture/discussion-response-playbook.md');
|
||||
|
||||
for (const section of [
|
||||
'## Release Identity Matrix',
|
||||
@@ -290,64 +287,14 @@ test('publication readiness checklist gates public release actions on evidence',
|
||||
assert.ok(may15Evidence.includes('Plugin Directory publishing is still blocked'));
|
||||
assert.ok(may15Evidence.includes('announcementGate.ready === true'));
|
||||
assert.ok(source.includes('ECC-Tools #73 added announcementGate'));
|
||||
assert.ok(source.includes('do not claim official Plugin Directory listing before OpenAI submission evidence'));
|
||||
assert.ok(source.includes('release-name-plugin-publication-checklist-2026-05-18.md'));
|
||||
assert.ok(source.includes('Release name and plugin publication checklist'));
|
||||
assert.ok(source.includes('official Plugin Directory publishing and self-serve management are documented as coming soon'));
|
||||
assert.ok(may15Evidence.includes('| Trunk discussions | GraphQL discussion count and maintainer-touch sweep | 58 total discussions;'));
|
||||
assert.ok(source.includes('platform audit sampled 58 trunk discussions'));
|
||||
assert.ok(source.includes('0 needing maintainer touch'));
|
||||
assert.ok(source.includes('discussion-response-playbook.md'));
|
||||
for (const expected of [
|
||||
'Public Support',
|
||||
'Maintainer Coordination',
|
||||
'Stale Or Concluded',
|
||||
'Release Announcement',
|
||||
'Security Escalation',
|
||||
'classified as informational',
|
||||
]) {
|
||||
assert.ok(discussionPlaybook.includes(expected), `discussion playbook missing ${expected}`);
|
||||
}
|
||||
assert.ok(source.includes('58 trunk discussions, 0 without maintainer touch'));
|
||||
assert.ok(may15Evidence.includes('env -u GITHUB_TOKEN'));
|
||||
assert.ok(may15Evidence.includes('ITO-44'));
|
||||
assert.ok(may15Evidence.includes('0 open PRs, 0 open issues'));
|
||||
});
|
||||
|
||||
test('release name and plugin publication checklist freezes rc.1 surfaces', () => {
|
||||
const checklist = read(
|
||||
'docs/releases/2.0.0-rc.1/release-name-plugin-publication-checklist-2026-05-18.md'
|
||||
);
|
||||
const launchChecklist = read('docs/releases/2.0.0-rc.1/launch-checklist.md');
|
||||
const referenceArchitecture = read('docs/ECC-2.0-REFERENCE-ARCHITECTURE.md');
|
||||
|
||||
for (const value of [
|
||||
'Everything Claude Code (ECC)',
|
||||
'`affaan-m/everything-claude-code`',
|
||||
'`ecc-universal`',
|
||||
'`ecc` on npm is occupied',
|
||||
'`@affaan-m/ecc` is unclaimed on npm',
|
||||
'Claude plugin',
|
||||
'Codex plugin',
|
||||
'do not claim official directory listing until OpenAI publishing path is available',
|
||||
'Do not rename the repo or package until rc.1 is published',
|
||||
'Do not announce billing, Marketplace, or native payments',
|
||||
]) {
|
||||
assert.ok(checklist.includes(value), `release name/plugin checklist missing ${value}`);
|
||||
}
|
||||
|
||||
for (const command of [
|
||||
'claude plugin validate .claude-plugin/plugin.json',
|
||||
'claude plugin tag .claude-plugin --dry-run',
|
||||
'codex plugin marketplace add --help',
|
||||
'npm publish --tag next --dry-run',
|
||||
'npm run preview-pack:smoke',
|
||||
]) {
|
||||
assert.ok(checklist.includes(command), `release name/plugin checklist missing command ${command}`);
|
||||
}
|
||||
|
||||
assert.ok(launchChecklist.includes('release-name-plugin-publication-checklist-2026-05-18.md'));
|
||||
assert.ok(referenceArchitecture.includes('Keep the release/name/plugin publication checklist current'));
|
||||
});
|
||||
|
||||
test('release checklist and roadmap link to publication readiness evidence gate', () => {
|
||||
const launchChecklist = read('docs/releases/2.0.0-rc.1/launch-checklist.md');
|
||||
const roadmap = read('docs/ECC-2.0-GA-ROADMAP.md');
|
||||
|
||||
@@ -75,7 +75,7 @@ function readAudit(root) {
|
||||
|
||||
function runMonitor(options = {}) {
|
||||
if (!PYTHON) {
|
||||
throw new Error('Python 3 was expected to be available for this test run');
|
||||
throw new Error('Python 3 is required for insaits-security-monitor.py tests');
|
||||
}
|
||||
|
||||
const tempDir = createTempDir();
|
||||
@@ -119,12 +119,6 @@ function test(name, fn) {
|
||||
function runTests() {
|
||||
console.log('\n=== Testing insaits-security-monitor.py ===\n');
|
||||
|
||||
if (!PYTHON) {
|
||||
console.log(' SKIP Python 3 not found; insaits-security-monitor.py subprocess tests require a Python runtime');
|
||||
console.log('\nResults: Passed: 0, Failed: 0');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
|
||||
@@ -955,75 +955,6 @@ async function runTests() {
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (await asyncTest('treats HTTP 406 probe responses as healthy reachable Streamable HTTP MCP servers', async () => {
|
||||
const tempDir = createTempDir();
|
||||
const configPath = path.join(tempDir, 'claude.json');
|
||||
const statePath = path.join(tempDir, 'mcp-health.json');
|
||||
const serverScript = path.join(tempDir, 'http-406-server.js');
|
||||
const portFile = path.join(tempDir, 'server-port.txt');
|
||||
|
||||
fs.writeFileSync(
|
||||
serverScript,
|
||||
[
|
||||
"const fs = require('fs');",
|
||||
"const http = require('http');",
|
||||
"const portFile = process.argv[2];",
|
||||
"const server = http.createServer((req, res) => {",
|
||||
" if (String(req.headers.accept || '').includes('text/event-stream')) {",
|
||||
" res.writeHead(200, { 'Content-Type': 'text/event-stream' });",
|
||||
" res.end();",
|
||||
" return;",
|
||||
" }",
|
||||
" res.writeHead(406, { 'Content-Type': 'application/json' });",
|
||||
" res.end(JSON.stringify({ error: 'missing Accept: text/event-stream' }));",
|
||||
"});",
|
||||
"server.listen(0, '127.0.0.1', () => {",
|
||||
" fs.writeFileSync(portFile, String(server.address().port));",
|
||||
"});",
|
||||
"setInterval(() => {}, 1000);"
|
||||
].join('\n')
|
||||
);
|
||||
|
||||
const serverProcess = spawn(process.execPath, [serverScript, portFile], {
|
||||
stdio: 'ignore'
|
||||
});
|
||||
|
||||
try {
|
||||
const port = waitForFile(portFile).trim();
|
||||
await waitForHttpReady(`http://127.0.0.1:${port}/mcp`);
|
||||
|
||||
writeConfig(configPath, {
|
||||
mcpServers: {
|
||||
streamable: {
|
||||
type: 'http',
|
||||
url: `http://127.0.0.1:${port}/mcp`
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const input = { tool_name: 'mcp__streamable__initialize', tool_input: {} };
|
||||
const result = runHook(input, {
|
||||
CLAUDE_HOOK_EVENT_NAME: 'PreToolUse',
|
||||
ECC_MCP_CONFIG_PATH: configPath,
|
||||
ECC_MCP_HEALTH_STATE_PATH: statePath,
|
||||
ECC_MCP_HEALTH_TIMEOUT_MS: '2000'
|
||||
});
|
||||
|
||||
assert.strictEqual(
|
||||
result.code,
|
||||
0,
|
||||
`Expected HTTP 406 probe to be treated as healthy: ${hookFailureDetails(result, statePath)}`
|
||||
);
|
||||
assert.strictEqual(result.stdout.trim(), JSON.stringify(input), 'Expected original JSON on stdout');
|
||||
|
||||
const state = readState(statePath);
|
||||
assert.strictEqual(state.servers.streamable.status, 'healthy', 'Expected Streamable HTTP MCP server to be marked healthy');
|
||||
} finally {
|
||||
serverProcess.kill('SIGTERM');
|
||||
cleanupTempDir(tempDir);
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
// Windows-only: child_process.spawn cannot resolve .cmd/.bat shims for
|
||||
// bare PATH commands without an extension, and Node 18.20+/20.12+ refuse
|
||||
// to spawn .cmd targets without `shell: true` (CVE-2024-27980). The probe
|
||||
|
||||
@@ -52,29 +52,6 @@ function runTests() {
|
||||
assert.deepStrictEqual(parsed.languages, []);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('parses --locale argument', () => {
|
||||
const parsed = parseInstallArgs([
|
||||
'node',
|
||||
'scripts/install-apply.js',
|
||||
'--locale', 'ja'
|
||||
]);
|
||||
|
||||
assert.strictEqual(parsed.locale, 'ja');
|
||||
assert.deepStrictEqual(parsed.languages, []);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('requires a --locale value', () => {
|
||||
assert.throws(
|
||||
() => parseInstallArgs([
|
||||
'node',
|
||||
'scripts/install-apply.js',
|
||||
'--locale',
|
||||
'--dry-run'
|
||||
]),
|
||||
/Missing value for --locale/
|
||||
);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('normalizes legacy language installs into a canonical request', () => {
|
||||
const request = normalizeInstallRequest({
|
||||
target: 'claude',
|
||||
@@ -90,69 +67,6 @@ function runTests() {
|
||||
assert.strictEqual(request.profileId, null);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('normalizes locale-only installs as manifest component requests', () => {
|
||||
const request = normalizeInstallRequest({
|
||||
target: 'claude',
|
||||
profileId: null,
|
||||
moduleIds: [],
|
||||
includeComponentIds: [],
|
||||
excludeComponentIds: [],
|
||||
languages: [],
|
||||
locale: 'ja',
|
||||
});
|
||||
|
||||
assert.strictEqual(request.mode, 'manifest');
|
||||
assert.strictEqual(request.target, 'claude');
|
||||
assert.deepStrictEqual(request.includeComponentIds, ['locale:ja']);
|
||||
assert.deepStrictEqual(request.legacyLanguages, []);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('allows legacy language installs to include a locale component', () => {
|
||||
const request = normalizeInstallRequest({
|
||||
target: 'claude',
|
||||
profileId: null,
|
||||
moduleIds: [],
|
||||
includeComponentIds: [],
|
||||
excludeComponentIds: [],
|
||||
languages: ['typescript'],
|
||||
locale: 'ja-JP',
|
||||
});
|
||||
|
||||
assert.strictEqual(request.mode, 'legacy-compat');
|
||||
assert.deepStrictEqual(request.legacyLanguages, ['typescript']);
|
||||
assert.deepStrictEqual(request.includeComponentIds, ['locale:ja']);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('rejects unsupported locale codes', () => {
|
||||
assert.throws(
|
||||
() => normalizeInstallRequest({
|
||||
target: 'claude',
|
||||
profileId: null,
|
||||
moduleIds: [],
|
||||
includeComponentIds: [],
|
||||
excludeComponentIds: [],
|
||||
languages: [],
|
||||
locale: 'fr',
|
||||
}),
|
||||
/Unsupported locale/
|
||||
);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('rejects --locale for non-Claude targets', () => {
|
||||
assert.throws(
|
||||
() => normalizeInstallRequest({
|
||||
target: 'cursor',
|
||||
profileId: null,
|
||||
moduleIds: [],
|
||||
includeComponentIds: [],
|
||||
excludeComponentIds: [],
|
||||
languages: [],
|
||||
locale: 'ja',
|
||||
}),
|
||||
/--locale can only be used with --target claude/
|
||||
);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('normalizes manifest installs into a canonical request', () => {
|
||||
const request = normalizeInstallRequest({
|
||||
target: 'cursor',
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
/**
|
||||
* Tests for --locale translated docs installs.
|
||||
*/
|
||||
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const { execFileSync } = require('child_process');
|
||||
|
||||
const {
|
||||
listInstallComponents,
|
||||
resolveInstallPlan,
|
||||
} = require('../../scripts/lib/install-manifests');
|
||||
|
||||
function normalizePlanPath(value) {
|
||||
return String(value || '').replace(/\\/g, '/');
|
||||
}
|
||||
|
||||
function runInstallApply(args, options = {}) {
|
||||
const scriptPath = path.join(__dirname, '..', '..', 'scripts', 'install-apply.js');
|
||||
return execFileSync('node', [scriptPath, ...args], {
|
||||
cwd: options.cwd || process.cwd(),
|
||||
env: { ...process.env, ...(options.env || {}) },
|
||||
encoding: 'utf8',
|
||||
maxBuffer: 16 * 1024 * 1024,
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
});
|
||||
}
|
||||
|
||||
function test(name, fn) {
|
||||
try {
|
||||
fn();
|
||||
console.log(` \u2713 ${name}`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.log(` \u2717 ${name}`);
|
||||
console.log(` Error: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
console.log('\n=== Testing --locale translated docs installs ===\n');
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
if (test('component catalog includes locale entries', () => {
|
||||
const components = listInstallComponents({ family: 'locale' });
|
||||
assert.ok(components.some(component => component.id === 'locale:ja'));
|
||||
assert.ok(components.some(component => component.id === 'locale:zh-cn'));
|
||||
assert.ok(components.every(component => component.family === 'locale'));
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('locale component resolves to the translated docs module', () => {
|
||||
const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'locale-plan-'));
|
||||
try {
|
||||
const plan = resolveInstallPlan({
|
||||
includeComponentIds: ['locale:ja'],
|
||||
target: 'claude',
|
||||
homeDir,
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(plan.selectedModuleIds, ['docs-ja-jp']);
|
||||
assert.ok(
|
||||
plan.operations.some(operation => (
|
||||
normalizePlanPath(operation.sourceRelativePath) === 'docs/ja-JP'
|
||||
&& normalizePlanPath(operation.destinationPath).endsWith('/.claude/docs/ja-JP')
|
||||
)),
|
||||
'Should map docs/ja-JP to ~/.claude/docs/ja-JP'
|
||||
);
|
||||
} finally {
|
||||
fs.rmSync(homeDir, { recursive: true, force: true });
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('end-to-end: --locale ja dry-run includes docs-ja-jp operations', () => {
|
||||
const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'locale-dry-run-'));
|
||||
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'locale-dry-run-project-'));
|
||||
|
||||
try {
|
||||
const output = runInstallApply([
|
||||
'--locale', 'ja',
|
||||
'--dry-run',
|
||||
'--json',
|
||||
], {
|
||||
cwd: projectDir,
|
||||
env: { HOME: homeDir },
|
||||
});
|
||||
const json = JSON.parse(output);
|
||||
|
||||
assert.strictEqual(json.plan.mode, 'manifest');
|
||||
assert.deepStrictEqual(json.plan.includedComponentIds, ['locale:ja']);
|
||||
assert.deepStrictEqual(json.plan.selectedModuleIds, ['docs-ja-jp']);
|
||||
assert.ok(
|
||||
json.plan.operations.some(operation => (
|
||||
normalizePlanPath(operation.sourceRelativePath) === 'docs/ja-JP/README.md'
|
||||
&& normalizePlanPath(operation.destinationPath).endsWith('/.claude/docs/ja-JP/README.md')
|
||||
)),
|
||||
'Should copy translated README into ~/.claude/docs/ja-JP'
|
||||
);
|
||||
} finally {
|
||||
fs.rmSync(homeDir, { recursive: true, force: true });
|
||||
fs.rmSync(projectDir, { recursive: true, force: true });
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('end-to-end: legacy language plus --locale keeps legacy install and docs', () => {
|
||||
const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'locale-legacy-dry-run-'));
|
||||
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'locale-legacy-dry-run-project-'));
|
||||
|
||||
try {
|
||||
const output = runInstallApply([
|
||||
'typescript',
|
||||
'--locale', 'ja',
|
||||
'--dry-run',
|
||||
'--json',
|
||||
], {
|
||||
cwd: projectDir,
|
||||
env: { HOME: homeDir },
|
||||
});
|
||||
const json = JSON.parse(output);
|
||||
|
||||
assert.strictEqual(json.plan.mode, 'legacy-compat');
|
||||
assert.deepStrictEqual(json.plan.legacyLanguages, ['typescript']);
|
||||
assert.ok(json.plan.includedComponentIds.includes('locale:ja'));
|
||||
assert.ok(json.plan.selectedModuleIds.includes('framework-language'));
|
||||
assert.ok(json.plan.selectedModuleIds.includes('docs-ja-jp'));
|
||||
} finally {
|
||||
fs.rmSync(homeDir, { recursive: true, force: true });
|
||||
fs.rmSync(projectDir, { recursive: true, force: true });
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('end-to-end: --locale ja installs translated docs side-by-side', () => {
|
||||
const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'locale-install-'));
|
||||
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'locale-install-project-'));
|
||||
|
||||
try {
|
||||
runInstallApply([
|
||||
'--locale', 'ja',
|
||||
], {
|
||||
cwd: projectDir,
|
||||
env: { HOME: homeDir },
|
||||
});
|
||||
|
||||
const claudeRoot = path.join(homeDir, '.claude');
|
||||
assert.ok(
|
||||
fs.existsSync(path.join(claudeRoot, 'docs', 'ja-JP', 'README.md')),
|
||||
'Should install Japanese README under docs/ja-JP'
|
||||
);
|
||||
assert.ok(
|
||||
!fs.existsSync(path.join(claudeRoot, 'skills', 'ecc', 'configure-ecc', 'SKILL.md')),
|
||||
'Locale-only install should not install English skills'
|
||||
);
|
||||
|
||||
const statePath = path.join(claudeRoot, 'ecc', 'install-state.json');
|
||||
const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
|
||||
assert.deepStrictEqual(state.request.includeComponents, ['locale:ja']);
|
||||
assert.deepStrictEqual(state.resolution.selectedModules, ['docs-ja-jp']);
|
||||
} finally {
|
||||
fs.rmSync(homeDir, { recursive: true, force: true });
|
||||
fs.rmSync(projectDir, { recursive: true, force: true });
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`);
|
||||
process.exit(failed > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
runTests();
|
||||
@@ -135,130 +135,6 @@ function runTests() {
|
||||
passed++;
|
||||
else failed++;
|
||||
|
||||
// Concurrency contract: two processes writing to the same session
|
||||
// bridge must not throw ENOENT and must never leave a corrupt JSON
|
||||
// file behind. The previous implementation used a fixed `${target}.tmp`
|
||||
// suffix; with concurrent writers it raced over a shared tmp path,
|
||||
// producing both ENOENT on rename and (occasionally) a half-written
|
||||
// payload on the destination.
|
||||
//
|
||||
// This test exercises the atomic-rename primitive only — it does NOT
|
||||
// attempt to defend against the read-modify-write race in callers,
|
||||
// which is a separate concern. Each subprocess writes its own
|
||||
// independent payload N times; we assert (a) every process exits 0
|
||||
// (no ENOENT bubbled up) and (b) the final file is always parseable
|
||||
// JSON whose contents match one of the two writers' last payloads.
|
||||
|
||||
if (
|
||||
test('concurrent writeBridgeAtomic does not throw ENOENT or corrupt the bridge file', () => {
|
||||
// Spawn two child processes that BOTH stay alive at the same time
|
||||
// and call writeBridgeAtomic in a tight loop. `spawnSync` would
|
||||
// run them sequentially (blocking on each), which would never
|
||||
// exercise the race the fix targets. Instead a sync runner script
|
||||
// launches both as async `spawn` children inside its own process,
|
||||
// waits for both to exit, and reports their statuses on stdout —
|
||||
// and the test calls *that* runner via `spawnSync`. The runner is
|
||||
// the only place that needs the event loop.
|
||||
const { spawnSync } = require('child_process');
|
||||
const path = require('path');
|
||||
const testId = `test-bridge-race-${Date.now()}-${process.pid}`;
|
||||
const writerPath = path.join(__dirname, '..', '__tmp_bridge_writer.js');
|
||||
const runnerPath = path.join(__dirname, '..', '__tmp_bridge_race_runner.js');
|
||||
const bridgeLib = path.join(__dirname, '..', '..', 'scripts', 'lib', 'session-bridge');
|
||||
fs.writeFileSync(
|
||||
writerPath,
|
||||
[
|
||||
"const { writeBridgeAtomic } = require(" + JSON.stringify(bridgeLib) + ");",
|
||||
"const [, , sid, tag] = process.argv;",
|
||||
"for (let i = 0; i < 200; i++) {",
|
||||
" writeBridgeAtomic(sid, { writer: tag, i });",
|
||||
"}",
|
||||
].join('\n'),
|
||||
'utf8'
|
||||
);
|
||||
fs.writeFileSync(
|
||||
runnerPath,
|
||||
[
|
||||
"'use strict';",
|
||||
"const { spawn } = require('child_process');",
|
||||
"const [, , writerPath, sid] = process.argv;",
|
||||
"const c1 = spawn(process.execPath, [writerPath, sid, 'A'], { stdio: ['ignore','pipe','pipe'] });",
|
||||
"const c2 = spawn(process.execPath, [writerPath, sid, 'B'], { stdio: ['ignore','pipe','pipe'] });",
|
||||
"const exits = {};",
|
||||
"const stderrs = { A: '', B: '' };",
|
||||
"c1.stderr.on('data', chunk => { stderrs.A += chunk.toString(); });",
|
||||
"c2.stderr.on('data', chunk => { stderrs.B += chunk.toString(); });",
|
||||
"let done = 0;",
|
||||
"function onExit(tag) { return function(code) { exits[tag] = code; if (++done === 2) finish(); }; }",
|
||||
"c1.on('exit', onExit('A'));",
|
||||
"c2.on('exit', onExit('B'));",
|
||||
"function finish() {",
|
||||
" process.stdout.write(JSON.stringify({ exits, stderrs }));",
|
||||
" process.exit(0);",
|
||||
"}",
|
||||
].join('\n'),
|
||||
'utf8'
|
||||
);
|
||||
try {
|
||||
const result = spawnSync('node', [runnerPath, writerPath, testId], { encoding: 'utf8' });
|
||||
assert.strictEqual(result.status, 0,
|
||||
`race runner should exit 0, got ${result.status}: ${result.stderr}`);
|
||||
const parsed = JSON.parse(result.stdout);
|
||||
assert.strictEqual(parsed.exits.A, 0,
|
||||
`writer A should exit 0 (no ENOENT), got ${parsed.exits.A}: ${parsed.stderrs.A}`);
|
||||
assert.strictEqual(parsed.exits.B, 0,
|
||||
`writer B should exit 0 (no ENOENT), got ${parsed.exits.B}: ${parsed.stderrs.B}`);
|
||||
// Final file must be parseable JSON and belong to one of the writers.
|
||||
const final = readBridge(testId);
|
||||
assert.ok(final && typeof final === 'object',
|
||||
`expected parseable JSON object, got: ${JSON.stringify(final)}`);
|
||||
assert.ok(final.writer === 'A' || final.writer === 'B',
|
||||
`expected last-writer-wins payload, got: ${JSON.stringify(final)}`);
|
||||
} finally {
|
||||
try { fs.unlinkSync(getBridgePath(testId)); } catch { /* ignore */ }
|
||||
try { fs.unlinkSync(writerPath); } catch { /* ignore */ }
|
||||
try { fs.unlinkSync(runnerPath); } catch { /* ignore */ }
|
||||
}
|
||||
})
|
||||
)
|
||||
passed++;
|
||||
else failed++;
|
||||
|
||||
if (
|
||||
test('writeBridgeAtomic cleans up its tmp file on renameSync failure', () => {
|
||||
// Trigger renameSync failure by passing a sessionId whose path is
|
||||
// already a directory. The tmp file exists at this point; the fix
|
||||
// must not leak it behind.
|
||||
const path = require('path');
|
||||
const testId = `test-bridge-cleanup-${Date.now()}-${process.pid}`;
|
||||
const target = getBridgePath(testId);
|
||||
const os = require('os');
|
||||
const tmpDir = os.tmpdir();
|
||||
// Plant a directory at the target path so renameSync (target.tmp → target) fails.
|
||||
fs.mkdirSync(target);
|
||||
try {
|
||||
assert.throws(
|
||||
() => writeBridgeAtomic(testId, { x: 1 }),
|
||||
// renameSync of a regular file onto an existing directory throws
|
||||
// EISDIR on Linux, EPERM on macOS, ENOTDIR on some BSDs. Accept
|
||||
// any of those so the test stays portable across CI runners.
|
||||
/EISDIR|EPERM|ENOTDIR|ENOENT/,
|
||||
'expected rename failure to surface'
|
||||
);
|
||||
// Count any leaked tmp files. The pid+nonce suffix is unique per
|
||||
// call, so we look for any matching pattern under os.tmpdir().
|
||||
const prefix = path.basename(target) + '.' + process.pid + '.';
|
||||
const leaked = fs.readdirSync(tmpDir).filter(f => f.startsWith(prefix) && f.endsWith('.tmp'));
|
||||
assert.strictEqual(leaked.length, 0,
|
||||
`expected no leaked tmp files after rename failure, found: ${leaked.join(', ')}`);
|
||||
} finally {
|
||||
try { fs.rmdirSync(target); } catch { /* ignore */ }
|
||||
}
|
||||
})
|
||||
)
|
||||
passed++;
|
||||
else failed++;
|
||||
|
||||
// resolveSessionId tests
|
||||
console.log('\nresolveSessionId:');
|
||||
|
||||
|
||||
@@ -9,10 +9,7 @@ const path = require('path');
|
||||
const { execFileSync, spawnSync } = require('child_process');
|
||||
|
||||
const SCRIPT = path.join(__dirname, '..', '..', 'scripts', 'discussion-audit.js');
|
||||
const {
|
||||
DISCUSSION_ENABLED_QUERY,
|
||||
DISCUSSION_QUERY
|
||||
} = require(path.join(__dirname, '..', '..', 'scripts', 'lib', 'github-discussions'));
|
||||
const { DISCUSSION_QUERY } = require(path.join(__dirname, '..', '..', 'scripts', 'lib', 'github-discussions'));
|
||||
|
||||
function createTempDir(prefix) {
|
||||
return fs.mkdtempSync(path.join(os.tmpdir(), prefix));
|
||||
@@ -26,10 +23,6 @@ function discussionGhKey(owner, name, first = 100) {
|
||||
return `api graphql -f owner=${owner} -f name=${name} -F first=${first} -f query=${DISCUSSION_QUERY}`;
|
||||
}
|
||||
|
||||
function discussionEnabledGhKey(owner, name) {
|
||||
return `api graphql -f owner=${owner} -f name=${name} -f query=${DISCUSSION_ENABLED_QUERY}`;
|
||||
}
|
||||
|
||||
function writeGhShim(rootDir, responses) {
|
||||
const shimPath = path.join(rootDir, 'gh-shim.js');
|
||||
fs.writeFileSync(shimPath, `
|
||||
@@ -102,9 +95,6 @@ function runTests() {
|
||||
|
||||
try {
|
||||
const shimPath = writeGhShim(rootDir, {
|
||||
[discussionEnabledGhKey('affaan-m', 'everything-claude-code')]: {
|
||||
data: { repository: { hasDiscussionsEnabled: true } }
|
||||
},
|
||||
[discussionGhKey('affaan-m', 'everything-claude-code')]: {
|
||||
data: {
|
||||
repository: {
|
||||
@@ -165,9 +155,6 @@ function runTests() {
|
||||
|
||||
try {
|
||||
const shimPath = writeGhShim(rootDir, {
|
||||
[discussionEnabledGhKey('affaan-m', 'everything-claude-code')]: {
|
||||
data: { repository: { hasDiscussionsEnabled: true } }
|
||||
},
|
||||
[discussionGhKey('affaan-m', 'everything-claude-code')]: {
|
||||
data: {
|
||||
repository: {
|
||||
@@ -220,9 +207,6 @@ function runTests() {
|
||||
|
||||
try {
|
||||
const shimPath = writeGhShim(rootDir, {
|
||||
[discussionEnabledGhKey('affaan-m', 'everything-claude-code')]: {
|
||||
data: { repository: { hasDiscussionsEnabled: true } }
|
||||
},
|
||||
[discussionGhKey('affaan-m', 'everything-claude-code')]: {
|
||||
data: {
|
||||
repository: {
|
||||
@@ -253,34 +237,6 @@ function runTests() {
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('passes without heavy query when discussions are disabled', () => {
|
||||
const rootDir = createTempDir('discussion-audit-disabled-');
|
||||
|
||||
try {
|
||||
const shimPath = writeGhShim(rootDir, {
|
||||
[discussionEnabledGhKey('ECC-Tools', 'ECC-website')]: {
|
||||
data: { repository: { hasDiscussionsEnabled: false } }
|
||||
}
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(run([
|
||||
'--json',
|
||||
'--repo',
|
||||
'ECC-Tools/ECC-website'
|
||||
], {
|
||||
cwd: rootDir,
|
||||
env: { ECC_GH_SHIM: shimPath }
|
||||
}));
|
||||
|
||||
assert.strictEqual(parsed.ready, true);
|
||||
assert.strictEqual(parsed.repos[0].discussions.enabled, false);
|
||||
assert.strictEqual(parsed.totals.totalDiscussions, 0);
|
||||
assert.strictEqual(parsed.totals.errors, 0);
|
||||
} finally {
|
||||
cleanup(rootDir);
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('cli help and invalid args exit cleanly', () => {
|
||||
const help = runProcess(['--help']);
|
||||
assert.strictEqual(help.status, 0);
|
||||
|
||||
@@ -64,41 +64,22 @@ function seedRepo(rootDir, overrides = {}) {
|
||||
'package-manager hardening Action outputs',
|
||||
'production Marketplace readback state',
|
||||
'eb69412',
|
||||
'Marketplace webhook provenance',
|
||||
'2859678',
|
||||
'Wrangler OAuth readback',
|
||||
'42653f9',
|
||||
'target account billing readback',
|
||||
'632e059',
|
||||
'69ca535',
|
||||
'team feedback controls',
|
||||
'e56fc1a',
|
||||
'1Password CLI authorization timed out',
|
||||
'Cloudflare API auth returned `Authentication error [code: 10000]`',
|
||||
'announcementGate',
|
||||
'ITO-55',
|
||||
'Linear live sync is current for the May 17 merge batch',
|
||||
'operator progress snapshot'
|
||||
].join('\n'),
|
||||
'docs/releases/2.0.0-rc.1/publication-readiness.md': 'Claude plugin Codex plugin release-name-plugin-publication-checklist-2026-05-18.md',
|
||||
'docs/releases/2.0.0-rc.1/publication-readiness.md': 'Claude plugin Codex plugin',
|
||||
'docs/releases/2.0.0-rc.1/naming-and-publication-matrix.md': 'Claude plugin Codex plugin npm package Publication Paths',
|
||||
'docs/releases/2.0.0-rc.1/release-name-plugin-publication-checklist-2026-05-18.md': [
|
||||
'Everything Claude Code (ECC)',
|
||||
'ecc-universal',
|
||||
'claude plugin tag .claude-plugin --dry-run',
|
||||
'codex plugin marketplace add',
|
||||
'Do not rename the repo or package until rc.1 is published'
|
||||
].join('\n'),
|
||||
'docs/releases/2.0.0-rc.1/preview-pack-manifest.md': [
|
||||
'publication-readiness.md release-notes.md quickstart.md',
|
||||
'release-name-plugin-publication-checklist-2026-05-18.md',
|
||||
'`scripts/preview-pack-smoke.js`',
|
||||
'npm run preview-pack:smoke'
|
||||
].join('\n'),
|
||||
'docs/releases/2.0.0-rc.1/release-notes.md': 'release notes',
|
||||
'docs/releases/2.0.0-rc.1/x-thread.md': 'x thread',
|
||||
'docs/releases/2.0.0-rc.1/linkedin-post.md': 'linkedin post',
|
||||
'docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-18.md': [
|
||||
'docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-15.md': [
|
||||
'This dashboard is generated by `npm run operator:dashboard`',
|
||||
'operator:dashboard',
|
||||
'Prompt-To-Artifact Checklist',
|
||||
@@ -108,12 +89,6 @@ function seedRepo(rootDir, overrides = {}) {
|
||||
'PR queue',
|
||||
'Not complete'
|
||||
].join('\n'),
|
||||
'docs/releases/2.0.0-rc.1/owner-queue-cleanup-2026-05-18.md': [
|
||||
'Owner-wide open PRs after cleanup: 0.',
|
||||
'Owner-wide open issues after cleanup: 0.',
|
||||
'Stale dependency-bot PRs closed: 24.',
|
||||
'Stale legacy payments/0EM roadmap issues closed: 72.'
|
||||
].join('\n'),
|
||||
'docs/HERMES-SETUP.md': 'Hermes setup Public Release Candidate Scope',
|
||||
'skills/hermes-imports/SKILL.md': 'Hermes imports Sanitization Checklist Do not ship raw workspace exports Output Contract',
|
||||
'docs/stale-pr-salvage-ledger.md': [
|
||||
@@ -144,14 +119,7 @@ function seedRepo(rootDir, overrides = {}) {
|
||||
].join('\n'),
|
||||
'docs/architecture/observability-readiness.md': 'observability-readiness.js',
|
||||
'docs/security/supply-chain-incident-response.md': 'TanStack Mini Shai-Hulud node-ipc scan-supply-chain-iocs.js supply-chain-advisory-sources.js',
|
||||
'docs/releases/2.0.0-rc.1/publication-evidence-2026-05-18.md': [
|
||||
'TanStack',
|
||||
'Mini Shai-Hulud',
|
||||
'Home persistence IOC scan',
|
||||
'Supply-Chain Watch',
|
||||
'npm signatures',
|
||||
'Node IPC follow-up node-ipc IOC scan'
|
||||
].join('\n'),
|
||||
'docs/releases/2.0.0-rc.1/publication-evidence-2026-05-15.md': 'TanStack Mini Shai-Hulud Node IPC follow-up node-ipc IOC scan',
|
||||
'.github/workflows/supply-chain-watch.yml': 'name: Supply-Chain Watch supply-chain-advisory-sources.js supply-chain-advisory-sources.json'
|
||||
};
|
||||
|
||||
@@ -283,22 +251,11 @@ function runTests() {
|
||||
)));
|
||||
assert.ok(report.requirements.some(item => (
|
||||
item.id === 'ecc-tools-next-level'
|
||||
&& item.gap === 'authorize Cloudflare API or 1Password CLI access, configure the target Marketplace Pro account and INTERNAL_API_SECRET, create or replay Marketplace Pro webhook state, then rerun target readback and the live announcement gate'
|
||||
&& item.gap === 'complete Marketplace purchase/webhook readback, then run the live announcement gate'
|
||||
&& item.evidence.includes('operator-visible promotion output details')
|
||||
&& item.evidence.includes('hosted promotion judge audit traces')
|
||||
&& item.evidence.includes('billing announcement preflight')
|
||||
&& item.evidence.includes('aggregate production billing KV readback')
|
||||
&& item.evidence.includes('Wrangler OAuth readback')
|
||||
&& item.evidence.includes('target-account billing readback')
|
||||
&& item.evidence.includes('provenance-aware Marketplace billing-state gates')
|
||||
&& item.evidence.includes('hosted team-learning feedback controls')
|
||||
&& item.evidence.includes('ECC-Tools Dependabot alert remediation')
|
||||
)));
|
||||
assert.ok(report.requirements.some(item => (
|
||||
item.id === 'naming-and-plugin-publication'
|
||||
&& item.artifact.includes('release-name-plugin-publication checklist')
|
||||
&& item.evidence.includes('release publication checklist')
|
||||
&& item.gap === 'real tag/push, marketplace submission, and final channel choice remain approval-gated'
|
||||
&& item.evidence.includes('production KV readback state')
|
||||
)));
|
||||
assert.ok(report.requirements.some(item => (
|
||||
item.id === 'supply-chain-local-protection'
|
||||
|
||||
@@ -9,10 +9,7 @@ const path = require('path');
|
||||
const { execFileSync, spawnSync } = require('child_process');
|
||||
|
||||
const SCRIPT = path.join(__dirname, '..', '..', 'scripts', 'platform-audit.js');
|
||||
const {
|
||||
DISCUSSION_ENABLED_QUERY,
|
||||
DISCUSSION_QUERY
|
||||
} = require(path.join(__dirname, '..', '..', 'scripts', 'lib', 'github-discussions'));
|
||||
const { DISCUSSION_QUERY } = require(path.join(__dirname, '..', '..', 'scripts', 'lib', 'github-discussions'));
|
||||
|
||||
function createTempDir(prefix) {
|
||||
return fs.mkdtempSync(path.join(os.tmpdir(), prefix));
|
||||
@@ -62,14 +59,14 @@ function seedRepo(rootDir, overrides = {}) {
|
||||
'scan-supply-chain-iocs.js',
|
||||
'supply-chain-advisory-sources.js'
|
||||
].join('\n'),
|
||||
'docs/releases/2.0.0-rc.1/publication-evidence-2026-05-18.md': [
|
||||
'docs/releases/2.0.0-rc.1/publication-evidence-2026-05-15.md': [
|
||||
'TanStack',
|
||||
'Mini Shai-Hulud',
|
||||
'Home persistence IOC scan',
|
||||
'Supply-Chain Watch',
|
||||
'npm signatures'
|
||||
'Node IPC follow-up',
|
||||
'node-ipc',
|
||||
'IOC scan'
|
||||
].join('\n'),
|
||||
'docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-18.md': [
|
||||
'docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-15.md': [
|
||||
'This dashboard is generated by `npm run operator:dashboard`',
|
||||
'Prompt-To-Artifact Checklist',
|
||||
'ITO-44',
|
||||
@@ -94,10 +91,6 @@ function discussionGhKey(owner, name, first = 100) {
|
||||
return `api graphql -f owner=${owner} -f name=${name} -F first=${first} -f query=${DISCUSSION_QUERY}`;
|
||||
}
|
||||
|
||||
function discussionEnabledGhKey(owner, name) {
|
||||
return `api graphql -f owner=${owner} -f name=${name} -f query=${DISCUSSION_ENABLED_QUERY}`;
|
||||
}
|
||||
|
||||
function writeGhShim(rootDir, responses) {
|
||||
const shimPath = path.join(rootDir, 'gh-shim.js');
|
||||
fs.writeFileSync(shimPath, `
|
||||
@@ -258,9 +251,6 @@ function runTests() {
|
||||
const shimPath = writeGhShim(projectRoot, {
|
||||
'pr list --repo affaan-m/everything-claude-code --state open --json number,title,isDraft,mergeStateStatus,updatedAt,url,author': [],
|
||||
'issue list --repo affaan-m/everything-claude-code --state open --json number,title,updatedAt,url,author,labels': [],
|
||||
[discussionEnabledGhKey('affaan-m', 'everything-claude-code')]: {
|
||||
data: { repository: { hasDiscussionsEnabled: true } }
|
||||
},
|
||||
[discussionGhKey('affaan-m', 'everything-claude-code')]: {
|
||||
data: {
|
||||
repository: {
|
||||
@@ -327,9 +317,6 @@ function runTests() {
|
||||
const shimPath = writeGhShim(projectRoot, {
|
||||
'pr list --repo affaan-m/everything-claude-code --state open --json number,title,isDraft,mergeStateStatus,updatedAt,url,author': prs,
|
||||
'issue list --repo affaan-m/everything-claude-code --state open --json number,title,updatedAt,url,author,labels': [],
|
||||
[discussionEnabledGhKey('affaan-m', 'everything-claude-code')]: {
|
||||
data: { repository: { hasDiscussionsEnabled: true } }
|
||||
},
|
||||
[discussionGhKey('affaan-m', 'everything-claude-code')]: {
|
||||
data: {
|
||||
repository: {
|
||||
@@ -377,38 +364,6 @@ function runTests() {
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('discussion-disabled repos skip the heavy discussion query', () => {
|
||||
const projectRoot = createTempDir('platform-audit-discussions-disabled-');
|
||||
|
||||
try {
|
||||
seedRepo(projectRoot);
|
||||
const shimPath = writeGhShim(projectRoot, {
|
||||
'pr list --repo ECC-Tools/ECC-website --state open --json number,title,isDraft,mergeStateStatus,updatedAt,url,author': [],
|
||||
'issue list --repo ECC-Tools/ECC-website --state open --json number,title,updatedAt,url,author,labels': [],
|
||||
[discussionEnabledGhKey('ECC-Tools', 'ECC-website')]: {
|
||||
data: { repository: { hasDiscussionsEnabled: false } }
|
||||
}
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(run([
|
||||
'--format=json',
|
||||
`--root=${projectRoot}`,
|
||||
'--repo',
|
||||
'ECC-Tools/ECC-website'
|
||||
], {
|
||||
cwd: projectRoot,
|
||||
env: { ECC_GH_SHIM: shimPath }
|
||||
}));
|
||||
|
||||
assert.strictEqual(parsed.ready, true);
|
||||
assert.strictEqual(parsed.github.repos[0].discussions.enabled, false);
|
||||
assert.strictEqual(parsed.github.repos[0].discussions.totalCount, 0);
|
||||
assert.strictEqual(parsed.github.totals.errors, 0);
|
||||
} finally {
|
||||
cleanup(projectRoot);
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('cli help and invalid args exit cleanly', () => {
|
||||
const help = runProcess(['--help']);
|
||||
assert.strictEqual(help.status, 0);
|
||||
|
||||
@@ -22,7 +22,7 @@ function test(name, fn) {
|
||||
}
|
||||
|
||||
function load(relativePath) {
|
||||
return fs.readFileSync(path.join(repoRoot, relativePath), 'utf8').replace(/\r\n/g, '\n');
|
||||
return fs.readFileSync(path.join(repoRoot, relativePath), 'utf8');
|
||||
}
|
||||
|
||||
console.log('\n=== Testing release publish workflow ===\n');
|
||||
@@ -32,12 +32,9 @@ for (const workflow of [
|
||||
'.github/workflows/reusable-release.yml',
|
||||
]) {
|
||||
const content = load(workflow);
|
||||
const jobsIndex = content.search(/^jobs:\s*$/m);
|
||||
const workflowHeader = jobsIndex >= 0 ? content.slice(0, jobsIndex) : content;
|
||||
|
||||
test(`${workflow} scopes id-token to the publish job for npm provenance`, () => {
|
||||
assert.doesNotMatch(workflowHeader, /id-token:\s*write/);
|
||||
assert.match(content, /\n\s+permissions:\n\s+contents:\s*write\n\s+id-token:\s*write/m);
|
||||
test(`${workflow} grants id-token for npm provenance`, () => {
|
||||
assert.match(content, /permissions:\s*[\s\S]*id-token:\s*write/m);
|
||||
});
|
||||
|
||||
test(`${workflow} configures the npm registry`, () => {
|
||||
@@ -54,7 +51,7 @@ for (const workflow of [
|
||||
});
|
||||
|
||||
test(`${workflow} publishes new tag versions to npm`, () => {
|
||||
assert.match(content, /npm publish "\$\{\{ needs\.verify\.outputs\.package_file \}\}" --access public --provenance/);
|
||||
assert.match(content, /npm publish --access public --provenance/);
|
||||
assert.match(content, /NODE_AUTH_TOKEN:\s*\$\{\{\s*secrets\.NPM_TOKEN\s*\}\}/);
|
||||
});
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ const INSTALL_SCRIPT = path.join(__dirname, '..', '..', 'scripts', 'install-appl
|
||||
const DOCTOR_SCRIPT = path.join(__dirname, '..', '..', 'scripts', 'doctor.js');
|
||||
const REPAIR_SCRIPT = path.join(__dirname, '..', '..', 'scripts', 'repair.js');
|
||||
const REPO_ROOT = path.join(__dirname, '..', '..');
|
||||
const CLI_TIMEOUT_MS = 30000;
|
||||
const CURRENT_PACKAGE_VERSION = JSON.parse(
|
||||
fs.readFileSync(path.join(REPO_ROOT, 'package.json'), 'utf8')
|
||||
).version;
|
||||
@@ -52,7 +51,7 @@ function runNode(scriptPath, args = [], options = {}) {
|
||||
env,
|
||||
encoding: 'utf8',
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
timeout: options.timeout || CLI_TIMEOUT_MS,
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
return { code: 0, stdout, stderr: '' };
|
||||
@@ -60,7 +59,7 @@ function runNode(scriptPath, args = [], options = {}) {
|
||||
return {
|
||||
code: error.status || 1,
|
||||
stdout: error.stdout || '',
|
||||
stderr: error.stderr || error.message || '',
|
||||
stderr: error.stderr || '',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
from llm.core.types import LLMInput, Message, Role, ToolDefinition
|
||||
from llm.providers.claude import ClaudeProvider
|
||||
from llm.providers.constants import EMPTY_FILTERED_RESPONSE_ERROR
|
||||
from llm.providers.openai import OpenAIProvider
|
||||
|
||||
|
||||
@@ -17,20 +14,21 @@ def _tool() -> ToolDefinition:
|
||||
|
||||
|
||||
class _OpenAICompletions:
|
||||
def __init__(self, response: SimpleNamespace | None = None) -> None:
|
||||
def __init__(self) -> None:
|
||||
self.params = None
|
||||
self.response = response
|
||||
|
||||
def create(self, **params):
|
||||
self.params = params
|
||||
if self.response:
|
||||
return self.response
|
||||
return _openai_response(model=params["model"])
|
||||
return SimpleNamespace(
|
||||
choices=[SimpleNamespace(message=SimpleNamespace(content="ok", tool_calls=None), finish_reason="stop")],
|
||||
model=params["model"],
|
||||
usage=SimpleNamespace(prompt_tokens=1, completion_tokens=1, total_tokens=2),
|
||||
)
|
||||
|
||||
|
||||
class _OpenAIClient:
|
||||
def __init__(self, response: SimpleNamespace | None = None) -> None:
|
||||
self.completions = _OpenAICompletions(response=response)
|
||||
def __init__(self) -> None:
|
||||
self.completions = _OpenAICompletions()
|
||||
self.chat = SimpleNamespace(completions=self.completions)
|
||||
|
||||
|
||||
@@ -54,16 +52,6 @@ class _AnthropicClient:
|
||||
self.api_key = "test"
|
||||
|
||||
|
||||
def _openai_response(**overrides) -> SimpleNamespace:
|
||||
defaults = {
|
||||
"choices": [SimpleNamespace(message=SimpleNamespace(content="ok", tool_calls=None), finish_reason="stop")],
|
||||
"model": "gpt-4o-mini",
|
||||
"usage": SimpleNamespace(prompt_tokens=1, completion_tokens=1, total_tokens=2),
|
||||
}
|
||||
defaults.update(overrides)
|
||||
return SimpleNamespace(**defaults)
|
||||
|
||||
|
||||
def test_openai_provider_serializes_tools_for_chat_completions():
|
||||
provider = OpenAIProvider(api_key="test")
|
||||
client = _OpenAIClient()
|
||||
@@ -84,36 +72,6 @@ def test_openai_provider_serializes_tools_for_chat_completions():
|
||||
]
|
||||
|
||||
|
||||
def test_openai_provider_can_be_constructed_without_credentials(monkeypatch):
|
||||
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
|
||||
|
||||
provider = OpenAIProvider()
|
||||
|
||||
assert provider.validate_config() is False
|
||||
|
||||
|
||||
def test_openai_provider_rejects_empty_or_filtered_responses():
|
||||
provider = OpenAIProvider(api_key="test")
|
||||
|
||||
for response in [
|
||||
_openai_response(choices=[]),
|
||||
_openai_response(choices=[SimpleNamespace(message=None, finish_reason="content_filter")]),
|
||||
]:
|
||||
provider.client = _OpenAIClient(response=response)
|
||||
with pytest.raises(ValueError, match=EMPTY_FILTERED_RESPONSE_ERROR):
|
||||
provider.generate(LLMInput(messages=[Message(role=Role.USER, content="hi")]))
|
||||
|
||||
|
||||
def test_openai_provider_allows_missing_usage():
|
||||
provider = OpenAIProvider(api_key="test")
|
||||
provider.client = _OpenAIClient(response=_openai_response(usage=None))
|
||||
|
||||
output = provider.generate(LLMInput(messages=[Message(role=Role.USER, content="hi")]))
|
||||
|
||||
assert output.content == "ok"
|
||||
assert output.usage is None
|
||||
|
||||
|
||||
def test_claude_provider_serializes_tools_for_messages_api():
|
||||
provider = ClaudeProvider(api_key="test")
|
||||
client = _AnthropicClient()
|
||||
|
||||
Reference in New Issue
Block a user