28 Commits

Author SHA1 Message Date
Affaan Mustafa
7ac506036c docs: refresh operator dashboard after hosted finding evidence 2026-05-16 01:50:12 -04:00
Affaan Mustafa
fb28e469f1 docs: record ECC Tools hosted finding evidence 2026-05-16 01:49:46 -04:00
Affaan Mustafa
257aa67b61 docs: refresh operator dashboard after ECC Tools fleet sync 2026-05-16 01:38:36 -04:00
Affaan Mustafa
a1cf97e3f2 docs: record ECC Tools fleet evidence consumption 2026-05-16 01:38:11 -04:00
Affaan Mustafa
10b1222fc8 docs: refresh operator dashboard after fleet routing 2026-05-16 01:24:49 -04:00
Affaan Mustafa
cc83a85eb8 docs: record AgentShield fleet routing evidence 2026-05-16 01:24:20 -04:00
Affaan Mustafa
1c5c5d2389 docs: refresh operator dashboard after evidence-pack inspect 2026-05-16 01:03:29 -04:00
Affaan Mustafa
fe49a31e9a docs: record AgentShield evidence-pack inspect evidence 2026-05-16 01:03:06 -04:00
Affaan Mustafa
6bced468d7 docs: refresh operator dashboard after AgentShield sync 2026-05-16 00:28:47 -04:00
Affaan Mustafa
1eb7b0809d docs: record AgentShield plugin-cache evidence 2026-05-16 00:27:48 -04:00
Affaan Mustafa
6c8e909d63 docs: record May 16 rc1 readiness evidence 2026-05-15 23:38:00 -04:00
Affaan Mustafa
cecab59747 docs: refresh operator dashboard after queue cleanup 2026-05-15 23:32:27 -04:00
Affaan Mustafa
9e973b29fb docs: remove emoji from recsys skill 2026-05-15 23:28:58 -04:00
Affaan Mustafa
d0303f4538 docs: sync recsys skill catalog counts 2026-05-15 23:28:58 -04:00
mehmet turac
4b96af8f6a feat: add recsys-pipeline-architect skill (community) 2026-05-15 23:28:58 -04:00
Kris Pahel
50ac061f9e chore: update statusline ANSI color palette
- Replace blinking red (5;31m) with bold red (1;31m) for critical context bar
- Replace cyan metrics (36m) with sky blue (38;5;117m)
- Replace plain bold task (1m) with bold bright white (1;97m)
- Update test assertion to match new bold red code
2026-05-15 23:18:01 -04:00
Affaan Mustafa
4093d1bb0b Refresh operator readiness dashboard 2026-05-15 23:09:54 -04:00
Affaan Mustafa
714200fd20 Cover advisory source renderer branches 2026-05-15 23:09:54 -04:00
Affaan Mustafa
2b387fb761 Cover advisory source refresh branches 2026-05-15 23:09:54 -04:00
Affaan Mustafa
5b1a5e6433 Refresh operator readiness dashboard 2026-05-15 23:09:54 -04:00
Affaan Mustafa
a8e3bcb00f Add supply-chain advisory source refresh 2026-05-15 23:09:54 -04:00
Affaan Mustafa
2d46c00763 Cover operator dashboard render branches 2026-05-15 22:28:16 -04:00
Affaan Mustafa
3315f0ed61 Include operator dashboard in publish surface test 2026-05-15 22:28:16 -04:00
Affaan Mustafa
1a7306acbe Refresh generated readiness dashboard 2026-05-15 22:28:16 -04:00
Affaan Mustafa
e26b5132c2 Align platform audit with generated dashboard 2026-05-15 22:28:16 -04:00
Affaan Mustafa
5157ee63f0 Generate operator readiness dashboard 2026-05-15 22:28:16 -04:00
Affaan Mustafa
50f375bc2c Add repeatable operator readiness dashboard 2026-05-15 22:28:16 -04:00
Affaan Mustafa
bfffc33869 Refresh release evidence after CI hardening 2026-05-15 17:46:25 -04:00
28 changed files with 2215 additions and 169 deletions

View File

@@ -11,7 +11,7 @@
{
"name": "ecc",
"source": "./",
"description": "The most comprehensive Claude Code plugin — 60 agents, 229 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",

View File

@@ -1,7 +1,7 @@
{
"name": "ecc",
"version": "2.0.0-rc.1",
"description": "Battle-tested Claude Code plugin for engineering teams — 60 agents, 229 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"

View File

@@ -40,11 +40,17 @@ jobs:
- name: Validate IOC scanner fixtures
run: node tests/ci/scan-supply-chain-iocs.test.js
- name: Validate advisory source fixtures
run: node tests/ci/supply-chain-advisory-sources.test.js
- name: Generate IOC report
run: |
mkdir -p artifacts
node scripts/ci/scan-supply-chain-iocs.js --json > artifacts/supply-chain-ioc-report.json
- name: Generate advisory source report
run: node scripts/ci/supply-chain-advisory-sources.js --refresh --json > artifacts/supply-chain-advisory-sources.json
- name: Validate workflow hardening rules
run: node scripts/ci/validate-workflow-security.js
@@ -53,5 +59,7 @@ jobs:
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: supply-chain-ioc-report
path: artifacts/supply-chain-ioc-report.json
path: |
artifacts/supply-chain-ioc-report.json
artifacts/supply-chain-advisory-sources.json
retention-days: 14

View File

@@ -1,6 +1,6 @@
# Everything Claude Code (ECC) — Agent Instructions
This is a **production-ready AI coding plugin** providing 60 specialized agents, 229 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/ — 229 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)

View File

@@ -124,7 +124,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, 229 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.
@@ -393,7 +393,7 @@ If you stacked methods, clean up in this order:
/plugin list ecc@ecc
```
**That's it!** You now have access to 60 agents, 229 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
@@ -1398,7 +1398,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: 229 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** |
@@ -1560,7 +1560,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** | 229 | 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 |

View File

@@ -160,7 +160,7 @@ Copy-Item -Recurse rules/typescript "$HOME/.claude/rules/"
/plugin list ecc@ecc
```
**完成!** 你现在可以使用 60 个代理、229 个技能和 75 个命令。
**完成!** 你现在可以使用 60 个代理、230 个技能和 75 个命令。
### multi-* 命令需要额外配置

View File

@@ -14,7 +14,7 @@ execution truth is split across:
## Current Evidence
As of 2026-05-15:
As of 2026-05-16:
- GitHub queues are clean across `affaan-m/everything-claude-code`,
`affaan-m/agentshield`, `affaan-m/JARVIS`, `ECC-Tools/ECC-Tools`, and
@@ -31,14 +31,24 @@ As of 2026-05-15:
`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.
- `docs/releases/2.0.0-rc.1/publication-evidence-2026-05-15.md` records the
- `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, restore-only CI cache hardening, AgentShield #85
full-campaign follow-up, scheduled supply-chain watch coverage, no-lifecycle
CI install hardening, GitHub Actions cache purge, AgentShield #85
registry-signature verification, AgentShield #86 evidence-pack CI provenance,
ECC-Tools #75 billing-gate tightening, and PR #1936 release-evidence refresh.
AgentShield #87 plugin-cache runtime-confidence classification, AgentShield
#88 evidence-pack inspect/readback, AgentShield #89 evidence-pack fleet
routing, ECC-Tools #75 billing-gate tightening, ECC-Tools #76 AgentShield
fleet-summary consumption, ECC-Tools #77 hosted finding evidence paths, PR
#1947 supply-chain protection, and May 16 release-evidence refresh.
- `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.
- `npm run operator:dashboard -- --allow-untracked docs/drafts/ --write
docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-15.md`
now regenerates the ITO-44 prompt-to-artifact dashboard from live
`platform:audit` evidence instead of leaving the operator snapshot as a
hand-maintained document.
- 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`.
@@ -46,6 +56,12 @@ As of 2026-05-15:
`docs/security/supply-chain-incident-response.md`, plus a workflow-security
validator rule blocking `pull_request_target` workflows from restoring or
saving shared dependency caches.
- PR #1940 merged as `6951b8d5d29d13cac6b89b461104ad03838553de` and added a
scheduled supply-chain watch workflow that emits a durable IOC report.
- PR #1941 merged as `f7035b5644ffc857879b71c39353b2141f17c3f0` and hardened
CI dependency installs against lifecycle-hook compromise by disabling package
manager lifecycle scripts, removing Actions dependency cache use, and adding
validator coverage so those patterns cannot be reintroduced silently.
- PR #1850 merged as `248673271455e9dc85b8add2a6ab76107b718639` and removed
shell access from read-only analyzer agents and zh-CN copies, reducing
AgentShield high findings on that surface without changing operator agents.
@@ -74,6 +90,24 @@ As of 2026-05-15:
and expanded the built-in attack corpus with an env proxy hijack scenario
covering proxy/runtime mutation, env-token exfiltration, DNS exfiltration,
credential-store access, and clipboard access.
- AgentShield PR #87 merged as `26bb44650663816d07180e0d20c1895e431a326c`
and added installed Claude plugin-cache runtime confidence. Cached plugin
findings now emit `runtimeConfidence: plugin-cache`, non-secret score impact
stays at the intended `0.5x`, repository-local non-Claude `plugins/cache`
paths are not downgraded, and cached hook implementations no longer appear as
active top-level `hook-code`.
- AgentShield PR #88 merged as `65ed6e2a87545dc99d962b58413f49096a4d70ec`
and added `agentshield evidence-pack inspect` for downstream consumers.
Evidence-pack bundles now have compact JSON/text readback for report score,
finding counts, runtime confidence, policy, baseline, supply-chain, CI
context, remediation phases, and malformed artifact errors without manually
opening every bundle file.
- AgentShield PR #89 merged as `521ada9091bb6d818511ab8589ae675b920c106a`
and added `agentshield evidence-pack fleet <dirs...> [--json]` for
downstream fleet routing. Multiple verified evidence packs now aggregate into
ready, security-blocker, policy-review, baseline-regression,
supply-chain-review, and invalid routes with finding, policy, baseline,
supply-chain, and remediation totals.
- JARVIS PR #13 merged as `127efabbfb5033ae53d7a53e1546aa3c33d6f962`
and hardened CI/deploy workflows with npm registry signature verification,
disabled persisted checkout credentials in write-permission jobs, and pinned
@@ -442,6 +476,16 @@ As of 2026-05-15:
- ECC-Tools PR #69 extends that gate to score cached completed hosted job
outputs for the current PR head, so hosted artifacts can satisfy corpus
evidence expectations before the check reports a promotion gap.
- ECC-Tools PR #76 consumes AgentShield PR #89 fleet output in hosted security
review: `agentshield-evidence/fleet-summary.json` is now classified as
`evidence-pack-fleet`, invalid packs and security-blocker routes become
high-severity hosted findings, and policy, baseline, and supply-chain routes
produce owner-ready review findings.
- ECC-Tools PR #77 merged as `31fd883b3f0cee135aee4839b01d34855b7867f6`
and adds an `Evidence` column to hosted job PR comments and check-run
details, surfacing up to three source evidence paths for each finding so
AgentShield fleet-derived findings point operators back to the exact bundle
artifact.
- ECC PR #1803 landed the contributor Quarkus handling branch after maintainer
cleanup, current-`main` alignment, full local validation, and preservation of
the author's removal of incomplete ja-JP and zh-CN Quarkus translations.
@@ -494,11 +538,11 @@ is not complete unless the evidence column exists and has been freshly verified.
| 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, and CI-provenance evidence packs | PRs #53, #55-#64, #67-#69, and #78-#86 landed with test evidence; 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, and `ci-context.json` provenance slices landed | Next evidence-pack consumer/readback workflow depth |
| 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, payment-announcement readiness | PRs #26-#43 plus #53-#74 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, a fail-closed `/api/billing/readiness` `announcementGate` for native GitHub payments claims, and `npm run billing:announcement-gate` as the non-secret operator verifier | Next work is hosted promotion telemetry, operator review UX, and live Marketplace test-account readback |
| 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, and fleet-level evidence-pack routing | PRs #53, #55-#64, #67-#69, and #78-#89 landed with test evidence, ECC-Tools #76 consumes the fleet-summary output in hosted security review, and ECC-Tools #77 surfaces source evidence paths in hosted finding 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, and `evidence-pack fleet` routing slices landed | Next cross-harness policy integration and richer fleet-review workflow |
| 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, payment-announcement readiness, AgentShield fleet-summary hosted routing, and hosted finding source-evidence surfacing | PRs #26-#43 plus #53-#77 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, a fail-closed `/api/billing/readiness` `announcementGate` for native GitHub payments claims, `npm run billing:announcement-gate` as the non-secret operator verifier, hosted security findings for AgentShield fleet summaries, and an `Evidence` column in hosted finding comments/check-runs | Next work is hosted promotion telemetry, richer operator review UX, and live Marketplace test-account readback |
| 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; this May 15 sync adds ECC #1860, AgentShield #78-#86, JARVIS #13, ECC-Tools #53-#74, resolved queue/discussion counts, and notes that Linear connector status updates after ECC-Tools #68 remain blocked by a connector secret-owner error | Needs recurring status updates after connector recovery |
| 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; this May 16 sync adds ECC #1860, AgentShield #78-#89, JARVIS #13, ECC-Tools #53-#77, resolved queue/discussion counts, and a 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 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 | Needs workspace capacity/config rollout |
| 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 |
@@ -518,9 +562,9 @@ repo evidence and merge commits.
| 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 | Hosted promotion telemetry and operator review UX |
| AgentShield enterprise | AgentShield PR evidence and roadmap notes | Remediation workflow depth or corpus expansion follow-up | Next implementation batch |
| 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, and #74 adds `npm run billing:announcement-gate` for operator verification | Live Marketplace test-account readback and hosted promotion telemetry |
| Linear progress | Linear project status updates, `docs/architecture/progress-sync-contract.md`, and this mirror | Status update with queue/evidence/missing gates | Every significant merge batch |
| AgentShield enterprise | AgentShield PR evidence and roadmap notes | Fleet routing landed in #89 after evidence-pack inspect/readback shipped in #88; ECC-Tools #76 consumes fleet summaries and #77 surfaces source evidence paths in hosted findings | Cross-harness policy integration and richer fleet-review workflow |
| 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, and #77 adds source evidence paths to hosted finding output | Live Marketplace test-account readback, hosted promotion telemetry, and richer operator review UX |
| 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:
@@ -737,8 +781,15 @@ Acceptance:
exfiltration; PRs #83-#85 hardened Mini Shai-Hulud IOC coverage and
release-path supply-chain verification; PR #86 added whitelisted
`ci-context.json` workflow, commit, run, and runtime provenance to evidence
packs; and ECC-Tools PRs #42/#43 now route and recognize evidence packs.
The next slice is evidence-pack consumer/readback workflow depth.
packs; PR #87 classified installed Claude plugin caches separately from
active top-level runtime config, including cached hook implementations; PR
#88 added `agentshield evidence-pack inspect` JSON/text readback for
downstream consumers; PR #89 added `agentshield evidence-pack fleet`
summary/routing across multiple inspected bundles; ECC-Tools PRs #42/#43 now
route and recognize evidence packs; ECC-Tools PR #76 consumes fleet
summaries in hosted security review; and ECC-Tools PR #77 surfaces source
evidence paths in hosted PR comments and check-runs. The next slice is
cross-harness policy integration and richer fleet-review workflow.
2. Run ECC-Tools `/api/billing/readiness` against a Marketplace-managed test
account and require `announcementGate.ready === true` before any native
GitHub payments announcement.

View File

@@ -1,6 +1,6 @@
# AgentShield Enterprise Research Roadmap
Generated: 2026-05-12
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,
@@ -84,12 +84,44 @@ AgentShield is already more than a static lint tool:
- Enterprise hooks exist: policy packs, exception metadata, expiring/expired
exception reporting, SARIF code scanning, and job-summary output.
- Accuracy work is active: `runtimeConfidence`, template/example weighting,
docs-example downgrades, hook-manifest resolution, false-positive audit
guidance, and corpus readiness.
docs-example downgrades, installed Claude plugin-cache confidence,
hook-manifest resolution, false-positive audit guidance, and corpus readiness.
- Evidence-pack consumption is now first-class enough for downstream tools:
`agentshield evidence-pack inspect` verifies a bundle and emits compact
JSON/text summaries for report score, finding counts, runtime confidence,
policy, baseline, supply-chain, CI context, remediation, and malformed
artifact errors.
- Fleet-level evidence-pack consumption now has a local routing primitive:
`agentshield evidence-pack fleet <dirs...> [--json]` aggregates multiple
inspected bundles into ready, security-blocker, policy-review,
baseline-regression, supply-chain-review, and invalid routes.
- ECC-Tools now consumes that fleet primitive in hosted security review:
`agentshield-evidence/fleet-summary.json` routes invalid packs, security
blockers, policy reviews, baseline regressions, and supply-chain reviews into
hosted findings.
The next iteration should not be "add more regex rules" by default. The higher
leverage move is to make AgentShield remember, compare, route, and enforce
security posture across time, repos, teams, and harnesses.
May 16 update: AgentShield PR #87 merged as
`26bb44650663816d07180e0d20c1895e431a326c`. It classifies installed Claude
plugin cache content as `runtimeConfidence: plugin-cache`, keeps non-secret
plugin-cache score impact at `0.5x`, avoids downgrading repository-local
non-Claude `plugins/cache` paths, and makes plugin-cache classification win
before cached hook implementations would otherwise appear as active `hook-code`.
AgentShield PR #88 merged as
`65ed6e2a87545dc99d962b58413f49096a4d70ec`. It adds
`agentshield evidence-pack inspect <dir> [--json]`, validates the bundle before
readback, summarizes every consumer-facing evidence artifact, and keeps
malformed-but-valid JSON artifacts from crashing inspection.
AgentShield PR #89 merged as
`521ada9091bb6d818511ab8589ae675b920c106a`. It adds
`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.
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; the higher leverage move is
cross-harness policy integration plus richer review workflow for routed fleet
findings.
## Enterprise Gaps
@@ -323,6 +355,8 @@ The AgentShield enterprise iteration is not complete until these are true:
- Built CLI smoke tests cover the new flags or report modes.
- GitHub Action self-test covers the new CI-visible output.
- Documentation names the free/local path and the paid/team path separately.
- Runtime-confidence changes include live scan evidence proving lower-confidence
plugin/package surfaces stay visible instead of being suppressed.
- Evidence produced by the feature is deterministic enough for CI diffing.
- ECC-Tools can consume the finding fingerprints or backlog export without
exceeding GitHub/Linear object caps.

View File

@@ -1,114 +1,55 @@
# ECC Operator Readiness Dashboard - 2026-05-15
# ECC Operator Readiness Dashboard
This dashboard is an operator snapshot, not a release approval. Use it to decide
the next ECC 2.0 work batch and to keep Linear, GitHub, and repo evidence in
sync. Before publishing, repeat the checks from the final release commit in a
clean checkout.
This dashboard is generated by `npm run operator:dashboard`. It is an operator snapshot, not release approval.
Generated: 2026-05-16T05:49:52.579Z
Commit: fb28e469f1b94d18c9196f1cac9dabbf08286ef3
Status: work remaining
## Current Status
| Area | Status | Evidence |
| --- | --- | --- |
| PR queue | Current | 0 open PRs across checked repos |
| Issue queue | Current | 0 open issues across checked repos |
| Discussions | Current | 58 main-repo discussions; 0 need maintainer touch; 0 answerable discussions missing accepted answers |
| Local worktree | Current with caveat | `main...origin/main`; unrelated `?? docs/drafts/` ignored |
| Security sweep | Current with follow-up | IOC scan, audits, package-manager hardening, and scheduled watch workflow completed |
| Linear roadmap | Current with follow-up | `ECC Platform Roadmap`, ITO-44 through ITO-59 |
| ECC 2.0 publication | Not complete | Release, npm, plugin, and announcement gates pending |
| AgentShield enterprise depth | In progress | AgentShield #86 merged; live IOC loop still pending |
| ECC Tools next-level app | In progress | Billing announcement gate merged; live readback pending |
| Legacy audit and salvage | Not complete | ITO-55 remains open |
## Live Command Evidence
Run these from `everything-claude-code` unless a row says otherwise.
| Evidence | Command | 2026-05-15 result |
| --- | --- | --- |
| Platform audit | `node scripts/platform-audit.js --json --allow-untracked docs/drafts/` | `ready: true`; open PRs 0/20; open issues 0/20; discussions needing maintainer touch 0; answerable discussions missing accepted answers 0; blocking dirty files 0 |
| Discussion audit | `node scripts/discussion-audit.js --json --repo affaan-m/everything-claude-code` | `ready: true`; 58 discussions sampled; 0 need maintainer touch; 0 answerable discussions missing accepted answers |
| Main repo status | `git status --short --branch` | `## main...origin/main`; `?? docs/drafts/` remains unrelated |
| Main commit | `git rev-parse HEAD` | `6887f2952d193cff10b3eb79af7765555d8ca9f5` |
| Main repo PRs/issues | GitHub connector and `gh` readback | 0 open PRs; 0 open issues |
| AgentShield PRs/issues | GitHub connector and `gh` readback | 0 open PRs; 0 open issues |
| ECC Tools PRs/issues | Local `gh pr list` and `gh issue list` | 0 open PRs; 0 open issues |
| Discussion baseline | GraphQL discussion sweep | Main repo #1923 marked answered; no answerable Q&A missing an answer |
| Supply-chain IOC scan | `node scripts/ci/scan-supply-chain-iocs.js --root <ECC-workspace> --home` | Passed; repo/home targeted scan inspected 200 files after clean no-script reinstall |
| IOC unit tests | `node tests/ci/scan-supply-chain-iocs.test.js` | 15/15 passed |
| Dead-man switch persistence sweep | Process, LaunchAgent, and known payload filename sweep for Mini Shai-Hulud markers | No matches |
| Workflow security gate | `node scripts/ci/validate-workflow-security.js` | Passed; 8 workflow files inspected; package-manager test installs disable lifecycle scripts and no Actions cache use remains |
| Supply-chain watch workflow | `.github/workflows/supply-chain-watch.yml` | Scheduled every 6 hours; emits `supply-chain-ioc-report.json` |
| npm signatures and audit | `npm audit signatures && npm audit --audit-level=high` in main | 213 verified signatures, 17 verified attestations, 0 high vulnerabilities |
| 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; 1 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 evidence | Status | Gap |
| --- | --- | --- | --- |
| Keep PRs under 20 | `scripts/platform-audit.js`; live GitHub readback | Current | Repeat before release |
| Keep issues under 20 | `scripts/platform-audit.js`; live GitHub readback | Current | Repeat before release |
| Respond and manage discussions | `scripts/discussion-audit.js`; #1923 answer marked | Current | Repeat before release |
| ECC 2.0 preview pack ready | `preview-pack-manifest.md`; `publication-readiness.md` | In progress | Final publish evidence still pending |
| Include Hermes specialized skills | `docs/HERMES-SETUP.md`; `skills/hermes-imports/SKILL.md` | In progress | Final preview-pack smoke still pending |
| Name-change and availability path | `naming-and-publication-matrix.md`; ITO-46 | In progress | Final name/package/channel choice not approved |
| Claude plugin publication path | `.claude-plugin/`; `publication-readiness.md`; ITO-46 | In progress | Actual publication still pending |
| Codex plugin publication path | `.codex-plugin/`; repo marketplace evidence; ITO-46 | In progress | Official directory path still pending |
| Release notes and push notifications | `release-notes.md`; `x-thread.md`; `linkedin-post.md`; ITO-47/56 | In progress | Live URLs and publish approval missing |
| AgentShield enterprise iteration | AgentShield PRs #83-#86; ITO-48/49 | In progress | Live IOC update loop and cross-harness depth pending |
| ECC Tools native payments announcement | ECC-Tools #75; ITO-50 | In progress | Live Marketplace test-account readback pending |
| ECC Tools AI-native harness-agnostic roadmap | ITO-51/52/53/54 | In progress | Implementation and hosted deep-analysis proof pending |
| Linear roadmap extremely detailed | Linear `ECC Platform Roadmap`; ITO-44 through ITO-59 | Current | Keep status comments synchronized |
| Legacy work audited, pruned, or attached | `docs/legacy-artifact-inventory.md`; ITO-55 | In progress | Final salvage/prune pass pending |
| Realtime progress tracking with Linear | ITO-54; Linear progress comments | In progress | Productized sync/observability plane pending |
| ECC 2.0 observability | `docs/architecture/observability-readiness.md`; ITO-54 | In progress | Runtime/dashboard implementation pending |
| Objective requirement | Artifact or gate | Status | Evidence | Gap |
| --- | --- | --- | --- | --- |
| Keep public PRs below 20 | scripts/platform-audit.js live GitHub sweep | current | 0 open PRs across 5 tracked repos | repeat before release |
| Keep public issues below 20 | scripts/platform-audit.js live GitHub sweep | current | 0 open issues across 5 tracked repos | repeat 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 | in_progress | preview pack manifest is in-tree | final clean-checkout release approval and publish evidence still pending |
| Include Hermes specialized skills safely | docs/HERMES-SETUP.md and skills/hermes-imports/SKILL.md | in_progress | Hermes setup and import skill are present | final preview-pack smoke and release review pending |
| Prepare name-change, Claude plugin, and Codex plugin paths | naming-and-publication-matrix plus publication-readiness | in_progress | naming matrix 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, and LinkedIn draft are present | URL-backed refresh and publish approval still pending |
| Advance AgentShield enterprise iteration | AgentShield PR evidence plus enterprise roadmap | in_progress | AgentShield enterprise PR evidence is mirrored in the GA roadmap | cross-harness policy integration and richer fleet-review workflow remain pending after fleet-summary consumption and evidence-path surfacing shipped |
| 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, and hosted finding evidence paths are mirrored in the GA roadmap | live Marketplace test-account readback, hosted promotion telemetry, and richer operator review UX pending |
| Audit, prune, or attach legacy work | docs/stale-pr-salvage-ledger.md and legacy inventory | not_complete | legacy salvage ledger and ITO-55 tracking are present | final translation/manual-review tail remains |
| Keep Linear roadmap detailed and progress tracking synchronized | Linear project mirror plus progress-sync contract | in_progress | repo mirror and progress-sync contract are present | recurring Linear status sync and productized realtime sync remain pending |
| 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 | current | scheduled supply-chain watch now emits IOC and advisory-source refresh artifacts | Linear status synchronization remains ITO-57 follow-up after each significant merge batch |
## Linear Operating State
## Top Actions
Project:
<https://linear.app/itomarkets/project/ecc-platform-roadmap-52b328ee03e1>
Active issue state after this pass:
| Issue | Lane | State |
| --- | --- | --- |
| ITO-44 | Completion audit and readiness dashboard | In Progress |
| ITO-57 | Supply-chain intelligence and local protection loop | In Progress |
| ITO-59 | Discussions and public response queue | Current; Linear status sync pending |
Still-open lanes:
- ITO-45: ECC 2.0 preview pack, Hermes skills, packaging, and cross-harness
readiness.
- ITO-46: name availability, Claude plugin, Codex plugin, and package channels.
- ITO-47: release notes, articles, and social copy since last release.
- ITO-48 and ITO-49: AgentShield enterprise iteration and live supply-chain
intelligence.
- ITO-50 through ITO-54: ECC Tools payments, deep analysis, setup
recommendations, queue automation, Linear sync, and observability.
- ITO-55: legacy audit, prune, attach, or salvage.
- ITO-56: final publication gate, release notes, and push notifications.
- ITO-58: ECC Tools GitHub access blocker.
## Decisions From This Pass
- The checked GitHub queues are below the explicit target, so the next work
should not spend more time closing nonexistent PRs/issues.
- The discussion queue is current and repeatable through `discussion:audit`.
ITO-59 remains open only for recurring Linear/status synchronization.
- The Mini Shai-Hulud/TanStack protection pass now has a durable scheduled
watch workflow. ITO-57 remains open for advisory-source refresh automation
and Linear status synchronization.
- The release is still blocked by publication, package, plugin, billing, and
announcement gates. Passing `platform:audit` alone is not proof that ECC 2.0
is publishable.
- `ecc-preview-pack`: final clean-checkout release approval and publish evidence still pending
- `hermes-specialized-skills`: final preview-pack smoke and release review pending
- `naming-and-plugin-publication`: real tag/push, marketplace submission, and final channel choice remain approval-gated
- `release-notes-and-notifications`: URL-backed refresh and publish approval still pending
- `agentshield-enterprise-iteration`: cross-harness policy integration and richer fleet-review workflow remain pending after fleet-summary consumption and evidence-path surfacing shipped
- `ecc-tools-next-level`: live Marketplace test-account readback, hosted promotion telemetry, and richer operator review UX pending
- `legacy-salvage`: final translation/manual-review tail remains
- `linear-roadmap-and-progress`: recurring Linear status sync and productized realtime sync remain pending
## Next Work Order
1. Build the ITO-44 completion dashboard into a repeatable command or generated
markdown artifact.
2. Run `platform:audit` and `discussion:audit` from the final release commit
before recording publication evidence.
3. Continue ITO-57 by adding advisory-source refresh automation and Linear
status synchronization for the scheduled supply-chain watch.
4. Resume release/publication lanes ITO-45, ITO-46, and ITO-56 only after the
readiness dashboard can be refreshed from commands.
1. Regenerate this dashboard from the final release commit before publication evidence is recorded.
2. Continue ITO-57 with Linear status synchronization for the scheduled supply-chain watch advisory-source report.
3. Advance ECC Tools live Marketplace test-account readback before publishing native-payments announcement copy.
4. Resume ITO-45, ITO-46, and ITO-56 only after the generated dashboard and final release gates are refreshed.

View File

@@ -20,7 +20,8 @@ surfaces, or posting announcements.
| `docs/releases/2.0.0-rc.1/quickstart.md` | Clone-to-first-workflow path | Covers clone, install, verify, first skill, and harness switch |
| `docs/releases/2.0.0-rc.1/launch-checklist.md` | Operator launch checklist | Must remain approval-gated for release, package, plugin, and announcement actions |
| `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, AgentShield #86 evidence-pack provenance, ECC Tools billing-gate, CI cache, and `ecc2` test evidence through PR #1936 | Must be superseded by a final clean-checkout evidence file before real publication |
| `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 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, ECC-Tools #76 fleet-summary consumption, ECC-Tools #77 hosted finding evidence paths, 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/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/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 |

View File

@@ -71,18 +71,21 @@ Project documents added in Linear:
| PR #1933 | Expanded home-scan IOC coverage to Claude `settings.local.json`, `.claude/hooks/hooks.json`, and user-level VS Code / Code Insiders `tasks.json` across macOS, Linux, and Windows |
| PR #1934 | Switched ordinary CI dependency caches to restore-only `actions/cache/restore` usage so test jobs do not save mutable dependency state back into shared caches |
| PR #1935 | Stabilized `ecc2` current-directory-mutating tests with a test-only serialized current-dir guard, preserving the Rust release-surface gate under parallel test execution |
| PR #1940 | Added `.github/workflows/supply-chain-watch.yml`, scheduled every 6 hours, so the TanStack/Mini Shai-Hulud/node-ipc IOC scan and npm signature/audit checks produce a durable `supply-chain-ioc-report.json` artifact |
| PR #1941 | Removed GitHub Actions dependency cache use from CI test workflows, disabled package-manager lifecycle scripts for npm/pnpm/Yarn/Bun installs, purged existing Actions caches, and added validator tests that reject unsafe install/cache patterns |
| AgentShield PR #83 | Merged Mini Shai-Hulud IOC coverage for TanStack, Mistral, OpenSearch, Guardrails, UiPath, Squawk, Claude Code / VS Code persistence, and dead-man switch artifacts |
| AgentShield PR #84 | Merged the broader Mini Shai-Hulud full-campaign affected-package table, including additional `@cap-js`, `@draftlab`, `@tallyui`, `intercom-client`, `lightning`, and related package/version IOCs |
| AgentShield PR #85 | Added GitHub Action supply-chain verification, gating, and evidence packs so AgentShield's enterprise scanner release path has a verified registry-signature surface |
| AgentShield PR #86 | Added `ci-context.json` to AgentShield evidence packs with whitelisted GitHub Actions workflow, commit, run, and runtime provenance while keeping arbitrary environment variables and tokens out of the bundle |
| ECC-Tools PR #75 | Tightened the native GitHub payments announcement gate so public billing claims remain blocked until live Marketplace-managed test-account readback is ready |
| Trunk merge commits | `f04702bdac132662c8496e817bcd850c86e2b854`, `ee85e1482e3d6322ddb2706392ea0fc97469bd26`, `13585f1092c92fa3f20ffe0d756e40c5720b0de5`, `553d507ea63bc252e815a924c0d2baea961351a1`, `c0bac4d6ced7f78a5464c6e3fd8cfbb43515a9d5`, `c2c54e7c0b84a213848b9ab3dfeb3ae16fb9844d`, `6b8a49a6eed11cc7df19d8b1f2add085b37cf466`, `1949d75e18e59a37de269d88b188fc701f5cf122` |
| Trunk merge commits | `f04702bdac132662c8496e817bcd850c86e2b854`, `ee85e1482e3d6322ddb2706392ea0fc97469bd26`, `13585f1092c92fa3f20ffe0d756e40c5720b0de5`, `553d507ea63bc252e815a924c0d2baea961351a1`, `c0bac4d6ced7f78a5464c6e3fd8cfbb43515a9d5`, `c2c54e7c0b84a213848b9ab3dfeb3ae16fb9844d`, `6b8a49a6eed11cc7df19d8b1f2add085b37cf466`, `1949d75e18e59a37de269d88b188fc701f5cf122`, `6951b8d5d29d13cac6b89b461104ad03838553de`, `f7035b5644ffc857879b71c39353b2141f17c3f0` |
| AgentShield merge commits | `f899b27ba3fa60ec7e0dca41cc2dadcb1a1fb75d`, `d1aa5313afd915d0b7296e57aabaeb979b1ea93b`, `908d8f3a52a6a65b21e737339b56906603eb1345`, `69a5e25b675b77666d0c96abc22639a5ba883403` |
| ECC-Tools merge commits | `6d00d67043e92cadc80f160bfe947115bfef33b1` |
| Local IOC tests | `node tests/ci/scan-supply-chain-iocs.test.js` passed 15/15 |
| Unicode safety | `node scripts/ci/check-unicode-safety.js` passed |
| IOC scan | `node scripts/ci/scan-supply-chain-iocs.js --root <ECC-workspace> --home` passed with 1241 files inspected |
| npm registry verification | `npm audit signatures` verified 241 registry signatures and 30 attestations; `npm audit --audit-level=moderate` found 0 vulnerabilities |
| IOC scan | `node scripts/ci/scan-supply-chain-iocs.js --root <ECC-workspace> --home` passed with 229 files inspected after the no-lifecycle install refresh |
| npm registry verification | `npm audit signatures` verified 241 registry signatures and 30 attestations; `npm audit --audit-level=high` found 0 vulnerabilities |
| Actions cache purge | `gh cache delete --all --succeed-on-no-caches` completed and `gh cache list --limit 20` returned no caches |
| Rust release-surface gate | `cd ecc2 && cargo test` passed 462/462 with the existing 14 dead-code/unused warnings |
| Root suite | `node tests/run-all.js` passed 2442/2442, 0 failed |
| Repo sweeps | Targeted persistence path checks found no active `gh-token-monitor`, `pgsql-monitor`, `transformers.pyz`, or `pgmonitor.py` artifacts |
@@ -105,10 +108,12 @@ the extra affected npm package scopes and unscoped packages reported in the
current Wiz table, rebuilding `dist/action.js` and `dist/index.js`, and passing
1758/1758 local tests plus the full AgentShield GitHub Actions matrix before
merge.
AgentShield PR #85 and trunk PR #1934 extend the response from IOC detection
into release-path hardening: AgentShield now records registry-signature evidence
for its action surface, while trunk CI restore-only dependency caches avoid
writing ordinary test dependency state back into shared caches.
AgentShield PR #85 and trunk PRs #1934, #1940, and #1941 extend the response
from IOC detection into release-path hardening: AgentShield now records
registry-signature evidence for its action surface, trunk has a scheduled IOC
watch workflow, and trunk CI no longer uses dependency caches or package-manager
lifecycle scripts in the test install matrix during active supply-chain
hardening.
AgentShield PR #86 completes the next evidence-pack provenance slice:
`agentshield scan --evidence-pack <dir>` now writes `ci-context.json`, includes
that artifact in the signed bundle digest, documents it in the bundle README,

View File

@@ -0,0 +1,82 @@
# ECC v2.0.0-rc.1 Publication Evidence - 2026-05-16
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 | `6bced468d76b269243a6f0bd28472853aa78e0e4` |
| Git remote | `https://github.com/affaan-m/everything-claude-code.git` |
| Evidence scope | Current `main` after PR #1944, PR #1945, issue #1946 triage, PR #1947 supply-chain protection, AgentShield PR #87, AgentShield PR #88, AgentShield PR #89, ECC-Tools PR #76, ECC-Tools PR #77, ITO-57 sync, and operator dashboard refresh |
| Local status caveat | `git status --short --branch` showed `## main...origin/main` plus unrelated untracked `docs/drafts/` |
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 --state open --json number,title,url --limit 20` | `[]` |
| Trunk issues | `gh issue list --state open --json number,title,url --limit 20` | `[]` |
| Platform audit | `node scripts/platform-audit.js --json --allow-untracked docs/drafts/` | Ready; open PRs 0, open issues 0, discussion maintainer-touch gaps 0, discussion missing-answer gaps 0, blocking dirty files 0 |
| Operator dashboard | `npm run operator:dashboard -- --json --allow-untracked docs/drafts/` | `dashboardReady: true`, `platformReady: true`, head `6bced468d76b269243a6f0bd28472853aa78e0e4` |
## Merge And Triage Batch
| Item | Result |
| --- | --- |
| PR #1944 | Merged statusline ANSI palette update as `50ac061f9e72d7daa137f1bd08760cf74e9b577d`; targeted `node tests/hooks/ecc-statusline.test.js` and `node scripts/ci/validate-hooks.js` passed before merge |
| PR #1945 | Merged `recsys-pipeline-architect` community skill as `9e973b29fb1a2a0aeb9e6980017b67c3ddb05201`; maintainer patches synced catalog counts and removed emoji blocked by Unicode safety |
| Issue #1946 | Closed as triaged with a corrected maintainer comment; Linear `ITO-60` now tracks GateGuard proactive fact-forcing preflight UX |
| PR #1947 | Merged scheduled supply-chain watch/advisory-source evidence as `4093d1bb7a14db1b4d4ea5bd00f2073baf94bfb0`; trunk now has the TanStack/Mini Shai-Hulud/node-ipc IOC scan plus advisory-source report surfaces wired into scheduled watch evidence |
| AgentShield PR #87 | Merged plugin-cache runtime-confidence classification as `26bb44650663816d07180e0d20c1895e431a326c`; installed Claude plugin cache findings now emit `runtimeConfidence: plugin-cache`, `plugins/cache` only maps to Claude cache under `.claude`, and cached hook implementations are no longer mislabeled as active `hook-code` |
| AgentShield PR #88 | Merged evidence-pack inspect/readback as `65ed6e2a87545dc99d962b58413f49096a4d70ec`; `agentshield evidence-pack inspect` now emits verified JSON/text summaries for report, policy, baseline, supply-chain, CI context, remediation, and malformed artifact errors |
| AgentShield PR #89 | Merged evidence-pack fleet routing as `521ada9091bb6d818511ab8589ae675b920c106a`; `agentshield evidence-pack fleet <dirs...> [--json]` now aggregates multiple verified bundles into ready, security-blocker, policy-review, baseline-regression, supply-chain-review, and invalid routes with finding, policy, baseline, supply-chain, and remediation totals |
| ECC-Tools PR #76 | Merged AgentShield fleet-summary consumption as `5bde2328d15f584481fb6334e6960716dbf3e16f`; hosted `security-evidence-review` now recognizes `agentshield-evidence/fleet-summary.json`, classifies it as `evidence-pack-fleet`, routes invalid/security-blocker/policy/baseline/supply-chain fleet outcomes into hosted findings, and fails closed on malformed fleet JSON |
| ECC-Tools PR #77 | Merged hosted finding source-evidence output as `31fd883b3f0cee135aee4839b01d34855b7867f6`; hosted job PR comments and check-run details now include an `Evidence` column with up to three source evidence paths per finding, including AgentShield fleet-derived findings |
| ITO-57 | Updated with PR #1947 advisory-source evidence, post-merge source refresh, IOC scan, npm audit/signature checks, and OpenAI app update caveat |
| ITO-49 | Updated with AgentShield PR #87, #88, and #89 merge evidence, local test evidence, CI status, live `~/.claude` scan classification counts, and local Mini Shai-Hulud protection scan results |
| ITO-50 | Updated with ECC-Tools PR #76 and PR #77 merge evidence, hosted security review behavior, hosted finding evidence-path behavior, local test evidence, and remote Verify/Security Audit/Workers build checks |
| ITO-44 | Updated with queue cleanup, dashboard refresh, and remaining macro gaps |
## Release Gate Commands
| Gate | Command | Result |
| --- | --- | --- |
| Root suite | `npm test` | 2469 passed, 0 failed |
| Rust `ecc2` suite | `cd ecc2 && cargo test` | 462 passed, 0 failed; existing dead-code/unused warnings only |
| Release surface | `node tests/docs/ecc2-release-surface.test.js` | 20 passed |
| Harness adapters | `npm run harness:adapters -- --check` | PASS; 11 adapters |
| Harness audit | `npm run harness:audit -- --format json` | 70/70, no top actions |
| Observability readiness | `npm run observability:ready` | 21/21, ready yes |
| Supply-chain IOC scan | `npm run security:ioc-scan` | Passed; 227 files inspected |
| Advisory source refresh | `npm run security:advisory-sources -- --refresh --json` | Ready; 9 active sources; Linear payload still points at `ITO-57` for sync |
| npm audit | `npm audit --audit-level=moderate` | 0 vulnerabilities |
| npm signatures | `npm audit signatures` | 241 verified registry signatures; 30 verified attestations |
| Dashboard renderer | `node tests/scripts/operator-readiness-dashboard.test.js` | 7 passed, 0 failed |
## 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 coming-soon
self-serve publishing surface.
- ECC Tools billing/native-payments copy remains blocked until live
Marketplace-managed test-account readback returns an announcement-ready gate.
- Release notes, X, LinkedIn, GitHub release, and longform copy still need final
live URLs after release/package/plugin URLs exist.
- The local checkout still has unrelated untracked `docs/drafts/`, so a strict
clean-checkout release pass remains required before real publication.
## Result
The public PR queue, issue queue, and discussion queue are clear, and the rc.1
preview pack passed the main Node, Rust, release-surface, harness, observability,
and supply-chain gates on May 16, 2026. This improves publication readiness but
does not replace the approval-gated release, package, plugin, and announcement
steps in `publication-readiness.md`.

View File

@@ -15,12 +15,20 @@ For the May 13 release-readiness evidence refresh, see
For the May 13 post-hardening evidence refresh after PR #1850 and PR #1851, see
[`publication-evidence-2026-05-13-post-hardening.md`](publication-evidence-2026-05-13-post-hardening.md).
For the May 15 queue, discussion, Linear roadmap, Mini Shai-Hulud/TanStack
follow-up, restore-only cache, AgentShield release-verification, billing-gate,
follow-up, scheduled supply-chain watch, no-lifecycle CI install hardening,
GitHub Actions cache purge, AgentShield release-verification, billing-gate,
AgentShield #86 evidence-pack provenance, and `ecc2` current-dir guard evidence
refresh through PR #1936, see
refresh through PR #1941, see
[`publication-evidence-2026-05-15.md`](publication-evidence-2026-05-15.md).
For the May 16 queue cleanup, recsys skill merge, GateGuard issue triage,
AgentShield #87 plugin-cache runtime-confidence evidence, AgentShield #88
evidence-pack inspect/readback, AgentShield #89 evidence-pack fleet routing,
ECC-Tools #76 fleet-summary consumption, ECC-Tools #77 hosted finding evidence
paths, operator dashboard refresh, and combined final-gate rerun on current
`main`, see
[`publication-evidence-2026-05-16.md`](publication-evidence-2026-05-16.md).
For the operator-facing prompt-to-artifact readiness dashboard from the same
May 15 pass, see
May 16 pass, see
[`operator-readiness-dashboard-2026-05-15.md`](operator-readiness-dashboard-2026-05-15.md).
## Release Identity Matrix
@@ -60,21 +68,21 @@ 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 | Pending final clean-checkout release pass; May 13 evidence branch still had unrelated untracked `docs/drafts/` |
| Harness audit | `npm run harness:audit -- --format json` | 70/70 passing | `publication-evidence-2026-05-13.md`: 70/70 |
| Adapter scorecard | `npm run harness:adapters -- --check` | PASS | `publication-evidence-2026-05-13.md`: PASS, 11 adapters |
| Observability readiness | `npm run observability:ready` | 21/21 passing | `publication-evidence-2026-05-13-post-hardening.md`: 21/21, ready true after release-safety gate refresh |
| 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-16.md` records current `main` with unrelated untracked `docs/drafts/` |
| Harness audit | `npm run harness:audit -- --format json` | 70/70 passing | `publication-evidence-2026-05-16.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-16.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-15.md`: npm registry signatures and attestations verified, 0 moderate-or-higher npm vulnerabilities, Mini Shai-Hulud/TanStack IOC scan clean |
| Root suite | `node tests/run-all.js` | 0 failures | `publication-evidence-2026-05-15.md`: 2442 passed, 0 failed |
| 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-16.md`: npm registry signatures and attestations verified, 0 moderate-or-higher npm vulnerabilities, supply-chain IOC scan clean |
| Root suite | `node tests/run-all.js` | 0 failures | `publication-evidence-2026-05-16.md`: `npm test` passed 2469/2469, 0 failed |
| Markdown lint | `npx markdownlint-cli '**/*.md' --ignore node_modules` | 0 failures | `publication-evidence-2026-05-13.md`: passed after zh-CN CLAUDE list-marker normalization |
| 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 | `publication-evidence-2026-05-13.md`: 18/18 passed |
| Optional Rust surface | `cd ecc2 && cargo test` | 0 failures or explicit deferral | `publication-evidence-2026-05-15.md`: 462/462 passed, existing warnings only after PR #1935 current-dir guard |
| 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-15.md`: platform audit ready, 0 open PRs and 0 open issues across checked repos |
| 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 | `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-16.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 | `node scripts/platform-audit.js --json --allow-untracked docs/drafts/` plus `node scripts/discussion-audit.js --json` | Current queue state mapped to macro-goal deliverables and incomplete gaps | `operator-readiness-dashboard-2026-05-15.md`: live status, command evidence, Linear state, and next work order |
| Operator readiness dashboard | `npm run operator:dashboard -- --allow-untracked docs/drafts/ --write docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-15.md` | Current queue state mapped to macro-goal deliverables and incomplete gaps | `operator-readiness-dashboard-2026-05-15.md`: regenerated from `6c8e909d`, 0 open PRs, 0 open issues, 0 discussion gaps |
## Do Not Publish If

View File

@@ -73,6 +73,7 @@ node scripts/ci/scan-supply-chain-iocs.js --home
npm ci --ignore-scripts
npm audit signatures
npm audit --audit-level=high
node scripts/ci/supply-chain-advisory-sources.js --json
node scripts/ci/validate-workflow-security.js
node tests/scripts/npm-publish-surface.test.js
node tests/run-all.js
@@ -86,8 +87,10 @@ evidence but do not rotate credentials for a docs-only reference.
ECC also runs `.github/workflows/supply-chain-watch.yml` every six hours and on
manual dispatch. The workflow is read-only, disables checkout credential
persistence, installs with `npm ci --ignore-scripts`, verifies npm registry
signatures, runs the IOC scanner fixtures, emits
`supply-chain-ioc-report.json`, and re-validates GitHub Actions hardening rules.
signatures, runs the IOC scanner fixtures, runs
`scripts/ci/supply-chain-advisory-sources.js --refresh --json`, emits
`supply-chain-ioc-report.json` and `supply-chain-advisory-sources.json`, and
re-validates GitHub Actions hardening rules.
Treat a failed scheduled watch as a release blocker until an operator confirms
whether the failure is a newly reported advisory, a stale scanner fixture, a
@@ -96,6 +99,12 @@ needs new indicators, update `scripts/ci/scan-supply-chain-iocs.js`, add fixture
coverage in `tests/ci/scan-supply-chain-iocs.test.js`, refresh this runbook, and
attach the latest JSON artifact to the release evidence.
The advisory-source artifact is the ITO-57 status payload. It records the
trusted source registry, live URL refresh warnings, and a Linear-ready summary.
Refresh source coverage through `npm run security:advisory-sources -- --json`
before changing IOC coverage, and attach the artifact to the next Linear project
status update after each significant merge batch.
## Immediate Response
If ECC or a maintainer machine installed a known-bad package version:

View File

@@ -1,6 +1,6 @@
# Everything Claude Code (ECC) — 智能体指令
这是一个**生产就绪的 AI 编码插件**,提供 60 个专业代理、229 项技能、75 条命令以及自动化钩子工作流,用于软件开发。
这是一个**生产就绪的 AI 编码插件**,提供 60 个专业代理、230 项技能、75 条命令以及自动化钩子工作流,用于软件开发。
**版本:** 2.0.0-rc.1
@@ -147,7 +147,7 @@
```
agents/ — 60 个专业子代理
skills/ — 229 个工作流技能和领域知识
skills/ — 230 个工作流技能和领域知识
commands/ — 75 个斜杠命令
hooks/ — 基于触发的自动化
rules/ — 始终遵循的指导方针(通用 + 每种语言)

View File

@@ -224,7 +224,7 @@ Copy-Item -Recurse rules/typescript "$HOME/.claude/rules/"
/plugin list ecc@ecc
```
**搞定!** 你现在可以使用 60 个智能体、229 项技能和 75 个命令了。
**搞定!** 你现在可以使用 60 个智能体、230 项技能和 75 个命令了。
***
@@ -1138,7 +1138,7 @@ opencode
|---------|-------------|----------|--------|
| 智能体 | PASS: 60 个 | PASS: 12 个 | **Claude Code 领先** |
| 命令 | PASS: 75 个 | PASS: 35 个 | **Claude Code 领先** |
| 技能 | PASS: 229 项 | 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 |
| **技能** | 229 | 共享 | 10 (原生格式) | 37 |
| **技能** | 230 | 共享 | 10 (原生格式) | 37 |
| **钩子事件** | 8 种类型 | 15 种类型 | 暂无 | 11 种类型 |
| **钩子脚本** | 20+ 个脚本 | 16 个脚本 (DRY 适配器) | N/A | 插件钩子 |
| **规则** | 34 (通用 + 语言) | 34 (YAML 前页) | 基于指令 | 13 条指令 |

View File

@@ -64,6 +64,7 @@
"schemas/",
"scripts/catalog.js",
"scripts/ci/scan-supply-chain-iocs.js",
"scripts/ci/supply-chain-advisory-sources.js",
"scripts/consult.js",
"scripts/auto-update.js",
"scripts/claw.js",
@@ -76,6 +77,7 @@
"scripts/harness-adapter-compliance.js",
"scripts/harness-audit.js",
"scripts/observability-readiness.js",
"scripts/operator-readiness-dashboard.js",
"scripts/platform-audit.js",
"scripts/hooks/",
"scripts/install-apply.js",
@@ -296,9 +298,11 @@
"harness:adapters": "node scripts/harness-adapter-compliance.js",
"harness:audit": "node scripts/harness-audit.js",
"observability:ready": "node scripts/observability-readiness.js",
"operator:dashboard": "node scripts/operator-readiness-dashboard.js",
"platform:audit": "node scripts/platform-audit.js",
"discussion:audit": "node scripts/discussion-audit.js",
"security:ioc-scan": "node scripts/ci/scan-supply-chain-iocs.js",
"security:advisory-sources": "node scripts/ci/supply-chain-advisory-sources.js",
"claw": "node scripts/claw.js",
"orchestrate:status": "node scripts/orchestration-status.js",
"orchestrate:worker": "bash scripts/orchestrate-codex-worker.sh",

View File

@@ -0,0 +1,469 @@
#!/usr/bin/env node
/**
* Build a refreshable source report for active supply-chain advisories.
*/
const fs = require('fs');
const http = require('http');
const https = require('https');
const path = require('path');
const DEFAULT_GENERATED_AT = () => new Date().toISOString();
const DEFAULT_TIMEOUT_MS = 5000;
const MAX_REDIRECTS = 5;
const DEFAULT_ADVISORY_SOURCES = [
{
id: 'tanstack-postmortem',
title: 'TanStack npm supply-chain compromise postmortem',
publisher: 'TanStack',
url: 'https://tanstack.com/blog/npm-supply-chain-compromise-postmortem',
sourceType: 'primary-incident-postmortem',
ecosystems: ['npm', 'GitHub Actions'],
signals: ['tanstack', 'trusted-publishing-limits', 'github-actions-cache-poisoning'],
},
{
id: 'github-ghsa-g7cv-rxg3-hmpx',
title: 'GitHub Advisory GHSA-g7cv-rxg3-hmpx / CVE-2026-45321',
publisher: 'GitHub Advisory Database',
url: 'https://github.com/advisories/GHSA-g7cv-rxg3-hmpx',
sourceType: 'security-advisory',
ecosystems: ['npm', 'AI developer tooling'],
signals: ['credential-theft', 'malicious-lifecycle-script', 'tanstack'],
},
{
id: 'tanstack-followup',
title: 'TanStack incident follow-up',
publisher: 'TanStack',
url: 'https://tanstack.com/blog/incident-followup',
sourceType: 'primary-incident-followup',
ecosystems: ['npm', 'GitHub Actions'],
signals: ['remediation', 'trusted-publishing-limits'],
},
{
id: 'stepsecurity-mini-shai-hulud',
title: 'Mini Shai-Hulud campaign analysis',
publisher: 'StepSecurity',
url: 'https://www.stepsecurity.io/blog/mini-shai-hulud-is-back-a-self-spreading-supply-chain-attack-hits-the-npm-ecosystem',
sourceType: 'incident-analysis',
ecosystems: ['npm', 'PyPI', 'AI developer tooling'],
signals: ['mini-shai-hulud', 'claude-code-persistence', 'vscode-persistence', 'os-persistence'],
},
{
id: 'openai-tanstack-response',
title: 'OpenAI response to the TanStack npm supply-chain attack',
publisher: 'OpenAI',
url: 'https://openai.com/index/our-response-to-the-tanstack-npm-supply-chain-attack/',
sourceType: 'vendor-response',
ecosystems: ['npm', 'AI developer tooling'],
signals: ['codex-update', 'developer-tooling-exposure', 'remediation'],
},
{
id: 'wiz-mini-shai-hulud',
title: 'Mini Shai-Hulud broader npm campaign coverage',
publisher: 'Wiz',
url: 'https://www.wiz.io/blog/mini-shai-hulud-strikes-again-tanstack-more-npm-packages-compromised',
sourceType: 'incident-analysis',
ecosystems: ['npm', 'PyPI', 'AI developer tooling'],
signals: ['mini-shai-hulud', 'opensearch', 'mistral-ai', 'uipath', 'squawk'],
},
{
id: 'socket-node-ipc',
title: 'node-ipc package compromise',
publisher: 'Socket',
url: 'https://socket.dev/blog/node-ipc-package-compromised',
sourceType: 'incident-analysis',
ecosystems: ['npm'],
signals: ['node-ipc', 'payload-hash', 'destructive-package-behavior'],
},
{
id: 'npm-trusted-publishers',
title: 'npm trusted publishing documentation',
publisher: 'npm',
url: 'https://docs.npmjs.com/trusted-publishers/',
sourceType: 'registry-control-reference',
ecosystems: ['npm', 'GitHub Actions'],
signals: ['trusted-publishing-limits', 'provenance'],
},
{
id: 'cisa-npm-compromise',
title: 'CISA widespread supply-chain compromise impacting npm ecosystem',
publisher: 'CISA',
url: 'https://www.cisa.gov/news-events/alerts/2025/09/23/widespread-supply-chain-compromise-impacting-npm-ecosystem',
sourceType: 'government-alert',
ecosystems: ['npm'],
signals: ['incident-response', 'credential-rotation', 'npm-compromise'],
},
];
function normalizeArray(values) {
return Array.isArray(values) ? values.filter(Boolean) : [];
}
function createCheck(id, status, summary, fix) {
return { id, status, summary, fix };
}
function uniqueValues(sources, field) {
return new Set(sources.flatMap(source => normalizeArray(source[field])));
}
function validateSources(sources) {
const checks = [];
const ids = new Set();
const duplicateIds = [];
const invalidSources = [];
for (const source of sources) {
if (ids.has(source.id)) duplicateIds.push(source.id);
ids.add(source.id);
if (!source.id || !source.title || !source.publisher || !source.url) {
invalidSources.push(source.id || '(missing id)');
}
}
checks.push(createCheck(
'advisory-source-count',
sources.length >= 8 ? 'pass' : 'fail',
`${sources.length} advisory sources registered`,
'Track at least eight sources spanning primary advisories, vendor responses, and registry controls.',
));
checks.push(createCheck(
'advisory-source-shape',
invalidSources.length === 0 && duplicateIds.length === 0 ? 'pass' : 'fail',
invalidSources.length === 0 && duplicateIds.length === 0
? 'all sources include id, title, publisher, and URL'
: `invalid sources: ${[...invalidSources, ...duplicateIds].join(', ')}`,
'Fix duplicate or incomplete advisory source records before relying on the watch artifact.',
));
const ecosystems = uniqueValues(sources, 'ecosystems');
const requiredEcosystems = ['npm', 'PyPI', 'AI developer tooling'];
const missingEcosystems = requiredEcosystems.filter(ecosystem => !ecosystems.has(ecosystem));
checks.push(createCheck(
'advisory-ecosystem-coverage',
missingEcosystems.length === 0 ? 'pass' : 'fail',
missingEcosystems.length === 0
? 'sources cover npm, PyPI, and AI developer tooling'
: `missing ecosystem coverage: ${missingEcosystems.join(', ')}`,
'Add sources for every active ecosystem touched by the campaign.',
));
const signals = uniqueValues(sources, 'signals');
const requiredSignals = [
'tanstack',
'mini-shai-hulud',
'claude-code-persistence',
'vscode-persistence',
'os-persistence',
'node-ipc',
'trusted-publishing-limits',
'remediation',
];
const missingSignals = requiredSignals.filter(signal => !signals.has(signal));
checks.push(createCheck(
'advisory-signal-coverage',
missingSignals.length === 0 ? 'pass' : 'fail',
missingSignals.length === 0
? 'sources cover package versions, persistence hooks, provenance limits, and remediation'
: `missing signal coverage: ${missingSignals.join(', ')}`,
'Update the source registry before adding or removing scanner indicators.',
));
return checks;
}
function refreshStatusFromResult(result) {
if (result && result.ok) {
return {
status: 'ok',
statusCode: result.statusCode || null,
finalUrl: result.finalUrl || null,
checkedAt: result.checkedAt || null,
};
}
return {
status: 'warning',
statusCode: result && result.statusCode ? result.statusCode : null,
finalUrl: result && result.finalUrl ? result.finalUrl : null,
checkedAt: result && result.checkedAt ? result.checkedAt : null,
error: result && result.error ? String(result.error) : 'source refresh failed',
};
}
async function defaultFetchSource(source, options = {}) {
const checkedAt = options.checkedAt || DEFAULT_GENERATED_AT();
try {
const result = await requestUrl(source.url, {
timeoutMs: options.timeoutMs || DEFAULT_TIMEOUT_MS,
redirectsRemaining: MAX_REDIRECTS,
method: 'HEAD',
});
if (result.statusCode === 405 || result.statusCode === 403) {
return requestUrl(source.url, {
timeoutMs: options.timeoutMs || DEFAULT_TIMEOUT_MS,
redirectsRemaining: MAX_REDIRECTS,
method: 'GET',
checkedAt,
});
}
return { ...result, checkedAt };
} catch (error) {
return {
ok: false,
statusCode: null,
finalUrl: source.url,
checkedAt,
error: error.message,
};
}
}
function requestUrl(url, options) {
return new Promise(resolve => {
const parsed = new URL(url);
const client = parsed.protocol === 'http:' ? http : https;
const request = client.request(parsed, {
method: options.method || 'HEAD',
timeout: options.timeoutMs || DEFAULT_TIMEOUT_MS,
headers: {
'User-Agent': 'ecc-supply-chain-watch/2.0',
Accept: 'text/html,application/json;q=0.9,*/*;q=0.8',
},
}, response => {
const statusCode = response.statusCode || 0;
const location = response.headers.location;
if (
statusCode >= 300
&& statusCode < 400
&& location
&& options.redirectsRemaining > 0
) {
response.resume();
const nextUrl = new URL(location, parsed).toString();
resolve(requestUrl(nextUrl, {
...options,
redirectsRemaining: options.redirectsRemaining - 1,
}));
return;
}
response.resume();
response.on('end', () => {
resolve({
ok: statusCode >= 200 && statusCode < 400,
statusCode,
finalUrl: url,
});
});
});
request.on('timeout', () => {
request.destroy(new Error(`timed out after ${options.timeoutMs || DEFAULT_TIMEOUT_MS}ms`));
});
request.on('error', error => {
resolve({
ok: false,
statusCode: null,
finalUrl: url,
error: error.message,
});
});
request.end();
});
}
function buildLinearStatus(report, sources) {
const primaryEvidence = sources
.filter(source => [
'primary-incident-postmortem',
'security-advisory',
'vendor-response',
'incident-analysis',
].includes(source.sourceType))
.slice(0, 5)
.map(source => `${source.publisher}: ${source.title}`);
return {
issueId: 'ITO-57',
status: 'in_progress',
summary: report.ready
? 'Advisory sources current; scheduled supply-chain watch now emits source refresh evidence.'
: 'Advisory source coverage needs repair before release readiness.',
evidence: primaryEvidence,
remaining: 'Linear status synchronization still needs a live connector/status-update pass after each significant merge batch.',
};
}
async function buildAdvisorySourceReport(options = {}) {
const generatedAt = options.generatedAt || DEFAULT_GENERATED_AT();
const sources = (options.sources || DEFAULT_ADVISORY_SOURCES).map(source => ({
...source,
ecosystems: normalizeArray(source.ecosystems),
signals: normalizeArray(source.signals),
}));
const checks = validateSources(sources);
const refreshEnabled = Boolean(options.refresh);
const fetchSource = options.fetchSource || defaultFetchSource;
let refreshWarnings = 0;
const reportSources = [];
for (const source of sources) {
let refreshStatus = { status: 'not_requested' };
if (refreshEnabled && source.refresh !== false) {
const result = await fetchSource(source, {
timeoutMs: options.timeoutMs || DEFAULT_TIMEOUT_MS,
checkedAt: generatedAt,
});
refreshStatus = refreshStatusFromResult(result);
if (refreshStatus.status !== 'ok') refreshWarnings += 1;
}
reportSources.push({ ...source, refreshStatus });
}
if (refreshEnabled) {
checks.push(createCheck(
'advisory-refresh',
refreshWarnings === 0 ? 'pass' : 'warn',
refreshWarnings === 0
? 'all advisory source URLs responded during refresh'
: `${refreshWarnings} advisory source URL(s) returned warnings during refresh`,
'Review warning sources manually before changing IOC coverage or release evidence.',
));
} else {
checks.push(createCheck(
'advisory-refresh',
'pass',
'live advisory refresh not requested for this offline source contract report',
'Run with --refresh in the scheduled watch to capture live URL status evidence.',
));
}
const ready = checks.every(check => check.status !== 'fail');
const report = {
schema_version: 'ecc.supply-chain-advisory-sources.v1',
generatedAt,
ready,
refresh: {
enabled: refreshEnabled,
ok: refreshEnabled ? refreshWarnings === 0 : null,
warningCount: refreshWarnings,
},
sources: reportSources,
checks,
};
report.linear = {
status: buildLinearStatus(report, reportSources),
};
return report;
}
function parseArgs(argv) {
const options = {};
for (let i = 0; i < argv.length; i += 1) {
const arg = argv[i];
if (arg === '--help' || arg === '-h') {
options.help = true;
} else if (arg === '--json') {
options.json = true;
} else if (arg === '--refresh') {
options.refresh = true;
} else if (arg === '--strict-refresh') {
options.strictRefresh = true;
options.refresh = true;
} else if (arg === '--generated-at') {
options.generatedAt = argv[++i];
} else if (arg === '--timeout-ms') {
options.timeoutMs = Number(argv[++i]);
if (!Number.isFinite(options.timeoutMs) || options.timeoutMs <= 0) {
throw new Error('--timeout-ms must be a positive number');
}
} else if (arg === '--write') {
options.writePath = argv[++i];
if (!options.writePath) throw new Error('--write requires a path');
} else {
throw new Error(`Unknown argument: ${arg}`);
}
}
return options;
}
function printHelp() {
console.log(`Usage: node scripts/ci/supply-chain-advisory-sources.js [options]
Build the active supply-chain advisory source report used by the scheduled
watch workflow and Linear ITO-57 status updates.
Options:
--json Emit JSON instead of text
--refresh Check source URLs and record warning status
--strict-refresh Fail when a refreshed source URL returns a warning
--generated-at <ts> Override the report timestamp
--timeout-ms <n> Per-source refresh timeout (default: ${DEFAULT_TIMEOUT_MS})
--write <path> Write the report to a file
--help, -h Show this help
`);
}
function renderText(report) {
const lines = [
`Supply-chain advisory sources: ${report.ready ? 'ready' : 'blocked'}`,
`Sources: ${report.sources.length}`,
`Refresh: ${report.refresh.enabled ? (report.refresh.ok ? 'ok' : `warnings=${report.refresh.warningCount}`) : 'not requested'}`,
`Linear ${report.linear.status.issueId}: ${report.linear.status.summary}`,
];
for (const check of report.checks) {
lines.push(`- ${check.status.toUpperCase()} ${check.id}: ${check.summary}`);
}
return `${lines.join('\n')}\n`;
}
function writeReport(report, writePath) {
const absolutePath = path.resolve(writePath);
fs.mkdirSync(path.dirname(absolutePath), { recursive: true });
fs.writeFileSync(absolutePath, `${JSON.stringify(report, null, 2)}\n`);
}
if (require.main === module) {
(async () => {
try {
const options = parseArgs(process.argv.slice(2));
if (options.help) {
printHelp();
process.exit(0);
}
const report = await buildAdvisorySourceReport(options);
if (options.writePath) writeReport(report, options.writePath);
if (options.json) {
console.log(JSON.stringify(report, null, 2));
} else {
process.stdout.write(renderText(report));
}
const failed = !report.ready || (options.strictRefresh && report.refresh.enabled && !report.refresh.ok);
process.exit(failed ? 1 : 0);
} catch (error) {
console.error(error.message);
process.exit(2);
}
})();
}
module.exports = {
DEFAULT_ADVISORY_SOURCES,
buildAdvisorySourceReport,
parseArgs,
renderText,
};

View File

@@ -52,7 +52,7 @@ function buildContextBar(remaining) {
if (used < 50) return ` \x1b[32m${bar} ${used}%\x1b[0m`;
if (used < 65) return ` \x1b[33m${bar} ${used}%\x1b[0m`;
if (used < 80) return ` \x1b[38;5;208m${bar} ${used}%\x1b[0m`;
return ` \x1b[5;31m${bar} ${used}%\x1b[0m`;
return ` \x1b[1;31m${bar} ${used}%\x1b[0m`;
}
/**
@@ -137,7 +137,7 @@ function runStatusline() {
parts.push(dur);
}
if (parts.length > 0) {
metricsStr = `\x1b[36m${parts.join(' ')}\x1b[0m`;
metricsStr = `\x1b[38;5;117m${parts.join(' ')}\x1b[0m`;
}
}
@@ -149,7 +149,7 @@ function runStatusline() {
const segments = [`\x1b[2m${model}\x1b[0m`];
if (task) {
segments.push(`\x1b[1m${task}\x1b[0m`);
segments.push(`\x1b[1;97m${task}\x1b[0m`);
}
if (metricsStr) {
segments.push(metricsStr);

View File

@@ -0,0 +1,660 @@
#!/usr/bin/env node
'use strict';
const fs = require('fs');
const path = require('path');
const { spawnSync } = require('child_process');
const { buildReport: buildPlatformReport } = require('./platform-audit');
const SCHEMA_VERSION = 'ecc.operator-readiness-dashboard.v1';
const DEFAULT_THRESHOLDS = Object.freeze({
maxOpenPrs: 20,
maxOpenIssues: 20,
maxDirtyFiles: 0,
});
function usage() {
console.log([
'Usage: node scripts/operator-readiness-dashboard.js [options]',
'',
'Generate the ECC operator readiness dashboard and prompt-to-artifact audit.',
'',
'Options:',
' --format <text|json|markdown>',
' Output format (default: markdown)',
' --json Alias for --format json',
' --markdown Alias for --format markdown',
' --write <path> Write json or markdown output to a file',
' --root <dir> Repository root to inspect (default: cwd)',
' --repo <owner/repo> GitHub repo to inspect; repeatable',
' --skip-github Skip live GitHub queue/discussion checks',
' --max-open-prs <n> PR budget passed through to platform:audit',
' --max-open-issues <n> Issue budget passed through to platform:audit',
' --max-dirty-files <n> Dirty-file budget passed through to platform:audit',
' --allow-untracked <path> Ignore untracked files under path; repeatable',
' --use-env-github-token Keep GITHUB_TOKEN when invoking gh',
' --generated-at <iso> Override generatedAt for deterministic tests',
' --exit-code Return 2 when the objective is not ready',
' --help, -h Show this help',
].join('\n'));
}
function readValue(args, index, flagName) {
const value = args[index + 1];
if (!value || value.startsWith('--')) {
throw new Error(`${flagName} requires a value`);
}
return value;
}
function parseIntegerFlag(value, flagName) {
const parsed = Number.parseInt(value, 10);
if (!Number.isFinite(parsed) || parsed < 0) {
throw new Error(`Invalid ${flagName}: ${value}`);
}
return parsed;
}
function normalizeRelativePrefix(value) {
const normalized = String(value || '')
.replace(/\\/g, '/')
.replace(/^\.\/+/, '')
.replace(/\/+$/, '');
return normalized ? `${normalized}/` : '';
}
function parseArgs(argv) {
const args = argv.slice(2);
const parsed = {
allowUntracked: [],
exitCode: false,
format: 'markdown',
generatedAt: null,
help: false,
repos: [],
root: path.resolve(process.cwd()),
skipGithub: false,
thresholds: { ...DEFAULT_THRESHOLDS },
useEnvGithubToken: false,
writePath: null,
};
for (let index = 0; index < args.length; index += 1) {
const arg = args[index];
if (arg === '--help' || arg === '-h') {
parsed.help = true;
continue;
}
if (arg === '--format') {
parsed.format = readValue(args, index, arg).toLowerCase();
index += 1;
continue;
}
if (arg.startsWith('--format=')) {
parsed.format = arg.slice('--format='.length).toLowerCase();
continue;
}
if (arg === '--json') {
parsed.format = 'json';
continue;
}
if (arg === '--markdown') {
parsed.format = 'markdown';
continue;
}
if (arg === '--write') {
parsed.writePath = path.resolve(readValue(args, index, arg));
index += 1;
continue;
}
if (arg.startsWith('--write=')) {
parsed.writePath = path.resolve(arg.slice('--write='.length));
continue;
}
if (arg === '--root') {
parsed.root = path.resolve(readValue(args, index, arg));
index += 1;
continue;
}
if (arg.startsWith('--root=')) {
parsed.root = path.resolve(arg.slice('--root='.length));
continue;
}
if (arg === '--repo') {
parsed.repos.push(readValue(args, index, arg));
index += 1;
continue;
}
if (arg.startsWith('--repo=')) {
parsed.repos.push(arg.slice('--repo='.length));
continue;
}
if (arg === '--skip-github') {
parsed.skipGithub = true;
continue;
}
if (arg === '--allow-untracked') {
parsed.allowUntracked.push(readValue(args, index, arg));
index += 1;
continue;
}
if (arg.startsWith('--allow-untracked=')) {
parsed.allowUntracked.push(arg.slice('--allow-untracked='.length));
continue;
}
if (arg === '--max-open-prs') {
parsed.thresholds.maxOpenPrs = parseIntegerFlag(readValue(args, index, arg), arg);
index += 1;
continue;
}
if (arg.startsWith('--max-open-prs=')) {
parsed.thresholds.maxOpenPrs = parseIntegerFlag(arg.slice('--max-open-prs='.length), '--max-open-prs');
continue;
}
if (arg === '--max-open-issues') {
parsed.thresholds.maxOpenIssues = parseIntegerFlag(readValue(args, index, arg), arg);
index += 1;
continue;
}
if (arg.startsWith('--max-open-issues=')) {
parsed.thresholds.maxOpenIssues = parseIntegerFlag(arg.slice('--max-open-issues='.length), '--max-open-issues');
continue;
}
if (arg === '--max-dirty-files') {
parsed.thresholds.maxDirtyFiles = parseIntegerFlag(readValue(args, index, arg), arg);
index += 1;
continue;
}
if (arg.startsWith('--max-dirty-files=')) {
parsed.thresholds.maxDirtyFiles = parseIntegerFlag(arg.slice('--max-dirty-files='.length), '--max-dirty-files');
continue;
}
if (arg === '--use-env-github-token') {
parsed.useEnvGithubToken = true;
continue;
}
if (arg === '--generated-at') {
parsed.generatedAt = readValue(args, index, arg);
index += 1;
continue;
}
if (arg.startsWith('--generated-at=')) {
parsed.generatedAt = arg.slice('--generated-at='.length);
continue;
}
if (arg === '--exit-code') {
parsed.exitCode = true;
continue;
}
throw new Error(`Unknown argument: ${arg}`);
}
if (!['text', 'json', 'markdown'].includes(parsed.format)) {
throw new Error(`Invalid format: ${parsed.format}. Use text, json, or markdown.`);
}
if (parsed.writePath && parsed.format === 'text') {
throw new Error('--write requires --json, --markdown, or --format json|markdown');
}
parsed.allowUntracked = parsed.allowUntracked.map(normalizeRelativePrefix).filter(Boolean);
return parsed;
}
function readText(rootDir, relativePath) {
try {
return fs.readFileSync(path.join(rootDir, relativePath), 'utf8');
} catch (_error) {
return '';
}
}
function fileExists(rootDir, relativePath) {
return fs.existsSync(path.join(rootDir, relativePath));
}
function includesAll(text, needles) {
return needles.every(needle => text.includes(needle));
}
function runCommand(command, args, options = {}) {
const result = spawnSync(command, args, {
cwd: options.cwd,
encoding: 'utf8',
maxBuffer: 10 * 1024 * 1024,
});
if (result.error || result.status !== 0) {
return null;
}
return (result.stdout || '').trim();
}
function readPackage(rootDir) {
const text = readText(rootDir, 'package.json');
if (!text.trim()) {
return {};
}
try {
return JSON.parse(text);
} catch (_error) {
return {};
}
}
function buildRequirement(id, requirement, artifact, status, evidence, gap) {
return { id, requirement, artifact, status, evidence, gap };
}
function isCurrentOrComplete(status) {
return status === 'current' || status === 'complete';
}
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 previewManifest = readText(rootDir, 'docs/releases/2.0.0-rc.1/preview-pack-manifest.md');
const progressSync = readText(rootDir, 'docs/architecture/progress-sync-contract.md');
const observabilityReadiness = readText(rootDir, 'docs/architecture/observability-readiness.md');
const stalePrSalvage = readText(rootDir, 'docs/stale-pr-salvage-ledger.md');
const supplyChainRunbook = readText(rootDir, 'docs/security/supply-chain-incident-response.md');
const supplyChainWorkflow = readText(rootDir, '.github/workflows/supply-chain-watch.yml');
const packageJson = readPackage(rootDir);
const scripts = packageJson.scripts || {};
const githubLive = !platformReport.github.skipped && platformReport.github.totals.errors === 0;
const queuesCurrent = githubLive
&& platformReport.github.totals.openPrs <= platformReport.thresholds.maxOpenPrs
&& platformReport.github.totals.openIssues <= platformReport.thresholds.maxOpenIssues;
const discussionsCurrent = githubLive
&& platformReport.github.totals.discussionsNeedingMaintainerTouch === 0
&& platformReport.github.totals.discussionsMissingAcceptedAnswer === 0;
return [
buildRequirement(
'public-pr-budget',
'Keep public PRs below 20',
'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`
: 'live GitHub queue readback was skipped or failed',
queuesCurrent ? 'repeat before release' : 'run live platform:audit and drain PR queue'
),
buildRequirement(
'public-issue-budget',
'Keep public issues below 20',
'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`
: 'live GitHub queue readback was skipped or failed',
queuesCurrent ? 'repeat before release' : 'run live platform:audit and drain issue queue'
),
buildRequirement(
'repository-discussions',
'Respond and manage repository discussions',
'scripts/platform-audit.js discussion summary',
discussionsCurrent ? 'current' : 'in_progress',
githubLive
? `${platformReport.github.totals.discussionsNeedingMaintainerTouch} need maintainer touch; ${platformReport.github.totals.discussionsMissingAcceptedAnswer} answerable discussions missing accepted answer`
: 'live discussion readback was skipped or failed',
discussionsCurrent ? 'repeat before release' : 'respond, answer, or route remaining discussions'
),
buildRequirement(
'completion-dashboard',
'Build ITO-44 completion dashboard into a repeatable command',
'npm run operator:dashboard',
scripts['operator:dashboard'] === 'node scripts/operator-readiness-dashboard.js'
&& fileExists(rootDir, 'scripts/operator-readiness-dashboard.js')
? 'complete'
: 'in_progress',
scripts['operator:dashboard'] === 'node scripts/operator-readiness-dashboard.js'
? 'operator:dashboard package script exists'
: 'operator:dashboard package script missing',
'keep generated dashboard attached to publication evidence'
),
buildRequirement(
'ecc-preview-pack',
'ECC 2.0 preview pack ready',
'docs/releases/2.0.0-rc.1/preview-pack-manifest.md',
includesAll(previewManifest, ['publication-readiness.md', 'release-notes.md', 'quickstart.md']) ? 'in_progress' : 'not_complete',
includesAll(previewManifest, ['publication-readiness.md', 'release-notes.md', 'quickstart.md'])
? 'preview pack manifest is in-tree'
: 'preview pack manifest is incomplete',
'final clean-checkout release approval and publish evidence still pending'
),
buildRequirement(
'hermes-specialized-skills',
'Include Hermes specialized skills safely',
'docs/HERMES-SETUP.md and skills/hermes-imports/SKILL.md',
fileExists(rootDir, 'docs/HERMES-SETUP.md') && fileExists(rootDir, 'skills/hermes-imports/SKILL.md')
? 'in_progress'
: 'not_complete',
fileExists(rootDir, 'docs/HERMES-SETUP.md') && fileExists(rootDir, 'skills/hermes-imports/SKILL.md')
? 'Hermes setup and import skill are present'
: 'Hermes setup/import artifacts missing',
'final preview-pack smoke and release review pending'
),
buildRequirement(
'naming-and-plugin-publication',
'Prepare name-change, Claude plugin, and Codex plugin paths',
'naming-and-publication-matrix plus publication-readiness',
includesAll(namingMatrix, ['Claude plugin', 'Codex plugin', 'npm package', 'Publication Paths'])
&& includesAll(publicationReadiness, ['Claude plugin', 'Codex plugin'])
? 'in_progress'
: 'not_complete',
'naming matrix and plugin readiness gates exist',
'real tag/push, marketplace submission, and final channel choice remain approval-gated'
),
buildRequirement(
'release-notes-and-notifications',
'Prepare release notes, articles, tweets, and push notifications',
'docs/releases/2.0.0-rc.1 social and release-copy files',
fileExists(rootDir, 'docs/releases/2.0.0-rc.1/release-notes.md')
&& fileExists(rootDir, 'docs/releases/2.0.0-rc.1/x-thread.md')
&& fileExists(rootDir, 'docs/releases/2.0.0-rc.1/linkedin-post.md')
? 'in_progress'
: 'not_complete',
'release notes, X thread, and LinkedIn draft are present',
'URL-backed refresh and publish approval still pending'
),
buildRequirement(
'agentshield-enterprise-iteration',
'Advance AgentShield enterprise iteration',
'AgentShield PR evidence plus enterprise roadmap',
roadmap.includes('AgentShield Enterprise Iteration') && roadmap.includes('#78-#89')
? 'in_progress'
: 'not_complete',
'AgentShield enterprise PR evidence is mirrored in the GA roadmap',
'cross-harness policy integration and richer fleet-review workflow remain pending after fleet-summary consumption and evidence-path surfacing shipped'
),
buildRequirement(
'ecc-tools-next-level',
'Advance ECC Tools native payments and AI-native harness-agnostic app',
'ECC Tools PR evidence, billing gate, hosted analysis lanes',
includesAll(roadmap, ['ECC-Tools PR #77', 'hosted promotion', 'announcementGate'])
? 'in_progress'
: 'not_complete',
'billing announcement gate, hosted analysis lanes, AgentShield fleet-summary consumption, and hosted finding evidence paths are mirrored in the GA roadmap',
'live Marketplace test-account readback, hosted promotion telemetry, and richer operator review UX pending'
),
buildRequirement(
'legacy-salvage',
'Audit, prune, or attach legacy work',
'docs/stale-pr-salvage-ledger.md and legacy inventory',
stalePrSalvage.includes('Manual review tail') || roadmap.includes('ITO-55')
? 'in_progress'
: 'not_complete',
'legacy salvage ledger and ITO-55 tracking are present',
'final translation/manual-review tail remains'
),
buildRequirement(
'linear-roadmap-and-progress',
'Keep Linear roadmap detailed and progress tracking synchronized',
'Linear project mirror plus progress-sync contract',
includesAll(roadmap, ['ITO-44', 'ITO-59', 'Linear']) && includesAll(progressSync, ['GitHub', 'Linear', 'handoff', 'repo roadmap'])
? 'in_progress'
: 'not_complete',
'repo mirror and progress-sync contract are present',
'recurring Linear status sync and productized realtime sync remain pending'
),
buildRequirement(
'observability-for-self-use',
'Provide ECC 2.0 observability for self-use',
'observability readiness gate',
scripts['observability:ready'] === 'node scripts/observability-readiness.js'
&& includesAll(observabilityReadiness, ['observability-readiness.js'])
? 'complete'
: 'in_progress',
scripts['observability:ready'] === 'node scripts/observability-readiness.js'
? 'observability:ready command and readiness doc exist'
: 'observability readiness command missing',
'runtime/dashboard implementation can continue after release gates'
),
buildRequirement(
'supply-chain-local-protection',
'Keep Mini Shai-Hulud/TanStack protection loop current',
'supply-chain watch plus runbook',
includesAll(supplyChainRunbook, ['TanStack', 'Mini Shai-Hulud', 'scan-supply-chain-iocs.js', 'supply-chain-advisory-sources.js'])
&& includesAll(supplyChainWorkflow, ['supply-chain-advisory-sources.js', 'supply-chain-advisory-sources.json'])
&& scripts['security:advisory-sources'] === 'node scripts/ci/supply-chain-advisory-sources.js'
&& fileExists(rootDir, '.github/workflows/supply-chain-watch.yml')
? 'current'
: 'in_progress',
scripts['security:advisory-sources'] === 'node scripts/ci/supply-chain-advisory-sources.js'
? 'scheduled supply-chain watch now emits IOC and advisory-source refresh artifacts'
: 'scheduled supply-chain watch or advisory-source command is missing',
'Linear status synchronization remains ITO-57 follow-up after each significant merge batch'
),
];
}
function buildReport(options) {
const rootDir = path.resolve(options.root);
const generatedAt = options.generatedAt || new Date().toISOString();
const platformReport = buildPlatformReport({
allowUntracked: options.allowUntracked,
exitCode: false,
format: 'json',
help: false,
repos: options.repos,
root: rootDir,
skipGithub: options.skipGithub,
thresholds: options.thresholds,
useEnvGithubToken: options.useEnvGithubToken,
writePath: null,
});
const requirements = buildRequirements(rootDir, platformReport);
const incompleteRequirements = requirements.filter(item => !isCurrentOrComplete(item.status));
const topActions = incompleteRequirements.map(item => ({
id: item.id,
summary: item.requirement,
fix: item.gap,
}));
const head = runCommand('git', ['rev-parse', 'HEAD'], { cwd: rootDir });
return {
schema_version: SCHEMA_VERSION,
generatedAt,
root: rootDir,
head,
ready: incompleteRequirements.length === 0,
dashboardReady: platformReport.ready,
publicationReady: false,
platform: {
ready: platformReport.ready,
branch: platformReport.git.branch,
blockingDirtyCount: platformReport.git.blockingDirtyCount,
ignoredDirtyCount: platformReport.git.ignoredDirty.length,
openPrs: platformReport.github.totals.openPrs,
openIssues: platformReport.github.totals.openIssues,
discussionsNeedingMaintainerTouch: platformReport.github.totals.discussionsNeedingMaintainerTouch,
discussionsMissingAcceptedAnswer: platformReport.github.totals.discussionsMissingAcceptedAnswer,
githubErrors: platformReport.github.totals.errors,
githubSkipped: platformReport.github.skipped,
},
requirements,
top_actions: topActions,
next_work_order: [
'Regenerate this dashboard from the final release commit before publication evidence is recorded.',
'Continue ITO-57 with Linear status synchronization for the scheduled supply-chain watch advisory-source report.',
'Advance ECC Tools live Marketplace test-account readback before publishing native-payments announcement copy.',
'Resume ITO-45, ITO-46, and ITO-56 only after the generated dashboard and final release gates are refreshed.',
],
};
}
function markdownEscape(value) {
return String(value === undefined || value === null ? '' : value)
.replace(/\|/g, '\\|')
.replace(/\r?\n/g, '<br>');
}
function renderText(report) {
const lines = [
`ECC Operator Readiness Dashboard: ${report.ready ? 'objective ready' : 'work remaining'}`,
`Generated: ${report.generatedAt}`,
`Commit: ${report.head || 'unknown'}`,
`Dashboard ready: ${report.dashboardReady}`,
`Publication ready: ${report.publicationReady}`,
'',
'Platform:',
` PRs: ${report.platform.openPrs}`,
` Issues: ${report.platform.openIssues}`,
` Discussions needing touch: ${report.platform.discussionsNeedingMaintainerTouch}`,
` Missing accepted answers: ${report.platform.discussionsMissingAcceptedAnswer}`,
` Blocking dirty files: ${report.platform.blockingDirtyCount}`,
'',
'Requirements:',
];
for (const item of report.requirements) {
lines.push(` ${item.status.toUpperCase()} ${item.id}: ${item.requirement}`);
}
lines.push('', 'Top actions:');
if (report.top_actions.length === 0) {
lines.push(' none');
} else {
for (const action of report.top_actions) {
lines.push(` - ${action.id}: ${action.fix}`);
}
}
return `${lines.join('\n')}\n`;
}
function renderMarkdown(report) {
const lines = [
'# ECC Operator Readiness Dashboard',
'',
'This dashboard is generated by `npm run operator:dashboard`. It is an operator snapshot, not release approval.',
'',
`Generated: ${report.generatedAt}`,
`Commit: ${report.head || 'unknown'}`,
`Status: ${report.ready ? 'objective ready' : 'work remaining'}`,
'',
'## Current Status',
'',
'| Area | Status | Evidence |',
'| --- | --- | --- |',
`| PR queue | ${report.platform.openPrs < 20 && !report.platform.githubSkipped ? 'Current' : 'Needs work'} | ${report.platform.openPrs} open PRs across tracked repos |`,
`| Issue queue | ${report.platform.openIssues < 20 && !report.platform.githubSkipped ? 'Current' : 'Needs work'} | ${report.platform.openIssues} open issues across tracked repos |`,
`| Discussions | ${report.platform.discussionsNeedingMaintainerTouch === 0 && report.platform.discussionsMissingAcceptedAnswer === 0 && !report.platform.githubSkipped ? 'Current' : 'Needs work'} | ${report.platform.discussionsNeedingMaintainerTouch} need maintainer touch; ${report.platform.discussionsMissingAcceptedAnswer} missing accepted answer |`,
`| Local worktree | ${report.platform.blockingDirtyCount === 0 ? 'Current' : 'Needs work'} | ${report.platform.blockingDirtyCount} blocking dirty files; ${report.platform.ignoredDirtyCount} ignored dirty entries |`,
`| Dashboard generation | ${report.dashboardReady ? 'Current' : 'Needs work'} | platform audit ready: ${report.platform.ready}; GitHub skipped: ${report.platform.githubSkipped} |`,
`| Publication | ${report.publicationReady ? 'Ready' : 'Not complete'} | release, npm, plugin, billing, and announcement gates are tracked below |`,
'',
'## Prompt-To-Artifact Checklist',
'',
'| Objective requirement | Artifact or gate | Status | Evidence | Gap |',
'| --- | --- | --- | --- | --- |',
];
for (const item of report.requirements) {
lines.push(`| ${markdownEscape(item.requirement)} | ${markdownEscape(item.artifact)} | ${markdownEscape(item.status)} | ${markdownEscape(item.evidence)} | ${markdownEscape(item.gap)} |`);
}
lines.push('', '## Top Actions', '');
if (report.top_actions.length === 0) {
lines.push('- none');
} else {
for (const action of report.top_actions) {
lines.push(`- \`${markdownEscape(action.id)}\`: ${markdownEscape(action.fix)}`);
}
}
lines.push('', '## Next Work Order', '');
report.next_work_order.forEach((item, index) => {
lines.push(`${index + 1}. ${item}`);
});
return `${lines.join('\n')}\n`;
}
function renderReport(report, format) {
if (format === 'json') {
return `${JSON.stringify(report, null, 2)}\n`;
}
if (format === 'text') {
return renderText(report);
}
return renderMarkdown(report);
}
function writeOutput(writePath, output) {
fs.mkdirSync(path.dirname(writePath), { recursive: true });
fs.writeFileSync(writePath, output, 'utf8');
}
function main() {
let options;
try {
options = parseArgs(process.argv);
} catch (error) {
console.error(`Error: ${error.message}`);
process.exit(1);
}
if (options.help) {
usage();
return;
}
const report = buildReport(options);
const output = renderReport(report, options.format);
if (options.writePath) {
writeOutput(options.writePath, output);
}
process.stdout.write(output);
if (options.exitCode && !report.ready) {
process.exit(2);
}
}
if (require.main === module) {
main();
}
module.exports = {
buildReport,
parseArgs,
renderMarkdown,
renderReport,
renderText,
};

View File

@@ -268,6 +268,10 @@ function readText(rootDir, relativePath) {
}
}
function fileExists(rootDir, relativePath) {
return fs.existsSync(path.join(rootDir, relativePath));
}
function safeParseJson(text) {
if (!text || !text.trim()) {
return null;
@@ -431,10 +435,20 @@ function buildLocalEvidenceChecks(rootDir) {
'platform-audit-cli-surface',
packageScripts['platform:audit'] === 'node scripts/platform-audit.js'
&& packageScripts['discussion:audit'] === 'node scripts/discussion-audit.js'
&& packageScripts['operator:dashboard'] === 'node scripts/operator-readiness-dashboard.js'
? 'pass'
: 'fail',
'package.json exposes the platform and discussion audit commands',
{ fix: 'Add platform:audit and discussion:audit commands to package.json.' }
'package.json exposes platform, discussion, and operator dashboard audit commands',
{ fix: 'Add platform:audit, discussion:audit, and operator:dashboard commands to package.json.' }
),
buildCheck(
'operator-dashboard-command',
fileExists(rootDir, 'scripts/operator-readiness-dashboard.js')
&& packageScripts['operator:dashboard'] === 'node scripts/operator-readiness-dashboard.js'
? 'pass'
: 'fail',
'operator dashboard is generated by the repeatable ITO-44 command',
{ path: 'scripts/operator-readiness-dashboard.js' }
),
buildCheck(
'roadmap-linear-mirror',
@@ -450,8 +464,11 @@ function buildLocalEvidenceChecks(rootDir) {
),
buildCheck(
'supply-chain-runbook',
includesAll(supplyChain, ['TanStack', 'Mini Shai-Hulud', 'node-ipc', 'scan-supply-chain-iocs.js']) ? 'pass' : 'fail',
'supply-chain runbook covers the current TanStack/Mini Shai-Hulud/node-ipc scanner lane',
includesAll(supplyChain, ['TanStack', 'Mini Shai-Hulud', 'node-ipc', 'scan-supply-chain-iocs.js', 'supply-chain-advisory-sources.js'])
&& packageScripts['security:advisory-sources'] === 'node scripts/ci/supply-chain-advisory-sources.js'
? 'pass'
: 'fail',
'supply-chain runbook covers the current TanStack/Mini Shai-Hulud/node-ipc scanner and advisory-source lanes',
{ path: 'docs/security/supply-chain-incident-response.md' }
),
buildCheck(
@@ -462,7 +479,13 @@ function buildLocalEvidenceChecks(rootDir) {
),
buildCheck(
'operator-readiness-dashboard',
includesAll(operatorDashboard, ['Prompt-To-Artifact Checklist', 'ITO-44', 'ITO-59', 'PR queue', 'Not complete']) ? 'pass' : 'fail',
includesAll(operatorDashboard, [
'This dashboard is generated by `npm run operator:dashboard`',
'Prompt-To-Artifact Checklist',
'PR queue',
'Not complete',
'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-15.md' }
),

View File

@@ -0,0 +1,114 @@
---
name: recsys-pipeline-architect
description: Design composable recommendation, ranking, and feed pipelines using the six-stage Source→Hydrator→Filter→Scorer→Selector→SideEffect framework popularized by xAI's open-sourced For You algorithm. Use this skill whenever the user is building any system that picks "the top K items for a (user, context)" — social feeds, content CMSs, RAG rerankers, task prioritizers, notification triage, search reranking, ad ranking.
origin: community
---
# recsys-pipeline-architect
A spec-and-scaffold skill for building composable recommendation, ranking, and feed pipelines. It encodes the **six-stage pattern** — Source → Hydrator → Filter → Scorer → Selector → SideEffect — popularized by xAI's open-sourced [For You algorithm](https://github.com/xai-org/x-algorithm) (Apache 2.0). This skill is an independent reimplementation of the pattern (MIT) — no code copied from the original.
Upstream: https://github.com/mturac/recsys-pipeline-architect
## When to Use
- User wants to build any system that picks "the top K items for a user/context"
- User asks "how should I rank X" or describes a feed/personalization problem
- User has a scoring function and needs the pipeline plumbing around it
- User wants to migrate from a single relevance score to multi-action prediction with tunable weights
- User is wrapping an LLM/ML scorer and needs filters, hydrators, side-effects, and a runnable scaffold in their stack (TypeScript / Go / Python)
- Triggers: "recommendation system", "feed algorithm", "ranking pipeline", "for you feed", "candidate pipeline", "content recommender", "pipeline architecture for recsys", "RAG retrieval reranker"
## When NOT to Use
- Model architecture work (transformer design, two-tower retrieval, embedding training) — this skill is plumbing *around* the model, not the model itself
- Pure ML training pipelines — the scoring function is the user's responsibility
- Operating a deployed pipeline (monitoring, autoscaling) — out of scope
## The six-stage framework
| # | Stage | Job | Parallel? |
|---|---|---|---|
| 1 | **Source** | Fetch candidates from one or more origins | Yes — multiple sources run in parallel |
| 2 | **Hydrator** | Enrich each candidate with metadata needed for filtering and scoring | Yes — independent hydrators run in parallel |
| 3 | **Filter** | Drop candidates that should never be shown (blocked, expired, duplicate, ineligible) | Sequential — each filter sees fewer items |
| 4 | **Scorer** | Assign each surviving candidate one or more scores | Sequential — later scorers see earlier scores |
| 5 | **Selector** | Sort by final score, return top K | Single op |
| 6 | **SideEffect** | Cache served IDs, log impressions, emit events, update counters | Async — must never block the response |
### Why this exact order
- Sources before hydration: know what candidates exist before paying to enrich them
- Hydration before filtering: many filters need metadata the source did not provide
- Filtering before scoring: scoring is the expensive stage; drop the ineligible first
- Scorer chain (not single scorer): real systems compose ML scoring + diversity reranking + business rules
- Selector after scoring: keeps scoring deterministic and cacheable
- SideEffects last and async: side effects must never block the user response
## Workflow when invoked
Walk the user through these eight steps:
1. **Clarify the use case** (one round, three questions): items being ranked? input context? language/runtime?
2. **Identify the candidate sources**: usually in-network (followed/owned/subscribed) + out-of-network (ML retrieval / trending / similar-to-liked)
3. **List required hydrations**: for each filter and scorer, what data does it need that the source did not provide?
4. **List the filters**: duplicate, self, age, block/mute, previously-served, eligibility. Order matters — cheap before expensive.
5. **Design the scorer chain**: primary (ML) → combiner (multi-action with weights) → diversity → business rules
6. **Selector**: sort descending by final score, take top K (or stratified mix for in-network/out-of-network)
7. **SideEffects**: cache served IDs, emit impression events, update counters, log analytics — all fire-and-forget
8. **Generate the scaffold** in the user's stack
## Key trade-offs to surface (don't default silently)
### 1. Single score vs multi-action prediction
- **Single score**: train one model to predict relevance. To change behavior → retrain.
- **Multi-action**: predict `P(action)` for many actions (read, like, share, skip, report), combine with weights at serving time. To change behavior → change weights. No retraining.
The X For You system uses multi-action with both positive and negative weights. Recommend multi-action when the user expects to tune frequently.
### 2. Candidate isolation in scoring
- **Isolated**: each candidate scored independently. Deterministic, cacheable.
- **Joint**: candidates attend to each other during scoring (e.g., transformer over batch). More expressive but non-deterministic across batches.
Default to isolation. Joint only when there's a specific reason (e.g., explicit batch-aware diversity).
### 3. Online vs offline
- **Request-time (online)**: pipeline runs on each request. Latency budget: 100300ms. Default.
- **Pre-computed (offline batch)**: pipeline runs periodically, results cached. Lower latency, lower freshness.
- **Hybrid**: candidate retrieval offline, ranking online.
## Hard rules
1. **Do not invent benchmark numbers.** "How much faster?" → "depends on workload, run it yourself."
2. **Attribution discipline.** When the pattern is referenced, attribute as "popularized by xAI's open-sourced For You algorithm" / `github.com/xai-org/x-algorithm` (Apache 2.0).
3. **No trademark use.** Do not name the user's artifact "X-like" or use "For You" branding. Pattern is free; brand is not. Suggested naming: "candidate pipeline", "feed pipeline", "ranking pipeline", "recsys pipeline".
4. **Surface trade-offs.** Multi-action vs single, isolation vs joint, online vs offline — never default silently.
5. **The generated scaffold must run.** No pseudocode passing as code.
6. **Filter order matters.** Cheap before expensive. Universal before user-specific.
7. **Side effects never block.** Wrap in fire-and-forget patterns (goroutines / promises without await / asyncio tasks).
## Anti-Patterns
- Scoring before filtering (wastes compute on candidates that will be dropped anyway)
- Synchronous side effects (cache writes / impression emits blocking the response)
- A single "relevance" score when the product needs to tune for multiple objectives (engagement vs safety vs diversity vs ads)
- Joint scoring as default (non-deterministic, harder to cache, doesn't compose with reranking stages)
- Generating pseudocode "for illustration" — the scaffold must actually run
## Upstream contents
The upstream repository at https://github.com/mturac/recsys-pipeline-architect ships:
- Full `SKILL.md` with the complete 8-step workflow
- 5 load-on-demand reference docs: interfaces in 4 languages (TS/Go/Python/Rust), multi-action scoring pattern, candidate isolation, filter cookbook (12 patterns), scorer cookbook (weighted sum, MMR, diversity penalty, position debiasing)
- 3 runnable example scaffolds, every one green on its test suite:
- Strapi v5 plugin (TypeScript / Jest — 3/3 pass)
- Zentra-compatible pipeline (Go with generics — 3/3 pass)
- PMAI task prioritizer (Python / FastAPI / pytest — 3/3 pass)
- v0.1.0 release tagged
- MIT license; pattern attributed to xAI X For You algorithm (Apache 2.0)
Install via skills.sh: `npx skills add mturac/recsys-pipeline-architect`

View File

@@ -0,0 +1,290 @@
#!/usr/bin/env node
/**
* Validate the supply-chain advisory source refresh report.
*/
const assert = require('assert');
const fs = require('fs');
const http = require('http');
const os = require('os');
const path = require('path');
const { spawnSync } = require('child_process');
const SCRIPT_PATH = path.join(
__dirname,
'..',
'..',
'scripts',
'ci',
'supply-chain-advisory-sources.js',
);
const {
DEFAULT_ADVISORY_SOURCES,
buildAdvisorySourceReport,
parseArgs,
renderText,
} = require(SCRIPT_PATH);
async function test(name, fn) {
try {
await fn();
console.log(`${name}`);
return true;
} catch (error) {
console.log(`${name}`);
console.log(` Error: ${error.message}`);
return false;
}
}
async function run() {
console.log('\n=== Testing supply-chain advisory source refresh ===\n');
let passed = 0;
let failed = 0;
if (await test('default sources cover the active npm and PyPI campaign', async () => {
const ids = DEFAULT_ADVISORY_SOURCES.map(source => source.id);
for (const requiredId of [
'tanstack-postmortem',
'github-ghsa-g7cv-rxg3-hmpx',
'stepsecurity-mini-shai-hulud',
'openai-tanstack-response',
'socket-node-ipc',
'cisa-npm-compromise',
]) {
assert.ok(ids.includes(requiredId), `Missing advisory source ${requiredId}`);
}
const ecosystemCoverage = new Set(DEFAULT_ADVISORY_SOURCES.flatMap(source => source.ecosystems));
assert.ok(ecosystemCoverage.has('npm'));
assert.ok(ecosystemCoverage.has('PyPI'));
assert.ok(ecosystemCoverage.has('AI developer tooling'));
})) passed++; else failed++;
if (await test('offline report emits passing coverage checks and Linear-ready ITO-57 payload', async () => {
const report = await buildAdvisorySourceReport({
generatedAt: '2026-05-16T00:00:00.000Z',
refresh: false,
});
assert.strictEqual(report.schema_version, 'ecc.supply-chain-advisory-sources.v1');
assert.strictEqual(report.ready, true);
assert.strictEqual(report.refresh.enabled, false);
assert.ok(report.sources.length >= 8);
assert.ok(report.checks.every(check => check.status === 'pass'));
assert.strictEqual(report.linear.status.issueId, 'ITO-57');
assert.match(report.linear.status.summary, /advisory sources current/i);
assert.match(report.linear.status.remaining, /Linear status/i);
})) passed++; else failed++;
if (await test('refresh mode records per-source live check results', async () => {
const calls = [];
const report = await buildAdvisorySourceReport({
generatedAt: '2026-05-16T00:00:00.000Z',
refresh: true,
fetchSource: async source => {
calls.push(source.id);
return {
ok: true,
statusCode: 200,
finalUrl: source.url,
checkedAt: '2026-05-16T00:00:00.000Z',
};
},
});
assert.deepStrictEqual(
calls.sort(),
DEFAULT_ADVISORY_SOURCES.filter(source => source.refresh !== false).map(source => source.id).sort(),
);
assert.strictEqual(report.refresh.enabled, true);
assert.strictEqual(report.refresh.ok, true);
assert.ok(report.sources.every(source => source.refreshStatus.status === 'ok'));
})) passed++; else failed++;
if (await test('refresh errors are captured as evidence without breaking offline source coverage', async () => {
const report = await buildAdvisorySourceReport({
generatedAt: '2026-05-16T00:00:00.000Z',
refresh: true,
fetchSource: async source => ({
ok: source.id !== 'socket-node-ipc',
statusCode: source.id === 'socket-node-ipc' ? 403 : 200,
error: source.id === 'socket-node-ipc' ? 'forbidden' : null,
finalUrl: source.url,
checkedAt: '2026-05-16T00:00:00.000Z',
}),
});
const socketSource = report.sources.find(source => source.id === 'socket-node-ipc');
assert.strictEqual(report.ready, true);
assert.strictEqual(report.refresh.ok, false);
assert.strictEqual(socketSource.refreshStatus.status, 'warning');
assert.match(socketSource.refreshStatus.error, /forbidden/);
assert.ok(report.checks.some(check => check.id === 'advisory-refresh' && check.status === 'warn'));
})) passed++; else failed++;
if (await test('CLI JSON can be written as a scheduled workflow artifact', async () => {
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-advisory-sources-'));
const outputPath = path.join(tempDir, 'advisory-sources.json');
try {
const result = spawnSync('node', [
SCRIPT_PATH,
'--json',
'--generated-at',
'2026-05-16T00:00:00.000Z',
'--write',
outputPath,
], {
encoding: 'utf8',
shell: process.platform === 'win32',
});
assert.strictEqual(result.status, 0, result.stderr);
const parsed = JSON.parse(fs.readFileSync(outputPath, 'utf8'));
assert.strictEqual(parsed.schema_version, 'ecc.supply-chain-advisory-sources.v1');
assert.strictEqual(parsed.ready, true);
assert.ok(parsed.linear.status.evidence.length >= 3);
} finally {
fs.rmSync(tempDir, { recursive: true, force: true });
}
})) passed++; else failed++;
if (await test('argument parser covers strict refresh, timeout validation, and unknown flags', async () => {
const parsed = parseArgs(['--strict-refresh', '--timeout-ms', '250', '--json']);
assert.strictEqual(parsed.refresh, true);
assert.strictEqual(parsed.strictRefresh, true);
assert.strictEqual(parsed.timeoutMs, 250);
assert.strictEqual(parsed.json, true);
assert.throws(() => parseArgs(['--timeout-ms', '0']), /positive number/);
assert.throws(() => parseArgs(['--write']), /requires a path/);
assert.throws(() => parseArgs(['--wat']), /Unknown argument/);
})) passed++; else failed++;
if (await test('invalid source coverage fails closed with actionable checks', async () => {
const report = await buildAdvisorySourceReport({
generatedAt: '2026-05-16T00:00:00.000Z',
sources: [
{
id: 'one-source',
title: 'Incomplete source set',
publisher: 'Test',
url: 'https://example.com',
sourceType: 'incident-analysis',
ecosystems: ['npm'],
signals: ['tanstack'],
},
],
});
assert.strictEqual(report.ready, false);
assert.ok(report.checks.some(check => check.id === 'advisory-source-count' && check.status === 'fail'));
assert.ok(report.checks.some(check => check.id === 'advisory-ecosystem-coverage' && check.status === 'fail'));
assert.ok(report.checks.some(check => check.id === 'advisory-signal-coverage' && check.status === 'fail'));
assert.match(report.linear.status.summary, /needs repair/i);
})) passed++; else failed++;
if (await test('CLI text output and invalid flag errors are stable', async () => {
const help = spawnSync('node', [SCRIPT_PATH, '--help'], {
encoding: 'utf8',
shell: process.platform === 'win32',
});
assert.strictEqual(help.status, 0);
assert.match(help.stdout, /--strict-refresh/);
const text = spawnSync('node', [
SCRIPT_PATH,
'--generated-at',
'2026-05-16T00:00:00.000Z',
], {
encoding: 'utf8',
shell: process.platform === 'win32',
});
assert.strictEqual(text.status, 0, text.stderr);
assert.match(text.stdout, /Supply-chain advisory sources: ready/);
assert.match(text.stdout, /Linear ITO-57:/);
const invalid = spawnSync('node', [SCRIPT_PATH, '--unknown'], {
encoding: 'utf8',
shell: process.platform === 'win32',
});
assert.strictEqual(invalid.status, 2);
assert.match(invalid.stderr, /Unknown argument/);
})) passed++; else failed++;
if (await test('text renderer covers blocked and refresh-warning states', async () => {
const blocked = await buildAdvisorySourceReport({
generatedAt: '2026-05-16T00:00:00.000Z',
sources: [],
});
const blockedText = renderText(blocked);
assert.match(blockedText, /blocked/);
assert.match(blockedText, /not requested/);
const warning = await buildAdvisorySourceReport({
generatedAt: '2026-05-16T00:00:00.000Z',
refresh: true,
fetchSource: async source => ({
ok: source.id !== 'tanstack-postmortem',
statusCode: source.id === 'tanstack-postmortem' ? 500 : 200,
error: source.id === 'tanstack-postmortem' ? 'server error' : null,
checkedAt: '2026-05-16T00:00:00.000Z',
finalUrl: source.url,
}),
});
const warningText = renderText(warning);
assert.match(warningText, /warnings=1/);
})) passed++; else failed++;
if (await test('default refresh follows redirects and retries GET for unsupported HEAD', async () => {
const server = http.createServer((request, response) => {
if (request.url === '/redirect') {
response.writeHead(302, { Location: '/ok' });
response.end();
return;
}
if (request.url === '/head-unsupported' && request.method === 'HEAD') {
response.writeHead(405);
response.end();
return;
}
response.writeHead(200, { 'Content-Type': 'text/plain' });
response.end('ok');
});
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
const { port } = server.address();
try {
const sources = DEFAULT_ADVISORY_SOURCES.map((source, index) => ({
...source,
url: index === 0
? `http://127.0.0.1:${port}/redirect`
: `http://127.0.0.1:${port}/head-unsupported`,
}));
const report = await buildAdvisorySourceReport({
generatedAt: '2026-05-16T00:00:00.000Z',
refresh: true,
sources,
});
assert.strictEqual(report.ready, true);
assert.strictEqual(report.refresh.ok, true);
assert.ok(report.sources.every(source => source.refreshStatus.status === 'ok'));
} finally {
await new Promise(resolve => server.close(resolve));
}
})) passed++; else failed++;
console.log(`\nPassed: ${passed}`);
console.log(`Failed: ${failed}`);
process.exit(failed > 0 ? 1 : 0);
}
run();

View File

@@ -58,9 +58,13 @@ function run() {
if (test('runs IOC fixtures, emits JSON report, and uploads the artifact', () => {
assert.match(source, /node tests\/ci\/scan-supply-chain-iocs\.test\.js/);
assert.match(source, /node scripts\/ci\/scan-supply-chain-iocs\.js --json > artifacts\/supply-chain-ioc-report\.json/);
assert.match(source, /node tests\/ci\/supply-chain-advisory-sources\.test\.js/);
assert.match(source, /node scripts\/ci\/supply-chain-advisory-sources\.js --refresh --json > artifacts\/supply-chain-advisory-sources\.json/);
assert.match(source, /node scripts\/ci\/validate-workflow-security\.js/);
assert.match(source, /uses: actions\/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a/);
assert.match(source, /name: supply-chain-ioc-report/);
assert.match(source, /artifacts\/supply-chain-ioc-report\.json/);
assert.match(source, /artifacts\/supply-chain-advisory-sources\.json/);
assert.match(source, /retention-days: 14/);
})) passed++; else failed++;

View File

@@ -131,9 +131,9 @@ function runTests() {
else failed++;
if (
test('20% remaining contains red blink ANSI code', () => {
test('20% remaining contains bold red ANSI code', () => {
const bar = buildContextBar(20);
assert.ok(bar.includes('\x1b[5;31m'), `Expected red blink ANSI in: ${JSON.stringify(bar)}`);
assert.ok(bar.includes('\x1b[1;31m'), `Expected bold red ANSI in: ${JSON.stringify(bar)}`);
})
)
passed++;

View File

@@ -44,6 +44,7 @@ function buildExpectedPublishPaths(repoRoot) {
"scripts/ecc.js",
"scripts/catalog.js",
"scripts/ci/scan-supply-chain-iocs.js",
"scripts/ci/supply-chain-advisory-sources.js",
"scripts/consult.js",
"scripts/claw.js",
"scripts/discussion-audit.js",
@@ -56,6 +57,7 @@ function buildExpectedPublishPaths(repoRoot) {
"scripts/list-installed.js",
"scripts/loop-status.js",
"scripts/observability-readiness.js",
"scripts/operator-readiness-dashboard.js",
"scripts/platform-audit.js",
"scripts/skill-create-output.js",
"scripts/repair.js",
@@ -123,8 +125,10 @@ function main() {
for (const requiredPath of [
"scripts/catalog.js",
"scripts/ci/scan-supply-chain-iocs.js",
"scripts/ci/supply-chain-advisory-sources.js",
"scripts/consult.js",
"scripts/discussion-audit.js",
"scripts/operator-readiness-dashboard.js",
"scripts/work-items.js",
"scripts/platform-audit.js",
".gemini/GEMINI.md",

View File

@@ -0,0 +1,331 @@
/**
* Tests for scripts/operator-readiness-dashboard.js
*/
const assert = require('assert');
const fs = require('fs');
const os = require('os');
const path = require('path');
const { execFileSync, spawnSync } = require('child_process');
const SCRIPT = path.join(__dirname, '..', '..', 'scripts', 'operator-readiness-dashboard.js');
const { buildReport, parseArgs, renderMarkdown, renderText } = require(SCRIPT);
function createTempDir(prefix) {
return fs.mkdtempSync(path.join(os.tmpdir(), prefix));
}
function cleanup(dirPath) {
fs.rmSync(dirPath, { recursive: true, force: true });
}
function writeFile(rootDir, relativePath, content) {
const targetPath = path.join(rootDir, relativePath);
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
fs.writeFileSync(targetPath, content);
}
function seedRepo(rootDir, overrides = {}) {
const files = {
'package.json': JSON.stringify({
name: 'everything-claude-code',
files: [
'scripts/observability-readiness.js',
'scripts/operator-readiness-dashboard.js',
'scripts/platform-audit.js'
],
scripts: {
'discussion:audit': 'node scripts/discussion-audit.js',
'observability:ready': 'node scripts/observability-readiness.js',
'operator:dashboard': 'node scripts/operator-readiness-dashboard.js',
'platform:audit': 'node scripts/platform-audit.js',
'security:ioc-scan': 'node scripts/ci/scan-supply-chain-iocs.js',
'security:advisory-sources': 'node scripts/ci/supply-chain-advisory-sources.js'
}
}, null, 2),
'scripts/operator-readiness-dashboard.js': 'operator dashboard generator',
'docs/ECC-2.0-GA-ROADMAP.md': [
'https://linear.app/itomarkets/project/ecc-platform-roadmap-52b328ee03e1',
'Linear ITO-44 ITO-59',
'AgentShield PR #89 #78-#89',
'AgentShield Enterprise Iteration',
'ECC-Tools PR #77',
'hosted promotion',
'announcementGate',
'ITO-55'
].join('\n'),
'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/preview-pack-manifest.md': 'publication-readiness.md release-notes.md quickstart.md',
'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-15.md': [
'This dashboard is generated by `npm run operator:dashboard`',
'operator:dashboard',
'Prompt-To-Artifact Checklist',
'Next Work Order',
'ITO-44',
'ITO-59',
'PR queue',
'Not complete'
].join('\n'),
'docs/HERMES-SETUP.md': 'Hermes setup',
'skills/hermes-imports/SKILL.md': 'Hermes imports',
'docs/stale-pr-salvage-ledger.md': 'Manual review tail',
'docs/architecture/progress-sync-contract.md': 'GitHub PRs/issues/discussions Linear project local handoff repo roadmap scripts/work-items.js',
'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-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'
};
for (const [relativePath, content] of Object.entries({ ...files, ...overrides })) {
if (content === null) {
continue;
}
writeFile(rootDir, relativePath, content);
}
}
function run(args = [], options = {}) {
return execFileSync('node', [SCRIPT, ...args], {
cwd: options.cwd || path.join(__dirname, '..', '..'),
encoding: 'utf8',
stdio: ['pipe', 'pipe', 'pipe'],
timeout: 10000
});
}
function runProcess(args = [], options = {}) {
return spawnSync('node', [SCRIPT, ...args], {
cwd: options.cwd || path.join(__dirname, '..', '..'),
encoding: 'utf8',
stdio: ['pipe', 'pipe', 'pipe'],
timeout: 10000
});
}
function test(name, fn) {
try {
fn();
console.log(` PASS ${name}`);
return true;
} catch (error) {
console.log(` FAIL ${name}`);
console.log(` Error: ${error.message}`);
return false;
}
}
function runTests() {
console.log('\n=== Testing operator-readiness-dashboard.js ===\n');
let passed = 0;
let failed = 0;
if (test('parseArgs accepts dashboard flags and rejects invalid values', () => {
const rootDir = createTempDir('operator-dashboard-args-');
try {
const parsed = parseArgs([
'node',
'script',
'--format=json',
`--root=${rootDir}`,
'--skip-github',
'--allow-untracked',
'docs/drafts/',
'--repo',
'affaan-m/everything-claude-code',
'--generated-at',
'2026-05-15T00:00:00.000Z'
]);
assert.strictEqual(parsed.format, 'json');
assert.strictEqual(parsed.root, path.resolve(rootDir));
assert.strictEqual(parsed.skipGithub, true);
assert.deepStrictEqual(parsed.allowUntracked, ['docs/drafts/']);
assert.deepStrictEqual(parsed.repos, ['affaan-m/everything-claude-code']);
assert.strictEqual(parsed.generatedAt, '2026-05-15T00:00:00.000Z');
assert.throws(() => parseArgs(['node', 'script', '--format', 'xml']), /Invalid format/);
assert.throws(() => parseArgs(['node', 'script', '--write', 'dashboard.md', '--format', 'text']), /--write requires/);
assert.throws(() => parseArgs(['node', 'script', '--max-open-prs', 'x']), /Invalid --max-open-prs/);
assert.throws(() => parseArgs(['node', 'script', '--unknown']), /Unknown argument/);
} finally {
cleanup(rootDir);
}
})) passed++; else failed++;
if (test('seeded repo emits an objective audit with remaining work', () => {
const rootDir = createTempDir('operator-dashboard-report-');
try {
seedRepo(rootDir);
const report = buildReport({
allowUntracked: [],
exitCode: false,
format: 'json',
generatedAt: '2026-05-15T00:00:00.000Z',
help: false,
repos: [],
root: rootDir,
skipGithub: true,
thresholds: { maxOpenPrs: 20, maxOpenIssues: 20, maxDirtyFiles: 0 },
useEnvGithubToken: false,
writePath: null
});
assert.strictEqual(report.schema_version, 'ecc.operator-readiness-dashboard.v1');
assert.strictEqual(report.generatedAt, '2026-05-15T00:00:00.000Z');
assert.strictEqual(report.dashboardReady, true);
assert.strictEqual(report.ready, false);
assert.strictEqual(report.publicationReady, false);
assert.ok(report.requirements.some(item => item.id === 'completion-dashboard' && item.status === 'complete'));
assert.ok(report.requirements.some(item => item.id === 'ecc-tools-next-level' && item.status === 'in_progress'));
assert.ok(report.top_actions.some(item => item.id === 'naming-and-plugin-publication'));
} finally {
cleanup(rootDir);
}
})) passed++; else failed++;
if (test('markdown output can be written as the dashboard artifact', () => {
const rootDir = createTempDir('operator-dashboard-markdown-');
const outputPath = path.join(rootDir, 'artifacts', 'dashboard.md');
try {
seedRepo(rootDir);
const stdout = run([
'--markdown',
'--skip-github',
`--root=${rootDir}`,
'--generated-at=2026-05-15T00:00:00.000Z',
'--write',
outputPath
], { cwd: rootDir });
const written = fs.readFileSync(outputPath, 'utf8');
assert.strictEqual(stdout, written);
assert.ok(written.includes('# ECC Operator Readiness Dashboard'));
assert.ok(written.includes('Generated: 2026-05-15T00:00:00.000Z'));
assert.ok(written.includes('## Prompt-To-Artifact Checklist'));
assert.ok(written.includes('Build ITO-44 completion dashboard into a repeatable command'));
assert.ok(written.includes('## Next Work Order'));
} finally {
cleanup(rootDir);
}
})) passed++; else failed++;
if (test('text output renders compact status and top actions', () => {
const rootDir = createTempDir('operator-dashboard-text-');
try {
seedRepo(rootDir);
const stdout = run([
'--format=text',
'--skip-github',
`--root=${rootDir}`,
'--generated-at=2026-05-15T00:00:00.000Z'
], { cwd: rootDir });
assert.ok(stdout.includes('ECC Operator Readiness Dashboard'));
assert.ok(stdout.includes('work remaining'));
assert.ok(stdout.includes('Dashboard ready: true'));
assert.ok(stdout.includes('Publication ready: false'));
assert.ok(stdout.includes('Top actions:'));
assert.ok(stdout.includes('naming-and-plugin-publication'));
} finally {
cleanup(rootDir);
}
})) passed++; else failed++;
if (test('renderers handle a ready report with no top actions', () => {
const report = {
dashboardReady: true,
generatedAt: '2026-05-15T00:00:00.000Z',
head: 'abc123',
next_work_order: ['Ship release evidence'],
platform: {
blockingDirtyCount: 0,
discussionsMissingAcceptedAnswer: 0,
discussionsNeedingMaintainerTouch: 0,
githubSkipped: false,
ignoredDirtyCount: 0,
openIssues: 1,
openPrs: 1,
ready: true
},
publicationReady: true,
ready: true,
requirements: [
{
artifact: 'artifact.md',
evidence: 'verified',
gap: '',
id: 'release',
requirement: 'Release is approved',
status: 'complete'
}
],
top_actions: []
};
const text = renderText(report);
assert.ok(text.includes('objective ready'));
assert.ok(text.includes('Commit: abc123'));
assert.ok(text.includes(' none'));
const markdown = renderMarkdown(report);
assert.ok(markdown.includes('Status: objective ready'));
assert.ok(markdown.includes('| PR queue | Current | 1 open PRs across tracked repos |'));
assert.ok(markdown.includes('| Publication | Ready |'));
assert.ok(markdown.includes('- none'));
})) passed++; else failed++;
if (test('exit-code mode fails closed while macro objective has gaps', () => {
const rootDir = createTempDir('operator-dashboard-exit-');
try {
seedRepo(rootDir);
const result = runProcess([
'--json',
'--skip-github',
`--root=${rootDir}`,
'--generated-at=2026-05-15T00:00:00.000Z',
'--exit-code'
], { cwd: rootDir });
assert.strictEqual(result.status, 2);
assert.strictEqual(result.stderr, '');
assert.ok(result.stdout.includes('"ready": false'));
assert.ok(result.stdout.includes('"publicationReady": false'));
} finally {
cleanup(rootDir);
}
})) passed++; else failed++;
if (test('cli help exits successfully and invalid cli flags fail before reporting', () => {
const help = runProcess(['--help']);
assert.strictEqual(help.status, 0);
assert.strictEqual(help.stderr, '');
assert.ok(help.stdout.includes('Usage: node scripts/operator-readiness-dashboard.js'));
assert.ok(help.stdout.includes('--write <path>'));
const invalid = runProcess(['--format=xml']);
assert.strictEqual(invalid.status, 1);
assert.strictEqual(invalid.stdout, '');
assert.match(invalid.stderr, /Error: Invalid format/);
})) passed++; else failed++;
console.log(`\nPassed: ${passed}`);
console.log(`Failed: ${failed}`);
if (failed > 0) {
process.exit(1);
}
}
if (require.main === module) {
runTests();
}

View File

@@ -32,8 +32,10 @@ function seedRepo(rootDir, overrides = {}) {
scripts: {
'platform:audit': 'node scripts/platform-audit.js',
'discussion:audit': 'node scripts/discussion-audit.js',
'operator:dashboard': 'node scripts/operator-readiness-dashboard.js',
'observability:ready': 'node scripts/observability-readiness.js',
'security:ioc-scan': 'node scripts/ci/scan-supply-chain-iocs.js',
'security:advisory-sources': 'node scripts/ci/supply-chain-advisory-sources.js',
'harness:audit': 'node scripts/harness-audit.js'
}
}, null, 2),
@@ -54,7 +56,8 @@ function seedRepo(rootDir, overrides = {}) {
'TanStack',
'Mini Shai-Hulud',
'node-ipc',
'scan-supply-chain-iocs.js'
'scan-supply-chain-iocs.js',
'supply-chain-advisory-sources.js'
].join('\n'),
'docs/releases/2.0.0-rc.1/publication-evidence-2026-05-15.md': [
'TanStack',
@@ -64,12 +67,16 @@ function seedRepo(rootDir, overrides = {}) {
'IOC scan'
].join('\n'),
'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',
'ITO-59',
'PR queue',
'Not complete'
].join('\n')
'Not complete',
'operator:dashboard',
'Next Work Order'
].join('\n'),
'scripts/operator-readiness-dashboard.js': 'operator dashboard generator'
};
for (const [relativePath, content] of Object.entries({ ...files, ...overrides })) {
@@ -201,6 +208,7 @@ function runTests() {
assert.strictEqual(parsed.github.skipped, true);
assert.ok(parsed.checks.some(check => check.id === 'roadmap-linear-mirror' && check.status === 'pass'));
assert.ok(parsed.checks.some(check => check.id === 'supply-chain-runbook' && check.status === 'pass'));
assert.ok(parsed.checks.some(check => check.id === 'operator-dashboard-command' && check.status === 'pass'));
assert.ok(parsed.checks.some(check => check.id === 'operator-readiness-dashboard' && check.status === 'pass'));
assert.deepStrictEqual(parsed.top_actions, []);
} finally {