Compare commits

..

10 Commits

Author SHA1 Message Date
Claude
d7a3ccd07a feat(installer): add --locale flag for translated docs installation
Adds `--locale <code>` support to the ECC installer so users can install
localized reference docs (agents, commands, skills, rules) into
`~/.claude/docs/<locale>/` alongside the existing English installation.

Changes:
- manifests/install-modules.json: add 8 locale doc modules (docs-ja-JP,
  docs-zh-CN, docs-ko-KR, docs-pt-BR, docs-ru, docs-tr, docs-vi-VN,
  docs-zh-TW), each with kind="docs" and defaultInstall=false
- manifests/install-components.json: add 8 locale: components mapping to
  the new modules
- scripts/lib/install-manifests.js: add locale: family prefix,
  SUPPORTED_LOCALES, LOCALE_ALIAS_TO_COMPONENT_ID (with aliases like
  ja=ja-JP, zh=zh-CN, ko=ko-KR), and listSupportedLocales()
- scripts/lib/install/request.js: add --locale flag to parseInstallArgs(),
  resolve locale alias → component ID in normalizeInstallRequest(), throw
  on unsupported locale codes
- scripts/lib/install-targets/claude-home.js: map docs/<locale>/ source
  paths to ~/.claude/docs/<locale>/ destination (side-by-side, no overwrite
  of English files)
- scripts/install-apply.js: import listSupportedLocales, add --locale
  usage line and available locales list to --help output

Usage examples:
  ./install.sh --locale ja                    # Japanese docs only
  ./install.sh --profile core --locale zh-CN  # core profile + zh-CN docs
  ./install.sh typescript --locale ja         # legacy + locale (errors)
2026-05-18 07:57:10 +09:00
Claude
c0d3152a11 feat(ja-JP): complete Japanese translation (607 files, full English-source parity) 2026-05-18 07:32:15 +09:00
Claude
174e31b3fc feat(ja-JP): add skill sub-reference translations (angular, remotion, etc.)
Translated 85 skill sub-reference files to achieve full parity with
the English source:

- skills/angular-developer/references/ — 35 files (all references)
- skills/remotion-video-creation/rules/ — 28 files (all rules)
- skills/tinystruct-patterns/references/ — 5 files
- skills/openclaw-persona-forge/references/ — 6 files
- skills/skill-comply/prompts/ — 3 files
- skills/lead-intelligence/agents/ — 4 files
- skills/brand-voice/references/ — 1 file
- skills/frontend-slides/ — 2 files
- hooks/memory-persistence/README.md — 1 file

English source parity: 0 missing files (excluding rules/zh/, internal
docs, and experimental examples absent from zh-CN)
2026-05-18 06:15:26 +09:00
Affaan Mustafa
63624426c8 fix(ja-JP): repair localized docs links 2026-05-17 02:29:16 -04:00
Affaan Mustafa
8672a6132b fix(ja-JP): repair localized security links 2026-05-17 02:13:33 -04:00
Claude
6f01e543dc fix(ja-JP): translate frontmatter description to Japanese in 3 skills
- skill-scout: translate description field
- tinystruct-patterns: translate description field
- ui-to-vue: translate description field
2026-05-17 09:13:45 +09:00
Claude
bdb725da83 fix(ja-JP): address review feedback and add 5 missing skills
- Fix Chinese term '提炼' → '蒸留' in commands/rules-distill.md
- Fix '重大な所見' (Critical→重大) in agents/opensource-sanitizer.md
- Fix non-transactional persistence in swift-actor-persistence/SKILL.md:
  add rollback logic so cache stays consistent if disk write fails
- Clarify anti-pattern wording: 'configurable file URL' → 'externally
  mutable after init' to remove internal inconsistency (P2)
- Fix broken relative link in videodb/reference/api-reference.md:
  ../../../../../skills/... → ./editor.md
- Add 5 previously missing SKILL.md translations:
  skill-scout, tinystruct-patterns, ui-to-vue, vite-patterns,
  windows-desktop-e2e
2026-05-17 09:08:06 +09:00
Claude
4831fcf1cf docs: fix zh-CN parity — add 44 missing files to ja-JP
Add files present in zh-CN but missing from ja-JP:
- commands: claw, context-budget, devfleet, docs, projects, prompt-optimize, rules-distill (7 files)
- skills: regex-vs-llm-structured-text, remotion-video-creation, repo-scan, research-ops,
  returns-reverse-logistics, rules-distill, rust-patterns, rust-testing, skill-comply,
  skill-stocktake, social-graph-ranker, swift-actor-persistence, swift-concurrency-6-2,
  swift-protocol-di-testing, swiftui-patterns, team-builder, terminal-ops, token-budget-advisor,
  ui-demo, unified-notifications-ops, video-editing, videodb (+reference/*), visa-doc-translate,
  workspace-surface-audit, x-api (37 files)

Result: ja-JP now has 517 files vs zh-CN 412 files.
zh-CN parity: 0 missing files (complete parity achieved).
2026-05-17 08:51:06 +09:00
Claude
329b67b9d5 docs: add missing Japanese translations to complete zh-CN parity (ja-JP)
Add remaining files to match zh-CN documentation structure:
- hooks/README.md — hooks architecture and customization guide
- examples/ — 8 project CLAUDE.md templates (general, user, django, go, harmonyos, laravel, rust, saas-nextjs)
- CHANGELOG.md — version history
- the-openclaw-guide.md — OpenClaw guide (471 lines)

Total: 11 files, 2362 insertions
ja-JP now has full parity with zh-CN directory structure.
2026-05-16 22:45:27 +09:00
Claude
386b312106 docs: add native Japanese translation of ECC documentation (ja-JP)
Translate everything-claude-code repository to Japanese including:
- 17 root documentation files
- 60 agent documentation files
- 80 command documentation files
- 99 rule files across 18 language directories (common, angular, arkts, cpp, csharp, dart, fsharp, golang, java, kotlin, perl, php, python, ruby, rust, swift, typescript, web)
- 199 skill documentation files

Total: 455 files translated to Japanese with:
- Consistent terminology glossary applied throughout
- YAML field names preserved in English (name, description, etc.)
- Code blocks and examples untouched (comments translated)
- Markdown structure and relative links preserved
- Professional translation maintaining technical accuracy

This translation expands ECC accessibility to Japanese-speaking developers and teams.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-16 20:12:58 +09:00
300 changed files with 9900 additions and 22023 deletions

View File

@@ -1,7 +1,7 @@
{
"name": "ecc",
"interface": {
"displayName": "ECC"
"displayName": "Everything Claude Code"
},
"plugins": [
{
@@ -9,7 +9,7 @@
"version": "2.0.0-rc.1",
"source": {
"source": "local",
"path": "./"
"path": "../.."
},
"policy": {
"installation": "AVAILABLE",

View File

@@ -5,20 +5,20 @@
"email": "me@affaanmustafa.com"
},
"metadata": {
"description": "Harness-native ECC skills, hooks, rules, MCP conventions, and operator workflows"
"description": "Battle-tested Claude Code configurations from an Anthropic hackathon winner"
},
"plugins": [
{
"name": "ecc",
"source": "./",
"description": "Harness-native ECC operator layer - 60 agents, 232 skills, 75 legacy command shims, reusable hooks, rules, selective install profiles, and production-ready workflows for Claude Code, Codex, OpenCode, Cursor, and related agent harnesses",
"description": "The most comprehensive Claude Code plugin — 60 agents, 228 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",
"email": "me@affaanmustafa.com"
},
"homepage": "https://ecc.tools",
"repository": "https://github.com/affaan-m/ECC",
"repository": "https://github.com/affaan-m/everything-claude-code",
"license": "MIT",
"keywords": [
"agents",

View File

@@ -1,13 +1,13 @@
{
"name": "ecc",
"version": "2.0.0-rc.1",
"description": "Harness-native ECC plugin for engineering teams - 60 agents, 232 skills, 75 legacy command shims, reusable hooks, rules, MCP conventions, and operator workflows for Claude Code plus adjacent agent harnesses",
"description": "Battle-tested Claude Code plugin for engineering teams 60 agents, 228 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"
},
"homepage": "https://ecc.tools",
"repository": "https://github.com/affaan-m/ECC",
"repository": "https://github.com/affaan-m/everything-claude-code",
"license": "MIT",
"keywords": [
"claude-code",

View File

@@ -1,6 +1,6 @@
# .codex-plugin — Codex Native Plugin for ECC
This directory contains the **Codex plugin manifest** for ECC.
This directory contains the **Codex plugin manifest** for Everything Claude Code.
## Structure
@@ -18,28 +18,18 @@ This directory contains the **Codex plugin manifest** for ECC.
## Installation
Codex plugin support is currently marketplace-backed. The repo exposes a
repo-scoped marketplace at `.agents/plugins/marketplace.json`; Codex can add and
track that marketplace source from the CLI:
Codex plugin support is currently in preview. Once generally available:
```bash
# Add the public repo marketplace
codex plugin marketplace add affaan-m/ECC
# Install from Codex CLI
codex plugin install affaan-m/everything-claude-code
# Or add a local checkout while developing
codex plugin marketplace add /absolute/path/to/ECC
# Or reference locally during development
codex plugin install ./
Run this from the repository root so `./` points to the repo root and `.mcp.json` resolves correctly.
```
The marketplace entry points at the repository root so `.codex-plugin/plugin.json`,
`skills/`, and `.mcp.json` resolve from one shared source of truth. After adding
or updating the marketplace, restart Codex and install or enable `ecc` from the
plugin directory.
Official Plugin Directory publishing is coming soon in Codex. Until self-serve
publishing exists, treat the public repo marketplace as the supported Codex
distribution path and keep release copy framed as repo-marketplace/manual
installation.
The installed plugin registers under the short slug `ecc` so tool and command names
stay below provider length limits.

View File

@@ -1,22 +1,22 @@
{
"name": "ecc",
"version": "2.0.0-rc.1",
"description": "Harness-native ECC workflows for Codex: shared skills, production-ready MCP configs, and selective-install-aligned conventions for TDD, security scanning, code review, and autonomous development.",
"description": "Battle-tested Codex workflows — 207 shared ECC skills, production-ready MCP configs, and selective-install-aligned conventions for TDD, security scanning, code review, and autonomous development.",
"author": {
"name": "Affaan Mustafa",
"email": "me@affaanmustafa.com",
"url": "https://x.com/affaanmustafa"
},
"homepage": "https://ecc.tools",
"repository": "https://github.com/affaan-m/ECC",
"repository": "https://github.com/affaan-m/everything-claude-code",
"license": "MIT",
"keywords": ["codex", "agents", "skills", "tdd", "code-review", "security", "workflow", "automation"],
"skills": "./skills/",
"mcpServers": "./.mcp.json",
"interface": {
"displayName": "ECC",
"displayName": "Everything Claude Code",
"shortDescription": "207 battle-tested ECC skills plus MCP configs for TDD, security, code review, and autonomous development.",
"longDescription": "ECC is a harness-native operator system for Codex and adjacent agent harnesses. It packages reusable skills, MCP configs, TDD workflows, security scanning, code review, architecture decisions, operator workflows, and release gates in one installable plugin.",
"longDescription": "Everything Claude Code (ECC) is a community-maintained collection of Codex-ready skills and MCP configs evolved over 10+ months of intensive daily use. It covers TDD workflows, security scanning, code review, architecture decisions, operator workflows, and more — all in one installable plugin.",
"developerName": "Affaan Mustafa",
"category": "Productivity",
"capabilities": ["Read", "Write"],

1
.github/CODEOWNERS vendored
View File

@@ -1 +0,0 @@
* @affaan-m

View File

@@ -45,7 +45,7 @@ jobs:
# Package manager setup
- name: Setup pnpm
if: matrix.pm == 'pnpm' && matrix.node != '18.x'
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
uses: pnpm/action-setup@91ab88e2619ed1f46221f0ba42d1492c02baf788 # v6.0.6
with:
# Keep an explicit pnpm major because this repo's packageManager is Yarn.
version: 10
@@ -68,6 +68,73 @@ jobs:
if: matrix.pm == 'bun'
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
# Cache configuration
- name: Get npm cache directory
if: matrix.pm == 'npm'
id: npm-cache-dir
shell: bash
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- name: Cache npm
if: matrix.pm == 'npm'
continue-on-error: true
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ steps.npm-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ matrix.node }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-${{ matrix.node }}-npm-
- name: Get pnpm store directory
if: matrix.pm == 'pnpm'
id: pnpm-cache-dir
shell: bash
env:
COREPACK_ENABLE_STRICT: '0'
run: echo "dir=$(pnpm store path)" >> $GITHUB_OUTPUT
- name: Cache pnpm
if: matrix.pm == 'pnpm'
continue-on-error: true
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ steps.pnpm-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ matrix.node }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-node-${{ matrix.node }}-pnpm-
- name: Get yarn cache directory
if: matrix.pm == 'yarn'
id: yarn-cache-dir
shell: bash
run: |
# Try Yarn Berry first, fall back to Yarn v1
if yarn config get cacheFolder >/dev/null 2>&1; then
echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
else
echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
fi
- name: Cache yarn
if: matrix.pm == 'yarn'
continue-on-error: true
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ steps.yarn-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ matrix.node }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-node-${{ matrix.node }}-yarn-
- name: Cache bun
if: matrix.pm == 'bun'
continue-on-error: true
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
restore-keys: |
${{ runner.os }}-bun-
# Install dependencies
# COREPACK_ENABLE_STRICT=0 allows pnpm to install even though
# package.json declares "packageManager": "yarn@..."
@@ -75,18 +142,16 @@ jobs:
shell: bash
env:
COREPACK_ENABLE_STRICT: '0'
npm_config_ignore_scripts: 'true'
YARN_ENABLE_SCRIPTS: 'false'
run: |
case "${{ matrix.pm }}" in
npm) npm ci --ignore-scripts ;;
npm) npm ci ;;
# pnpm v10 can fail CI on ignored native build scripts
# (for example msgpackr-extract) even though this repo is Yarn-native
# and pnpm is only exercised here as a compatibility lane.
pnpm) pnpm install --ignore-scripts --config.strict-dep-builds=false --no-frozen-lockfile ;;
pnpm) pnpm install --config.strict-dep-builds=false --no-frozen-lockfile ;;
# Yarn Berry (v4+) removed --ignore-engines; engine checking is no longer a core feature
yarn) yarn install --mode=skip-build ;;
bun) bun install --ignore-scripts ;;
yarn) yarn install ;;
bun) bun install ;;
*) echo "Unsupported package manager: ${{ matrix.pm }}" && exit 1 ;;
esac
@@ -155,10 +220,6 @@ jobs:
run: node scripts/ci/catalog.js --text
continue-on-error: false
- name: Validate command registry
run: npm run command-registry:check
continue-on-error: false
- name: Check unicode safety
run: node scripts/ci/check-unicode-safety.js
continue-on-error: false
@@ -181,43 +242,11 @@ jobs:
with:
node-version: '20.x'
- name: Install audit dependencies
run: npm ci --ignore-scripts
- name: Run npm audit
run: |
npm audit signatures
npm audit --audit-level=high
- name: Run supply-chain IOC scan
run: npm run security:ioc-scan
coverage:
name: Coverage
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: '20.x'
- name: Install dependencies
run: npm ci --ignore-scripts
- name: Run coverage
run: npm run coverage
- name: Upload coverage report
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: coverage-ubuntu-node20-npm
path: coverage/
continue-on-error: true # Allows PR to proceed, but marks job as failed if vulnerabilities found
lint:
name: Lint

View File

@@ -5,16 +5,13 @@ on:
tags: ['v*']
permissions:
contents: read
contents: write
id-token: write
jobs:
verify:
name: Verify Release
release:
name: Create Release
runs-on: ubuntu-latest
outputs:
already_published: ${{ steps.npm_publish_state.outputs.already_published }}
dist_tag: ${{ steps.npm_publish_state.outputs.dist_tag }}
package_file: ${{ steps.pack.outputs.package_file }}
steps:
- name: Checkout
@@ -32,9 +29,6 @@ jobs:
- name: Install dependencies
run: npm ci --ignore-scripts
- name: Run supply-chain IOC scan
run: npm run security:ioc-scan
- name: Verify OpenCode package payload
run: node tests/scripts/build-opencode.test.js
@@ -96,46 +90,10 @@ jobs:
### Notes
- npm package: \`ecc-universal\`
- Claude marketplace/plugin identifier: \`ecc@ecc\`
- Claude marketplace/plugin identifier: \`everything-claude-code@everything-claude-code\`
- For migration tips and compatibility notes, see README and CHANGELOG.
EOF
- name: Pack npm artifact
id: pack
run: |
npm pack --json > npm-pack.json
PACKAGE_FILE=$(node -e "const fs = require('fs'); const data = JSON.parse(fs.readFileSync('npm-pack.json', 'utf8')); console.log(data[0].filename)")
echo "package_file=${PACKAGE_FILE}" >> "$GITHUB_OUTPUT"
- name: Upload release artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ecc-release-artifacts
path: |
release_body.md
${{ steps.pack.outputs.package_file }}
if-no-files-found: error
publish:
name: Publish Release
runs-on: ubuntu-latest
needs: verify
permissions:
contents: write
id-token: write
steps:
- name: Download release artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: ecc-release-artifacts
- name: Setup Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
- name: Create GitHub Release
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
with:
@@ -145,7 +103,7 @@ jobs:
make_latest: ${{ contains(github.ref_name, '-') && 'false' || 'true' }}
- name: Publish npm package
if: needs.verify.outputs.already_published != 'true'
if: steps.npm_publish_state.outputs.already_published != 'true'
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npm publish "${{ needs.verify.outputs.package_file }}" --access public --provenance --tag "${{ needs.verify.outputs.dist_tag }}"
run: npm publish --access public --provenance --tag "${{ steps.npm_publish_state.outputs.dist_tag }}"

View File

@@ -28,16 +28,13 @@ on:
default: true
permissions:
contents: read
contents: write
id-token: write
jobs:
verify:
name: Verify Release
release:
name: Create Release
runs-on: ubuntu-latest
outputs:
already_published: ${{ steps.npm_publish_state.outputs.already_published }}
dist_tag: ${{ steps.npm_publish_state.outputs.dist_tag }}
package_file: ${{ steps.pack.outputs.package_file }}
steps:
- name: Checkout
@@ -56,9 +53,6 @@ jobs:
- name: Install dependencies
run: npm ci --ignore-scripts
- name: Run supply-chain IOC scan
run: npm run security:ioc-scan
- name: Verify OpenCode package payload
run: node tests/scripts/build-opencode.test.js
@@ -114,45 +108,9 @@ jobs:
### Package Notes
- npm package: \`ecc-universal\`
- Claude marketplace/plugin identifier: \`ecc@ecc\`
- Claude marketplace/plugin identifier: \`everything-claude-code@everything-claude-code\`
EOF
- name: Pack npm artifact
id: pack
run: |
npm pack --json > npm-pack.json
PACKAGE_FILE=$(node -e "const fs = require('fs'); const data = JSON.parse(fs.readFileSync('npm-pack.json', 'utf8')); console.log(data[0].filename)")
echo "package_file=${PACKAGE_FILE}" >> "$GITHUB_OUTPUT"
- name: Upload release artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ecc-release-artifacts
path: |
release_body.md
${{ steps.pack.outputs.package_file }}
if-no-files-found: error
publish:
name: Publish Release
runs-on: ubuntu-latest
needs: verify
permissions:
contents: write
id-token: write
steps:
- name: Download release artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: ecc-release-artifacts
- name: Setup Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
- name: Create GitHub Release
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
with:
@@ -163,7 +121,7 @@ jobs:
make_latest: ${{ contains(inputs.tag, '-') && 'false' || 'true' }}
- name: Publish npm package
if: needs.verify.outputs.already_published != 'true'
if: steps.npm_publish_state.outputs.already_published != 'true'
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npm publish "${{ needs.verify.outputs.package_file }}" --access public --provenance --tag "${{ needs.verify.outputs.dist_tag }}"
run: npm publish --access public --provenance --tag "${{ steps.npm_publish_state.outputs.dist_tag }}"

View File

@@ -36,7 +36,7 @@ jobs:
- name: Setup pnpm
if: inputs.package-manager == 'pnpm' && inputs.node-version != '18.x'
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
uses: pnpm/action-setup@91ab88e2619ed1f46221f0ba42d1492c02baf788 # v6.0.6
with:
# Keep an explicit pnpm major because this repo's packageManager is Yarn.
version: 10
@@ -59,24 +59,88 @@ jobs:
if: inputs.package-manager == 'bun'
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
- name: Get npm cache directory
if: inputs.package-manager == 'npm'
id: npm-cache-dir
shell: bash
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- name: Cache npm
if: inputs.package-manager == 'npm'
continue-on-error: true
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ steps.npm-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ inputs.node-version }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-${{ inputs.node-version }}-npm-
- name: Get pnpm store directory
if: inputs.package-manager == 'pnpm'
id: pnpm-cache-dir
shell: bash
env:
COREPACK_ENABLE_STRICT: '0'
run: echo "dir=$(pnpm store path)" >> $GITHUB_OUTPUT
- name: Cache pnpm
if: inputs.package-manager == 'pnpm'
continue-on-error: true
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ steps.pnpm-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ inputs.node-version }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-node-${{ inputs.node-version }}-pnpm-
- name: Get yarn cache directory
if: inputs.package-manager == 'yarn'
id: yarn-cache-dir
shell: bash
run: |
# Try Yarn Berry first, fall back to Yarn v1
if yarn config get cacheFolder >/dev/null 2>&1; then
echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
else
echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
fi
- name: Cache yarn
if: inputs.package-manager == 'yarn'
continue-on-error: true
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ steps.yarn-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ inputs.node-version }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-node-${{ inputs.node-version }}-yarn-
- name: Cache bun
if: inputs.package-manager == 'bun'
continue-on-error: true
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
restore-keys: |
${{ runner.os }}-bun-
# COREPACK_ENABLE_STRICT=0 allows pnpm to install even though
# package.json declares "packageManager": "yarn@..."
- name: Install dependencies
shell: bash
env:
COREPACK_ENABLE_STRICT: '0'
npm_config_ignore_scripts: 'true'
YARN_ENABLE_SCRIPTS: 'false'
run: |
case "${{ inputs.package-manager }}" in
npm) npm ci --ignore-scripts ;;
npm) npm ci ;;
# pnpm v10 can fail CI on ignored native build scripts
# (for example msgpackr-extract) even though this repo is Yarn-native
# and pnpm is only exercised here as a compatibility lane.
pnpm) pnpm install --ignore-scripts --config.strict-dep-builds=false --no-frozen-lockfile ;;
pnpm) pnpm install --config.strict-dep-builds=false --no-frozen-lockfile ;;
# Yarn Berry (v4+) removed --ignore-engines; engine checking is no longer a core feature
yarn) yarn install --mode=skip-build ;;
bun) bun install --ignore-scripts ;;
yarn) yarn install ;;
bun) bun install ;;
*) echo "Unsupported package manager: ${{ inputs.package-manager }}" && exit 1 ;;
esac

View File

@@ -1,65 +0,0 @@
name: Supply-Chain Watch
on:
schedule:
- cron: '17 */6 * * *'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
permissions:
contents: read
jobs:
ioc-watch:
name: IOC watch
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: '20.x'
- name: Install dependencies without lifecycle scripts
run: npm ci --ignore-scripts
- name: Verify registry signatures and advisories
run: |
npm audit signatures
npm audit --audit-level=high
- 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
- name: Upload IOC report
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: supply-chain-ioc-report
path: |
artifacts/supply-chain-ioc-report.json
artifacts/supply-chain-advisory-sources.json
retention-days: 14

View File

@@ -1,6 +1,6 @@
# Migration Guide: Claude Code to OpenCode
This guide helps you migrate from Claude Code to OpenCode while using the ECC configuration.
This guide helps you migrate from Claude Code to OpenCode while using the Everything Claude Code (ECC) configuration.
## Overview
@@ -365,4 +365,4 @@ If you need to switch back:
For issues specific to:
- **OpenCode CLI**: Report to OpenCode's issue tracker
- **ECC Configuration**: Report to [github.com/affaan-m/ECC](https://github.com/affaan-m/ECC)
- **ECC Configuration**: Report to [github.com/affaan-m/everything-claude-code](https://github.com/affaan-m/everything-claude-code)

View File

@@ -3,13 +3,13 @@
> WARNING: This README is specific to OpenCode usage.
> If you installed ECC via npm (e.g. `npm install opencode-ecc`), refer to the root README instead.
ECC plugin for OpenCode - agents, commands, hooks, and skills.
Everything Claude Code (ECC) plugin for OpenCode - agents, commands, hooks, and skills.
## Installation
## Installation Overview
There are two ways to use ECC:
There are two ways to use Everything Claude Code (ECC):
1. **npm package (recommended for most users)**
Install via npm/bun/yarn and use the `ecc-install` CLI to set up rules and agents.
@@ -52,8 +52,8 @@ npx ecc-install typescript
Clone and run OpenCode in the repository:
```bash
git clone https://github.com/affaan-m/ECC
cd ECC
git clone https://github.com/affaan-m/everything-claude-code
cd everything-claude-code
opencode
```

View File

@@ -24,9 +24,9 @@ node scripts/harness-audit.js <scope> --format <text|json> [--root <path>]
This script is the source of truth for scoring and checks. Do not invent additional dimensions or ad-hoc points.
Rubric version: `2026-05-19`.
Rubric version: `2026-03-30`.
The script computes up to 12 fixed categories (`0-10` normalized each). The first seven are always applicable; GitHub Integration is always applicable; deploy-target categories are applicable only when a matching marker is detected.
The script computes 7 fixed categories (`0-10` normalized each):
1. Tool Coverage
2. Context Efficiency
@@ -35,11 +35,6 @@ The script computes up to 12 fixed categories (`0-10` normalized each). The firs
5. Eval Coverage
6. Security Guardrails
7. Cost Efficiency
8. GitHub Integration
9. Vercel Integration *(when `vercel.json` or `.vercel/` is present)*
10. Netlify Integration *(when `netlify.toml` or `.netlify/` is present)*
11. Cloudflare Integration *(when `wrangler.toml` or `wrangler.jsonc` is present)*
12. Fly Integration *(when `fly.toml` is present)*
Scores are derived from explicit file/rule checks and are reproducible for the same commit.
The script audits the current working directory by default and auto-detects whether the target is the ECC repo itself or a consumer project using ECC.
@@ -48,12 +43,11 @@ The script audits the current working directory by default and auto-detects whet
Return:
1. `overall_score` out of `max_score`. `max_score` depends on which categories are applicable to the target; never assume a fixed total.
2. `applicable_categories[]` and `category_count` describing which categories contributed.
3. Category scores and concrete findings.
4. Failed checks with exact file paths.
5. Top 3 actions from the deterministic output (`top_actions`).
6. Suggested ECC skills to apply next.
1. `overall_score` out of `max_score` (70 for `repo`; smaller for scoped audits)
2. Category scores and concrete findings
3. Failed checks with exact file paths
4. Top 3 actions from the deterministic output (`top_actions`)
5. Suggested ECC skills to apply next
## Checklist
@@ -65,15 +59,14 @@ Return:
## Example Result
```text
Harness Audit (repo, repo): 71/80
Harness Audit (repo): 66/70
- Tool Coverage: 10/10 (10/10 pts)
- Context Efficiency: 9/10 (9/10 pts)
- Quality Gates: 10/10 (10/10 pts)
- GitHub Integration: 2/10 (2/10 pts)
Top 3 Actions:
1) [GitHub Integration] Add at least one workflow under .github/workflows/. (.github/workflows/)
2) [Security Guardrails] Add prompt/tool preflight security guards in hooks/hooks.json. (hooks/hooks.json)
1) [Security Guardrails] Add prompt/tool preflight security guards in hooks/hooks.json. (hooks/hooks.json)
2) [Tool Coverage] Sync commands/harness-audit.md and .opencode/commands/harness-audit.md. (.opencode/commands/harness-audit.md)
3) [Eval Coverage] Increase automated test coverage across scripts/hooks/lib. (tests/)
```

View File

@@ -1,5 +1,5 @@
/**
* ECC Plugin for OpenCode
* Everything Claude Code (ECC) Plugin for OpenCode
*
* This package provides the published ECC OpenCode plugin module:
* - Plugin hooks (auto-format, TypeScript check, console.log warning, env injection, etc.)
@@ -26,8 +26,8 @@
*
* Option 2: Clone and use directly
* ```bash
* git clone https://github.com/affaan-m/ECC
* cd ECC
* git clone https://github.com/affaan-m/everything-claude-code
* cd everything-claude-code
* opencode
* ```
*
@@ -47,7 +47,7 @@ export const VERSION = "1.6.0"
export const metadata = {
name: "ecc-universal",
version: VERSION,
description: "ECC plugin for OpenCode",
description: "Everything Claude Code plugin for OpenCode",
author: "affaan-m",
features: {
agents: 13,

View File

@@ -1,4 +1,4 @@
# ECC - OpenCode Instructions
# Everything Claude Code - OpenCode Instructions
This document consolidates the core rules and guidelines from the Claude Code configuration for use with OpenCode.

View File

@@ -1,7 +1,7 @@
{
"name": "ecc-universal",
"version": "2.0.0-rc.1",
"description": "ECC plugin for OpenCode - agents, commands, hooks, and skills",
"description": "Everything Claude Code (ECC) plugin for OpenCode - agents, commands, hooks, and skills",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"type": "module",
@@ -47,12 +47,12 @@
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/affaan-m/ECC.git"
"url": "git+https://github.com/affaan-m/everything-claude-code.git"
},
"bugs": {
"url": "https://github.com/affaan-m/ECC/issues"
"url": "https://github.com/affaan-m/everything-claude-code/issues"
},
"homepage": "https://github.com/affaan-m/ECC#readme",
"homepage": "https://github.com/affaan-m/everything-claude-code#readme",
"publishConfig": {
"access": "public"
},

View File

@@ -1,5 +1,5 @@
/**
* ECC Plugin Hooks for OpenCode
* Everything Claude Code (ECC) Plugin Hooks for OpenCode
*
* This plugin translates Claude Code hooks to OpenCode's plugin system.
* OpenCode's plugin system is MORE sophisticated than Claude Code with 20+ events
@@ -453,7 +453,7 @@ export const ECCHooksPlugin: ECCHooksPluginFn = async ({
const contextBlock = [
"# ECC Context (preserve across compaction)",
"",
"## Active Plugin: ECC v2.0.0-rc.1",
"## Active Plugin: Everything Claude Code v2.0.0-rc.1",
"- Hooks: file.edited, tool.execute.before/after, session.created/idle/deleted, shell.env, compacting, permission.ask",
"- Tools: run-tests, check-coverage, security-audit, format-code, lint-check, git-summary, changed-files",
"- Agents: 13 specialized (planner, architect, tdd-guide, code-reviewer, security-reviewer, build-error-resolver, e2e-runner, refactor-cleaner, doc-updater, go-reviewer, go-build-resolver, database-reviewer, python-reviewer)",

View File

@@ -1,5 +1,5 @@
/**
* ECC Plugins for OpenCode
* Everything Claude Code (ECC) Plugins for OpenCode
*
* This module exports all ECC plugins for OpenCode integration.
* Plugins provide hook-based automation that mirrors Claude Code's hook system

View File

@@ -15,8 +15,7 @@
"sourceMap": true,
"resolveJsonModule": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"types": ["node"]
"verbatimModuleSyntax": true
},
"include": [
"plugins/**/*.ts",

View File

@@ -1,41 +0,0 @@
{
"agent": {
"tool_permissions": {
"default": "confirm",
"tools": {
"terminal": {
"default": "confirm",
"always_deny": [
{
"pattern": "rm\\s+-rf\\s+(/|~)"
},
{
"pattern": "(^|\\s)(cat|sed|grep|rg)\\s+.*\\.(env|pem|key)(\\s|$)"
}
],
"always_confirm": [
{
"pattern": "sudo\\s"
},
{
"pattern": "(npm|pnpm|yarn|bun)\\s+(install|add|dlx|exec|x)\\b"
},
{
"pattern": "gh\\s+(auth|api|repo|release|pr|issue)\\b"
}
]
},
"edit_file": {
"always_deny": [
{
"pattern": "\\.env"
},
{
"pattern": "\\.(pem|key|p12|pfx)$"
}
]
}
}
}
}
}

View File

@@ -1,6 +1,6 @@
# Everything Claude Code (ECC) — Agent Instructions
This is a **production-ready AI coding plugin** providing 60 specialized agents, 232 skills, 75 commands, and automated hook workflows for software development.
This is a **production-ready AI coding plugin** providing 60 specialized agents, 228 skills, 75 commands, and automated hook workflows for software development.
**Version:** 2.0.0-rc.1
@@ -150,7 +150,7 @@ Troubleshoot failures: check test isolation → verify mocks → fix implementat
```
agents/ — 60 specialized subagents
skills/ — 232 workflow skills and domain knowledge
skills/ — 228 workflow skills and domain knowledge
commands/ — 75 slash commands
hooks/ — Trigger-based automations
rules/ — Always-follow guidelines (common + per-language)

169
README.md
View File

@@ -1,12 +1,12 @@
**Language:** English | [Português (Brasil)](docs/pt-BR/README.md) | [简体中文](README.zh-CN.md) | [繁體中文](docs/zh-TW/README.md) | [日本語](docs/ja-JP/README.md) | [한국어](docs/ko-KR/README.md) | [Türkçe](docs/tr/README.md) | [Русский](docs/ru/README.md) | [Tiếng Việt](docs/vi-VN/README.md) | [ไทย](docs/th/README.md)
**Language:** English | [Português (Brasil)](docs/pt-BR/README.md) | [简体中文](README.zh-CN.md) | [繁體中文](docs/zh-TW/README.md) | [日本語](docs/ja-JP/README.md) | [한국어](docs/ko-KR/README.md) | [Türkçe](docs/tr/README.md) | [Русский](docs/ru/README.md) | [Tiếng Việt](docs/vi-VN/README.md)
# ECC
# Everything Claude Code
![ECC - the harness-native operator system for agentic work](assets/hero.png)
![Everything Claude Code — the performance system for AI agent harnesses](assets/hero.png)
[![Stars](https://img.shields.io/github/stars/affaan-m/ECC?style=flat)](https://github.com/affaan-m/ECC/stargazers)
[![Forks](https://img.shields.io/github/forks/affaan-m/ECC?style=flat)](https://github.com/affaan-m/ECC/network/members)
[![Contributors](https://img.shields.io/github/contributors/affaan-m/ECC?style=flat)](https://github.com/affaan-m/ECC/graphs/contributors)
[![Stars](https://img.shields.io/github/stars/affaan-m/everything-claude-code?style=flat)](https://github.com/affaan-m/everything-claude-code/stargazers)
[![Forks](https://img.shields.io/github/forks/affaan-m/everything-claude-code?style=flat)](https://github.com/affaan-m/everything-claude-code/network/members)
[![Contributors](https://img.shields.io/github/contributors/affaan-m/everything-claude-code?style=flat)](https://github.com/affaan-m/everything-claude-code/graphs/contributors)
[![npm ecc-universal](https://img.shields.io/npm/dw/ecc-universal?label=ecc-universal%20weekly%20downloads&logo=npm)](https://www.npmjs.com/package/ecc-universal)
[![npm ecc-agentshield](https://img.shields.io/npm/dw/ecc-agentshield?label=ecc-agentshield%20weekly%20downloads&logo=npm)](https://www.npmjs.com/package/ecc-agentshield)
[![GitHub App Install](https://img.shields.io/badge/GitHub%20App-150%20installs-2ea44f?logo=github)](https://github.com/marketplace/ecc-tools)
@@ -19,7 +19,7 @@
![Perl](https://img.shields.io/badge/-Perl-39457E?logo=perl&logoColor=white)
![Markdown](https://img.shields.io/badge/-Markdown-000000?logo=markdown&logoColor=white)
> **182K+ stars** | **28K+ forks** | **170+ contributors** | **12+ language ecosystems** | **Anthropic Hackathon Winner**
> **140K+ stars** | **21K+ forks** | **170+ contributors** | **12+ language ecosystems** | **Anthropic Hackathon Winner**
---
@@ -28,56 +28,22 @@
**Language / 语言 / 語言 / Dil / Язык / Ngôn ngữ**
[**English**](README.md) | [Português (Brasil)](docs/pt-BR/README.md) | [简体中文](README.zh-CN.md) | [繁體中文](docs/zh-TW/README.md) | [日本語](docs/ja-JP/README.md) | [한국어](docs/ko-KR/README.md)
| [Türkçe](docs/tr/README.md) | [Русский](docs/ru/README.md) | [Tiếng Việt](docs/vi-VN/README.md) | [ไทย](docs/th/README.md)
| [Türkçe](docs/tr/README.md) | [Русский](docs/ru/README.md) | [Tiếng Việt](docs/vi-VN/README.md)
</div>
---
**The harness-native operator system for agentic work. From an Anthropic hackathon winner.**
**The performance optimization system for AI agent harnesses. From an Anthropic hackathon winner.**
Not just configs. A complete system: skills, instincts, memory optimization, continuous learning, security scanning, and research-first development. Production-ready agents, skills, hooks, rules, MCP configurations, and legacy command shims evolved over 10+ months of intensive daily use building real products.
Works across **Claude Code**, **Codex**, **Cursor**, **OpenCode**, **Gemini**, **Zed**, **GitHub Copilot**, and other AI agent harnesses.
Works across **Claude Code**, **Codex**, **Cursor**, **OpenCode**, **Gemini**, **GitHub Copilot**, and other AI agent harnesses.
ECC v2.0.0-rc.1 adds the public Hermes operator story on top of that reusable layer: start with the [Hermes setup guide](docs/HERMES-SETUP.md), then review the [rc.1 release notes](docs/releases/2.0.0-rc.1/release-notes.md) and [cross-harness architecture](docs/architecture/cross-harness.md).
---
<table>
<tr>
<td width="25%" align="center">
<a href="https://ecc.tools/pricing">
<strong> ECC Pro</strong><br />
<sub>Private repos · GitHub App · $19/seat/mo</sub>
</a>
</td>
<td width="25%" align="center">
<a href="https://github.com/sponsors/affaan-m">
<strong> Sponsor</strong><br />
<sub>Fund the OSS · From $5/mo</sub>
</a>
</td>
<td width="25%" align="center">
<a href="https://github.com/affaan-m/ECC/discussions">
<strong>Community</strong>
<br />
<sub>Discussions · Q&amp;A · Show & Tell</sub>
</a>
</td>
<td width="25%" align="center">
<a href="https://github.com/apps/ecc-tools">
<strong> GitHub App</strong><br />
<sub>Install · PR audits · Free tier</sub>
</a>
</td>
</tr>
</table>
<sub>**OSS stays free.** This repo is MIT-licensed forever. ECC Pro is the hosted GitHub App for private repos. <a href="https://github.com/sponsors/affaan-m">Sponsors</a> and <a href="https://ecc.tools/pricing">Pro subscribers</a> fund the work — that's why a single maintainer ships weekly across 7 harnesses.</sub>
---
## The Guides
This repo is the raw code only. The guides explain everything.
@@ -123,7 +89,7 @@ This repo is the raw code only. The guides explain everything.
### v2.0.0-rc.1 — Surface Refresh, Operator Workflows, and ECC 2.0 Alpha (Apr 2026)
- **Dashboard GUI** — New Tkinter-based desktop application (`ecc_dashboard.py` or `npm run dashboard`) with dark/light theme toggle, font customization, and project logo in header and taskbar.
- **Public surface synced to the live repo** — metadata, catalog counts, plugin manifests, and install-facing docs now match the actual OSS surface: 60 agents, 232 skills, and 75 legacy command shims.
- **Public surface synced to the live repo** — metadata, catalog counts, plugin manifests, and install-facing docs now match the actual OSS surface: 55 agents, 208 skills, and 72 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.
@@ -172,7 +138,7 @@ This repo is the raw code only. The guides explain everything.
### v1.4.1 — Bug Fix (Feb 2026)
- **Fixed instinct import content loss** — `parse_instinct_file()` was silently dropping all content after frontmatter (Action, Evidence, Examples sections) during `/instinct-import`. ([#148](https://github.com/affaan-m/ECC/issues/148), [#161](https://github.com/affaan-m/ECC/pull/161))
- **Fixed instinct import content loss** — `parse_instinct_file()` was silently dropping all content after frontmatter (Action, Evidence, Examples sections) during `/instinct-import`. ([#148](https://github.com/affaan-m/everything-claude-code/issues/148), [#161](https://github.com/affaan-m/everything-claude-code/pull/161))
### v1.4.0 — Multi-Language Rules, Installation Wizard & PM2 (Feb 2026)
@@ -196,7 +162,7 @@ This repo is the raw code only. The guides explain everything.
- **Session management** — `/sessions` command for session history
- **Continuous learning v2** — Instinct-based learning with confidence scoring, import/export, evolution
See the full changelog in [Releases](https://github.com/affaan-m/ECC/releases).
See the full changelog in [Releases](https://github.com/affaan-m/everything-claude-code/releases).
---
@@ -265,7 +231,7 @@ npx ecc install --profile minimal --target claude --with capability:machine-lear
```bash
# Add marketplace
/plugin marketplace add https://github.com/affaan-m/ECC
/plugin marketplace add https://github.com/affaan-m/everything-claude-code
# Install plugin
/plugin install ecc@ecc
@@ -275,7 +241,7 @@ npx ecc install --profile minimal --target claude --with capability:machine-lear
ECC now has three public identifiers, and they are not interchangeable:
- GitHub source repo: `affaan-m/ECC`
- GitHub source repo: `affaan-m/everything-claude-code`
- Claude marketplace/plugin identifier: `ecc@ecc`
- npm package: `ecc-universal`
@@ -295,8 +261,8 @@ This is intentional. Anthropic marketplace/plugin installs are keyed by a canoni
```bash
# Clone the repo first
git clone https://github.com/affaan-m/ECC.git
cd ECC
git clone https://github.com/affaan-m/everything-claude-code.git
cd everything-claude-code
# Install dependencies (pick your package manager)
npm install # or: pnpm install | yarn install | bun install
@@ -392,7 +358,7 @@ If you stacked methods, clean up in this order:
/plugin list ecc@ecc
```
**That's it!** You now have access to 60 agents, 232 skills, and 75 legacy command shims.
**That's it!** You now have access to 60 agents, 228 skills, and 75 legacy command shims.
### Dashboard GUI
@@ -429,7 +395,7 @@ python3 ./ecc_dashboard.py
## Cross-Platform Support
This plugin now fully supports **Windows, macOS, and Linux**, alongside tight integration across major IDEs (Cursor, Zed, OpenCode, Antigravity) and CLI harnesses. All hooks and scripts have been rewritten in Node.js for maximum compatibility.
This plugin now fully supports **Windows, macOS, and Linux**, alongside tight integration across major IDEs (Cursor, OpenCode, Antigravity) and CLI harnesses. All hooks and scripts have been rewritten in Node.js for maximum compatibility.
### Package Manager Detection
@@ -476,15 +442,6 @@ export ECC_SESSION_START_MAX_CHARS=4000
# Disable SessionStart additional context entirely for low-context/local-model setups
export ECC_SESSION_START_CONTEXT=off
# Keep context/scope/loop warnings but suppress API-rate cost estimates
export ECC_CONTEXT_MONITOR_COST_WARNINGS=off
```
Windows PowerShell:
```powershell
[Environment]::SetEnvironmentVariable('ECC_CONTEXT_MONITOR_COST_WARNINGS', 'off', 'User')
```
---
@@ -494,7 +451,7 @@ Windows PowerShell:
This repo is a **Claude Code plugin** - install it directly or copy components manually.
```
ECC/
everything-claude-code/
|-- .claude-plugin/ # Plugin and marketplace manifests
| |-- plugin.json # Plugin metadata and component paths
| |-- marketplace.json # Marketplace catalog for /plugin marketplace add
@@ -812,7 +769,7 @@ Claude Code v2.1+ **automatically loads** `hooks/hooks.json` from any installed
Duplicate hooks file detected: ./hooks/hooks.json resolves to already-loaded file
```
**History:** This has caused repeated fix/revert cycles in this repo ([#29](https://github.com/affaan-m/ECC/issues/29), [#52](https://github.com/affaan-m/ECC/issues/52), [#103](https://github.com/affaan-m/ECC/issues/103)). The behavior changed between Claude Code versions, leading to confusion. We now have a regression test to prevent this from being reintroduced.
**History:** This has caused repeated fix/revert cycles in this repo ([#29](https://github.com/affaan-m/everything-claude-code/issues/29), [#52](https://github.com/affaan-m/everything-claude-code/issues/52), [#103](https://github.com/affaan-m/everything-claude-code/issues/103)). The behavior changed between Claude Code versions, leading to confusion. We now have a regression test to prevent this from being reintroduced.
---
@@ -824,7 +781,7 @@ The easiest way to use this repo - install as a Claude Code plugin:
```bash
# Add this repo as a marketplace
/plugin marketplace add https://github.com/affaan-m/ECC
/plugin marketplace add https://github.com/affaan-m/everything-claude-code
# Install the plugin
/plugin install ecc@ecc
@@ -838,7 +795,7 @@ Or add directly to your `~/.claude/settings.json`:
"ecc": {
"source": {
"source": "github",
"repo": "affaan-m/ECC"
"repo": "affaan-m/everything-claude-code"
}
}
},
@@ -854,21 +811,20 @@ This gives you instant access to all commands, agents, skills, and hooks.
>
> ```bash
> # Clone the repo first
> git clone https://github.com/affaan-m/ECC.git
> cd ECC
> git clone https://github.com/affaan-m/everything-claude-code.git
>
> # Option A: User-level rules (applies to all projects)
> mkdir -p ~/.claude/rules/ecc
> cp -r rules/common ~/.claude/rules/ecc/
> cp -r rules/typescript ~/.claude/rules/ecc/ # pick your stack
> cp -r rules/python ~/.claude/rules/ecc/
> cp -r rules/golang ~/.claude/rules/ecc/
> cp -r rules/php ~/.claude/rules/ecc/
> cp -r everything-claude-code/rules/common ~/.claude/rules/ecc/
> cp -r everything-claude-code/rules/typescript ~/.claude/rules/ecc/ # pick your stack
> cp -r everything-claude-code/rules/python ~/.claude/rules/ecc/
> cp -r everything-claude-code/rules/golang ~/.claude/rules/ecc/
> cp -r everything-claude-code/rules/php ~/.claude/rules/ecc/
>
> # Option B: Project-level rules (applies to current project only)
> mkdir -p .claude/rules/ecc
> cp -r rules/common .claude/rules/ecc/
> cp -r rules/typescript .claude/rules/ecc/ # pick your stack
> cp -r everything-claude-code/rules/common .claude/rules/ecc/
> cp -r everything-claude-code/rules/typescript .claude/rules/ecc/ # pick your stack
> ```
---
@@ -879,35 +835,34 @@ If you prefer manual control over what's installed:
```bash
# Clone the repo
git clone https://github.com/affaan-m/ECC.git
cd ECC
git clone https://github.com/affaan-m/everything-claude-code.git
# Copy agents to your Claude config
cp agents/*.md ~/.claude/agents/
cp everything-claude-code/agents/*.md ~/.claude/agents/
# Copy rules directories (common + language-specific)
mkdir -p ~/.claude/rules/ecc
cp -r rules/common ~/.claude/rules/ecc/
cp -r rules/typescript ~/.claude/rules/ecc/ # pick your stack
cp -r rules/python ~/.claude/rules/ecc/
cp -r rules/golang ~/.claude/rules/ecc/
cp -r rules/php ~/.claude/rules/ecc/
cp -r rules/arkts ~/.claude/rules/ecc/
cp -r everything-claude-code/rules/common ~/.claude/rules/ecc/
cp -r everything-claude-code/rules/typescript ~/.claude/rules/ecc/ # pick your stack
cp -r everything-claude-code/rules/python ~/.claude/rules/ecc/
cp -r everything-claude-code/rules/golang ~/.claude/rules/ecc/
cp -r everything-claude-code/rules/php ~/.claude/rules/ecc/
cp -r everything-claude-code/rules/arkts ~/.claude/rules/ecc/
# Copy skills first (primary workflow surface)
# Recommended (new users): core/general skills only
mkdir -p ~/.claude/skills/ecc
cp -r .agents/skills/* ~/.claude/skills/ecc/
cp -r skills/search-first ~/.claude/skills/ecc/
cp -r everything-claude-code/.agents/skills/* ~/.claude/skills/ecc/
cp -r everything-claude-code/skills/search-first ~/.claude/skills/ecc/
# Optional: add niche/framework-specific skills only when needed
# for s in django-patterns django-tdd laravel-patterns springboot-patterns quarkus-patterns; do
# cp -r skills/$s ~/.claude/skills/ecc/
# cp -r everything-claude-code/skills/$s ~/.claude/skills/ecc/
# done
# Optional: keep maintained slash-command compatibility during migration
mkdir -p ~/.claude/commands
cp commands/*.md ~/.claude/commands/
cp everything-claude-code/commands/*.md ~/.claude/commands/
# Retired shims live in legacy-command-shims/commands/.
# Copy individual files from there only if you still need old names such as /tdd.
@@ -1085,7 +1040,7 @@ This shows all available agents, commands, and skills from the plugin.
<details>
<summary><b>My hooks aren't working / I see "Duplicate hooks file" errors</b></summary>
This is the most common issue. **Do NOT add a `"hooks"` field to `.claude-plugin/plugin.json`.** Claude Code v2.1+ automatically loads `hooks/hooks.json` from installed plugins. Explicitly declaring it causes duplicate detection errors. See [#29](https://github.com/affaan-m/ECC/issues/29), [#52](https://github.com/affaan-m/ECC/issues/52), [#103](https://github.com/affaan-m/ECC/issues/103).
This is the most common issue. **Do NOT add a `"hooks"` field to `.claude-plugin/plugin.json`.** Claude Code v2.1+ automatically loads `hooks/hooks.json` from installed plugins. Explicitly declaring it causes duplicate detection errors. See [#29](https://github.com/affaan-m/everything-claude-code/issues/29), [#52](https://github.com/affaan-m/everything-claude-code/issues/52), [#103](https://github.com/affaan-m/everything-claude-code/issues/103).
</details>
<details>
@@ -1130,11 +1085,11 @@ Yes. Use Option 2 (manual installation) and copy only what you need:
```bash
# Just agents
cp agents/*.md ~/.claude/agents/
cp everything-claude-code/agents/*.md ~/.claude/agents/
# Just rules
mkdir -p ~/.claude/rules/ecc/
cp -r rules/common ~/.claude/rules/ecc/
cp -r everything-claude-code/rules/common ~/.claude/rules/ecc/
```
Each component is fully independent.
@@ -1147,12 +1102,11 @@ Yes. ECC is cross-platform:
- **Cursor**: Pre-translated configs in `.cursor/`. See [Cursor IDE Support](#cursor-ide-support).
- **Gemini CLI**: Experimental project-local support via `.gemini/GEMINI.md` and shared installer plumbing.
- **OpenCode**: Full plugin support in `.opencode/`. See [OpenCode Support](#opencode-support).
- **Codex**: First-class support for both macOS app and CLI, with adapter drift guards and SessionStart fallback. See PR [#257](https://github.com/affaan-m/ECC/pull/257).
- **Codex**: First-class support for both macOS app and CLI, with adapter drift guards and SessionStart fallback. See PR [#257](https://github.com/affaan-m/everything-claude-code/pull/257).
- **GitHub Copilot (VS Code)**: Instruction and prompt layer via `.github/copilot-instructions.md`, `.vscode/settings.json`, and `.github/prompts/`. See [GitHub Copilot Support](#github-copilot-support).
- **Antigravity**: Tightly integrated setup for workflows, skills, and flattened rules in `.agent/`. See [Antigravity Guide](docs/ANTIGRAVITY-GUIDE.md).
- **JoyCode / CodeBuddy**: Project-local selective install adapters for commands, agents, skills, and flattened rules. See [JoyCode Adapter Guide](docs/JOYCODE-GUIDE.md).
- **Qwen CLI**: Home-directory selective install adapter for commands, agents, skills, rules, and Qwen config. See [Qwen CLI Adapter Guide](docs/QWEN-GUIDE.md).
- **Zed**: Project-local selective install adapter for `.zed/settings.json`, flattened rules, commands, agents, and skills.
- **Non-native harnesses**: Manual fallback path for Grok and similar interfaces. See [Manual Adaptation Guide](docs/MANUAL-ADAPTATION-GUIDE.md).
- **Claude Code**: Native — this is the primary target.
</details>
@@ -1387,22 +1341,6 @@ ECC ships three sample role configs:
---
## Zed Support
ECC provides Zed project support through a conservative `.zed` adapter for project-local settings, flattened rules, agents, commands, and skills.
```bash
./install.sh --profile minimal --target zed
```
```powershell
.\install.ps1 --profile minimal --target zed
```
The adapter writes ECC-managed files under `.zed/` and keeps BYOK/OpenRouter credentials out of the repo. Configure Zed account or API keys through Zed's own settings UI or your local user settings.
---
## OpenCode Support
ECC provides **full OpenCode support** including plugins and hooks.
@@ -1425,7 +1363,7 @@ The configuration is automatically detected from `.opencode/opencode.json`.
|---------|-------------|----------|--------|
| Agents | PASS: 60 agents | PASS: 12 agents | **Claude Code leads** |
| Commands | PASS: 75 commands | PASS: 35 commands | **Claude Code leads** |
| Skills | PASS: 232 skills | PASS: 37 skills | **Claude Code leads** |
| Skills | PASS: 228 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** |
@@ -1490,7 +1428,7 @@ OpenCode's plugin system is MORE sophisticated than Claude Code with 20+ event t
**Option 1: Use directly**
```bash
cd ECC
cd everything-claude-code
opencode
```
@@ -1587,7 +1525,7 @@ ECC is the **first plugin to maximize every major AI coding tool**. Here's how e
|---------|------------|------------|-----------|----------|----------------|
| **Agents** | 60 | Shared (AGENTS.md) | Shared (AGENTS.md) | 12 | N/A |
| **Commands** | 75 | Shared | Instruction-based | 35 | 6 prompts |
| **Skills** | 232 | Shared | 10 (native format) | 37 | Via instructions |
| **Skills** | 228 | 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 |
@@ -1638,7 +1576,6 @@ Add to `~/.claude/settings.json`:
| `model` | opus | **sonnet** | ~60% cost reduction; handles 80%+ of coding tasks |
| `MAX_THINKING_TOKENS` | 31,999 | **10,000** | ~70% reduction in hidden thinking cost per request |
| `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` | 95 | **50** | Compacts earlier — better quality in long sessions |
| `ECC_CONTEXT_MONITOR_COST_WARNINGS` | on | **off for subscription users** | Suppresses agent-facing API-rate estimate warnings while keeping context/scope/loop warnings |
Switch to Opus only when you need deep architectural reasoning:
```
@@ -1655,8 +1592,6 @@ Switch to Opus only when you need deep architectural reasoning:
| `/compact` | At logical task breakpoints (research done, milestone complete) |
| `/cost` | Monitor token spending during session |
If you use a Claude subscription and the context monitor's API-rate estimates are not useful, set `ECC_CONTEXT_MONITOR_COST_WARNINGS=off`. This only suppresses the agent-facing cost warnings; it does not disable context exhaustion, scope, or loop warnings.
### Strategic Compaction
The `strategic-compact` skill (included in this plugin) suggests `/compact` at logical breakpoints instead of relying on auto-compaction at 95% context. See `skills/strategic-compact/SKILL.md` for the full decision guide.
@@ -1719,7 +1654,7 @@ These configs work for my workflow. You should:
## Community Projects
Projects built on or inspired by ECC:
Projects built on or inspired by Everything Claude Code:
| Project | Description |
|---------|-------------|
@@ -1740,7 +1675,7 @@ This project is free and open source. Sponsors help keep it maintained and growi
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=affaan-m/ECC&type=Date)](https://star-history.com/#affaan-m/ECC&Date)
[![Star History Chart](https://api.star-history.com/svg?repos=affaan-m/everything-claude-code&type=Date)](https://star-history.com/#affaan-m/everything-claude-code&Date)
---

View File

@@ -23,7 +23,7 @@
**Language / 语言 / 語言 / Dil / Язык / Ngôn ngữ**
[**English**](README.md) | [Português (Brasil)](docs/pt-BR/README.md) | [简体中文](README.zh-CN.md) | [繁體中文](docs/zh-TW/README.md) | [日本語](docs/ja-JP/README.md) | [한국어](docs/ko-KR/README.md) | [Türkçe](docs/tr/README.md) | [Русский](docs/ru/README.md) | [Tiếng Việt](docs/vi-VN/README.md) | [ไทย](docs/th/README.md)
[**English**](README.md) | [Português (Brasil)](docs/pt-BR/README.md) | [简体中文](README.zh-CN.md) | [繁體中文](docs/zh-TW/README.md) | [日本語](docs/ja-JP/README.md) | [한국어](docs/ko-KR/README.md) | [Türkçe](docs/tr/README.md) | [Русский](docs/ru/README.md) | [Tiếng Việt](docs/vi-VN/README.md)
</div>
@@ -160,7 +160,7 @@ Copy-Item -Recurse rules/typescript "$HOME/.claude/rules/"
/plugin list ecc@ecc
```
**完成!** 你现在可以使用 60 个代理、232 个技能和 75 个命令。
**完成!** 你现在可以使用 60 个代理、228 个技能和 75 个命令。
### multi-* 命令需要额外配置

View File

@@ -1,76 +1,59 @@
# Sponsors
Thank you to everyone funding ECC's open-source work. Your sponsorship is what lets the OSS layer stay free while the GitHub App, hosted security scans, and continuous improvements ship every week.
Thank you to everyone who sponsors this project! Your support keeps the ECC ecosystem growing.
## Enterprise Sponsors — $2,500/mo
## Enterprise Sponsors
*Become an [Enterprise sponsor](https://github.com/sponsors/affaan-m) to be featured here.*
*Become an [Enterprise sponsor](https://github.com/sponsors/affaan-m) to be featured here*
## Business Sponsors — $500/mo
## Business Sponsors
| Sponsor | Logo | Since |
|---------|------|-------|
| [**CodeRabbit**](https://coderabbit.ai) | <img src="https://avatars.githubusercontent.com/u/132028505?s=120" width="60" alt="CodeRabbit" /> | 2026 |
*Become a [Business sponsor](https://github.com/sponsors/affaan-m) to be featured here*
*[Become a Business sponsor](https://github.com/sponsors/affaan-m) to be featured here with logo placement in the main README hero and a quarterly case study.*
## Team Sponsors
## Team Sponsors — $200/mo
*Become a [Team sponsor](https://github.com/sponsors/affaan-m) to be featured here*
| Sponsor | Since |
|---------|-------|
| [Mike Morgan](https://github.com/mikejmorgan-ai) | 2026 |
## Individual Sponsors
*[Become a Team sponsor](https://github.com/sponsors/affaan-m) to get small logo placement and 5 ECC Pro seats.*
## Pro Sponsors — $50/mo
*[Become a Pro sponsor](https://github.com/sponsors/affaan-m) to be listed here with your name in the main README sponsor row.*
## Builder Sponsors — $25/mo
- @jasonwu513 (grandfathered at $10)
- @1anter (grandfathered at $10)
- @massimotodaro (grandfathered at $10)
- @meadmccabe (grandfathered at $10)
*[Become a Builder sponsor](https://github.com/sponsors/affaan-m) to support the project and get your name in this list + a private monthly progress note.*
## Supporters — $5/mo
*[Become a Supporter](https://github.com/sponsors/affaan-m) to back the project with a profile badge and a thank-you in our release notes.*
---
## Sponsorship Tiers
| Tier | Monthly | Perks |
|------|--------:|-------|
| Supporter | $5 | Sponsor badge on profile, thank-you in release notes |
| Builder | $25 | Above + name in SPONSORS.md + private monthly progress note |
| Pro Sponsor | $50 | Above + name in main README + 1 quarterly roadmap vote |
| Team | $200 | Above + small org logo in README + 5 ECC Pro seats |
| Business | $500 | Above + featured logo in README hero + quarterly case study + Discord sponsors-lounge access |
| Enterprise | $2,500 | Above + unlimited Pro seats + 30 min/mo founder time + SLA + dedicated channel |
[**Become a Sponsor →**](https://github.com/sponsors/affaan-m)
For corporate sponsorship inquiries, custom partnerships, or PR integrations, email **[affaan@ecc.tools](mailto:affaan@ecc.tools)** with your company name and intended tier. We'll move fast — most agreements close within 48 hours.
*Become a [sponsor](https://github.com/sponsors/affaan-m) to be listed here*
---
## Why Sponsor?
Your sponsorship directly funds:
Your sponsorship helps:
- **OSS work that stays free** — the core repo, AgentShield, install scripts, and skills library remain MIT
- **Weekly releases** — full-time work on the harness, not a side project
- **Independent maintenance** — no acquisition pressure, no rug pulls, no enshittification
- **Sponsor-driven roadmap** — Pro+ sponsors vote on direction, Business+ get case studies and integration support
- **Ship faster** — More time dedicated to building tools and features
- **Keep it free** — Premium features fund the free tier for everyone
- **Better support** — Sponsors get priority responses
- **Shape the roadmap** — Pro+ sponsors vote on features
## Existing Sponsors Are Grandfathered
## Sponsor Readiness Signals
If you sponsored before May 2026, you keep your original perks at your original price. New tiers apply to new sponsors only.
Use these proof points in sponsor conversations:
- Live npm install/download metrics for `ecc-universal` and `ecc-agentshield`
- GitHub App distribution via Marketplace installs
- Public adoption signals: stars, forks, contributors, release cadence
- Cross-harness support: Claude Code, Cursor, OpenCode, Codex app/CLI
See [`docs/business/metrics-and-sponsorship.md`](docs/business/metrics-and-sponsorship.md) for a copy/paste metrics pull workflow.
## Sponsor Tiers
| Tier | Price | Benefits |
|------|-------|----------|
| Supporter | $5/mo | Name in README, early access |
| Builder | $10/mo | Premium tools access |
| Pro | $25/mo | Priority support, office hours |
| Team | $100/mo | 5 seats, team configs |
| Harness Partner | $200/mo | Monthly roadmap sync, prioritized maintainer feedback, release-note mention |
| Business | $500/mo | 25 seats, consulting credit |
| Enterprise | $2K/mo | Unlimited seats, custom tools |
[**Become a Sponsor →**](https://github.com/sponsors/affaan-m)
---
*Auto-updated by Hermes on every release. Last sync: 2026-05-14*
*Updated automatically. Last sync: February 2026*

View File

@@ -1,5 +1,5 @@
spec_version: "0.1.0"
name: ecc
name: everything-claude-code
version: 2.0.0-rc.1
description: "Initial gitagent export surface for ECC's shared skill catalog, governance, and identity. Native agents, commands, and hooks remain authoritative in the repository while manifest coverage expands."
author: affaan-m

View File

@@ -24,9 +24,9 @@ node scripts/harness-audit.js <scope> --format <text|json> [--root <path>]
This script is the source of truth for scoring and checks. Do not invent additional dimensions or ad-hoc points.
Rubric version: `2026-05-19`.
Rubric version: `2026-03-30`.
The script computes up to 12 fixed categories (`0-10` normalized each). The first seven are always applicable; GitHub Integration is always applicable; deploy-target categories are applicable only when a matching marker is detected.
The script computes 7 fixed categories (`0-10` normalized each):
1. Tool Coverage
2. Context Efficiency
@@ -35,11 +35,6 @@ The script computes up to 12 fixed categories (`0-10` normalized each). The firs
5. Eval Coverage
6. Security Guardrails
7. Cost Efficiency
8. GitHub Integration
9. Vercel Integration *(when `vercel.json` or `.vercel/` is present)*
10. Netlify Integration *(when `netlify.toml` or `.netlify/` is present)*
11. Cloudflare Integration *(when `wrangler.toml` or `wrangler.jsonc` is present)*
12. Fly Integration *(when `fly.toml` is present)*
Scores are derived from explicit file/rule checks and are reproducible for the same commit.
The script audits the current working directory by default and auto-detects whether the target is the ECC repo itself or a consumer project using ECC.
@@ -48,12 +43,11 @@ The script audits the current working directory by default and auto-detects whet
Return:
1. `overall_score` out of `max_score`. `max_score` depends on which categories are applicable to the target; never assume a fixed total.
2. `applicable_categories[]` and `category_count` describing which categories contributed.
3. Category scores and concrete findings.
4. Failed checks with exact file paths.
5. Top 3 actions from the deterministic output (`top_actions`).
6. Suggested ECC skills to apply next.
1. `overall_score` out of `max_score` (70 for `repo`; smaller for scoped audits)
2. Category scores and concrete findings
3. Failed checks with exact file paths
4. Top 3 actions from the deterministic output (`top_actions`)
5. Suggested ECC skills to apply next
## Checklist
@@ -65,15 +59,14 @@ Return:
## Example Result
```text
Harness Audit (repo, repo): 71/80
Harness Audit (repo): 66/70
- Tool Coverage: 10/10 (10/10 pts)
- Context Efficiency: 9/10 (9/10 pts)
- Quality Gates: 10/10 (10/10 pts)
- GitHub Integration: 2/10 (2/10 pts)
Top 3 Actions:
1) [GitHub Integration] Add at least one workflow under .github/workflows/. (.github/workflows/)
2) [Security Guardrails] Add prompt/tool preflight security guards in hooks/hooks.json. (hooks/hooks.json)
1) [Security Guardrails] Add prompt/tool preflight security guards in hooks/hooks.json. (hooks/hooks.json)
2) [Tool Coverage] Sync commands/harness-audit.md and .opencode/commands/harness-audit.md. (.opencode/commands/harness-audit.md)
3) [Eval Coverage] Increase automated test coverage across scripts/hooks/lib. (tests/)
```

View File

@@ -1,898 +0,0 @@
{
"schemaVersion": 1,
"totalCommands": 75,
"commands": [
{
"command": "aside",
"description": "Answer a quick side question without interrupting or losing context from the current task. Resume work automatically after answering.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/aside.md"
},
{
"command": "auto-update",
"description": "Pull the latest ECC repo changes and reinstall the current managed targets.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/auto-update.md"
},
{
"command": "build-fix",
"description": "Detect the project build system and incrementally fix build/type errors with minimal safe changes.",
"type": "refactoring",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/build-fix.md"
},
{
"command": "checkpoint",
"description": "Create, verify, or list workflow checkpoints after running verification checks.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/checkpoint.md"
},
{
"command": "code-review",
"description": "Code review — local uncommitted changes or GitHub PR (pass PR number/URL for PR mode)",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/code-review.md"
},
{
"command": "cost-report",
"description": "Generate a local Claude Code cost report from a cost-tracker SQLite database.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/cost-report.md"
},
{
"command": "cpp-build",
"description": "Fix C++ build errors, CMake issues, and linker problems incrementally. Invokes the cpp-build-resolver agent for minimal, surgical fixes.",
"type": "testing",
"primaryAgents": [
"cpp-build-resolver"
],
"allAgents": [
"cpp-build-resolver"
],
"skills": [
"cpp-coding-standards"
],
"path": "commands/cpp-build.md"
},
{
"command": "cpp-review",
"description": "Comprehensive C++ code review for memory safety, modern C++ idioms, concurrency, and security. Invokes the cpp-reviewer agent.",
"type": "testing",
"primaryAgents": [
"cpp-reviewer"
],
"allAgents": [
"cpp-reviewer"
],
"skills": [
"cpp-coding-standards",
"cpp-testing"
],
"path": "commands/cpp-review.md"
},
{
"command": "cpp-test",
"description": "Enforce TDD workflow for C++. Write GoogleTest tests first, then implement. Verify coverage with gcov/lcov.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [
"cpp-testing",
"tdd-workflow"
],
"path": "commands/cpp-test.md"
},
{
"command": "ecc-guide",
"description": "Navigate ECC's current agents, skills, commands, hooks, install profiles, and docs from the live repository surface.",
"type": "review",
"primaryAgents": [],
"allAgents": [],
"skills": [
"ecc-guide",
"security-scan"
],
"path": "commands/ecc-guide.md"
},
{
"command": "evolve",
"description": "Analyze instincts and suggest or generate evolved structures",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [
"continuous-learning-v2"
],
"path": "commands/evolve.md"
},
{
"command": "fastapi-review",
"description": "Review a FastAPI application for architecture, async correctness, dependency injection, Pydantic schemas, security, performance, and testability.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/fastapi-review.md"
},
{
"command": "feature-dev",
"description": "Guided feature development with codebase understanding and architecture focus",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/feature-dev.md"
},
{
"command": "flutter-build",
"description": "Fix Dart analyzer errors and Flutter build failures incrementally. Invokes the dart-build-resolver agent for minimal, surgical fixes.",
"type": "testing",
"primaryAgents": [
"dart-build-resolver"
],
"allAgents": [
"dart-build-resolver"
],
"skills": [
"flutter-dart-code-review"
],
"path": "commands/flutter-build.md"
},
{
"command": "flutter-review",
"description": "Review Flutter/Dart code for idiomatic patterns, widget best practices, state management, performance, accessibility, and security. Invokes the flutter-reviewer agent.",
"type": "testing",
"primaryAgents": [
"flutter-reviewer"
],
"allAgents": [
"flutter-reviewer"
],
"skills": [
"flutter-dart-code-review"
],
"path": "commands/flutter-review.md"
},
{
"command": "flutter-test",
"description": "Run Flutter/Dart tests, report failures, and incrementally fix test issues. Covers unit, widget, golden, and integration tests.",
"type": "testing",
"primaryAgents": [
"dart-build-resolver",
"flutter-reviewer"
],
"allAgents": [
"dart-build-resolver",
"flutter-reviewer"
],
"skills": [
"flutter-dart-code-review"
],
"path": "commands/flutter-test.md"
},
{
"command": "gan-build",
"description": "Run a generator/evaluator build loop for implementation tasks with bounded iterations and scoring.",
"type": "orchestration",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/gan-build.md"
},
{
"command": "gan-design",
"description": "Run a generator/evaluator design loop for frontend or visual work with bounded iterations and scoring.",
"type": "planning",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/gan-design.md"
},
{
"command": "go-build",
"description": "Fix Go build errors, go vet warnings, and linter issues incrementally. Invokes the go-build-resolver agent for minimal, surgical fixes.",
"type": "testing",
"primaryAgents": [
"go-build-resolver"
],
"allAgents": [
"go-build-resolver"
],
"skills": [
"golang-patterns"
],
"path": "commands/go-build.md"
},
{
"command": "go-review",
"description": "Comprehensive Go code review for idiomatic patterns, concurrency safety, error handling, and security. Invokes the go-reviewer agent.",
"type": "testing",
"primaryAgents": [
"go-reviewer"
],
"allAgents": [
"go-reviewer"
],
"skills": [
"golang-patterns",
"golang-testing"
],
"path": "commands/go-review.md"
},
{
"command": "go-test",
"description": "Enforce TDD workflow for Go. Write table-driven tests first, then implement. Verify 80%+ coverage with go test -cover.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [
"golang-testing",
"tdd-workflow"
],
"path": "commands/go-test.md"
},
{
"command": "gradle-build",
"description": "Fix Gradle build errors for Android and KMP projects",
"type": "build",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/gradle-build.md"
},
{
"command": "harness-audit",
"description": "Run a deterministic repository harness audit and return a prioritized scorecard.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/harness-audit.md"
},
{
"command": "hookify-configure",
"description": "Enable or disable hookify rules interactively",
"type": "general",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/hookify-configure.md"
},
{
"command": "hookify-help",
"description": "Get help with the hookify system",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/hookify-help.md"
},
{
"command": "hookify-list",
"description": "List all configured hookify rules",
"type": "general",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/hookify-list.md"
},
{
"command": "hookify",
"description": "Create hooks to prevent unwanted behaviors from conversation analysis or explicit instructions",
"type": "general",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/hookify.md"
},
{
"command": "instinct-export",
"description": "Export instincts from project/global scope to a file",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/instinct-export.md"
},
{
"command": "instinct-import",
"description": "Import instincts from file or URL into project/global scope",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [
"continuous-learning-v2"
],
"path": "commands/instinct-import.md"
},
{
"command": "instinct-status",
"description": "Show learned instincts (project + global) with confidence",
"type": "review",
"primaryAgents": [],
"allAgents": [],
"skills": [
"continuous-learning-v2"
],
"path": "commands/instinct-status.md"
},
{
"command": "jira",
"description": "Retrieve a Jira ticket, analyze requirements, update status, or add comments. Uses the jira-integration skill and MCP or REST API.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [
"jira-integration"
],
"path": "commands/jira.md"
},
{
"command": "kotlin-build",
"description": "Fix Kotlin/Gradle build errors, compiler warnings, and dependency issues incrementally. Invokes the kotlin-build-resolver agent for minimal, surgical fixes.",
"type": "testing",
"primaryAgents": [
"kotlin-build-resolver"
],
"allAgents": [
"kotlin-build-resolver"
],
"skills": [
"kotlin-patterns"
],
"path": "commands/kotlin-build.md"
},
{
"command": "kotlin-review",
"description": "Comprehensive Kotlin code review for idiomatic patterns, null safety, coroutine safety, and security. Invokes the kotlin-reviewer agent.",
"type": "testing",
"primaryAgents": [
"kotlin-reviewer"
],
"allAgents": [
"kotlin-reviewer"
],
"skills": [
"kotlin-patterns",
"kotlin-testing"
],
"path": "commands/kotlin-review.md"
},
{
"command": "kotlin-test",
"description": "Enforce TDD workflow for Kotlin. Write Kotest tests first, then implement. Verify 80%+ coverage with Kover.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [
"kotlin-testing",
"tdd-workflow"
],
"path": "commands/kotlin-test.md"
},
{
"command": "learn-eval",
"description": "Extract reusable patterns from the session, self-evaluate quality before saving, and determine the right save location (Global vs Project).",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/learn-eval.md"
},
{
"command": "learn",
"description": "Extract reusable patterns from the current session and save them as candidate skills or guidance.",
"type": "review",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/learn.md"
},
{
"command": "loop-start",
"description": "Start a managed autonomous loop pattern with safety defaults and explicit stop conditions.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/loop-start.md"
},
{
"command": "loop-status",
"description": "Inspect active loop state, progress, failure signals, and recommended intervention.",
"type": "general",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/loop-status.md"
},
{
"command": "model-route",
"description": "Recommend the best model tier for the current task based on complexity, risk, and budget.",
"type": "review",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/model-route.md"
},
{
"command": "multi-backend",
"description": "Run a backend-focused multi-model workflow for APIs, algorithms, data, and business logic.",
"type": "orchestration",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/multi-backend.md"
},
{
"command": "multi-execute",
"description": "Execute a multi-model implementation plan while preserving Claude as the only filesystem writer.",
"type": "orchestration",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/multi-execute.md"
},
{
"command": "multi-frontend",
"description": "Run a frontend-focused multi-model workflow for components, layouts, animation, and UI polish.",
"type": "orchestration",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/multi-frontend.md"
},
{
"command": "multi-plan",
"description": "Create a multi-model implementation plan without modifying production code.",
"type": "orchestration",
"primaryAgents": [],
"allAgents": [],
"skills": [
"accessibility"
],
"path": "commands/multi-plan.md"
},
{
"command": "multi-workflow",
"description": "Run a full multi-model development workflow with research, planning, execution, optimization, and review.",
"type": "orchestration",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/multi-workflow.md"
},
{
"command": "plan-prd",
"description": "Generate a lean, problem-first PRD and hand off to /plan for implementation planning.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/plan-prd.md"
},
{
"command": "plan",
"description": "Restate requirements, assess risks, and create step-by-step implementation plan. WAIT for user CONFIRM before touching any code.",
"type": "testing",
"primaryAgents": [
"planner"
],
"allAgents": [
"planner"
],
"skills": [],
"path": "commands/plan.md"
},
{
"command": "pm2",
"description": "Analyze a project and generate PM2 service commands for detected frontend, backend, or database services.",
"type": "general",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/pm2.md"
},
{
"command": "pr",
"description": "Create a GitHub PR from current branch with unpushed commits — discovers templates, analyzes changes, pushes",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/pr.md"
},
{
"command": "project-init",
"description": "Detect a project's stack and produce a dry-run ECC onboarding plan using the repository's install manifests and stack mappings.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [
"ecc-guide"
],
"path": "commands/project-init.md"
},
{
"command": "projects",
"description": "List known projects and their instinct statistics",
"type": "general",
"primaryAgents": [],
"allAgents": [],
"skills": [
"continuous-learning-v2"
],
"path": "commands/projects.md"
},
{
"command": "promote",
"description": "Promote project-scoped instincts to global scope",
"type": "review",
"primaryAgents": [],
"allAgents": [],
"skills": [
"continuous-learning-v2"
],
"path": "commands/promote.md"
},
{
"command": "prp-commit",
"description": "Quick commit with natural language file targeting — describe what to commit in plain English",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/prp-commit.md"
},
{
"command": "prp-implement",
"description": "Execute an implementation plan with rigorous validation loops",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/prp-implement.md"
},
{
"command": "prp-plan",
"description": "Create comprehensive feature implementation plan with codebase analysis and pattern extraction",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/prp-plan.md"
},
{
"command": "prp-pr",
"description": "Create a GitHub PR from current branch with unpushed commits — discovers templates, analyzes changes, pushes",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/prp-pr.md"
},
{
"command": "prp-prd",
"description": "Interactive PRD generator - problem-first, hypothesis-driven product spec with back-and-forth questioning",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/prp-prd.md"
},
{
"command": "prune",
"description": "Delete pending instincts older than 30 days that were never promoted",
"type": "review",
"primaryAgents": [],
"allAgents": [],
"skills": [
"continuous-learning-v2"
],
"path": "commands/prune.md"
},
{
"command": "python-review",
"description": "Comprehensive Python code review for PEP 8 compliance, type hints, security, and Pythonic idioms. Invokes the python-reviewer agent.",
"type": "testing",
"primaryAgents": [
"python-reviewer"
],
"allAgents": [
"python-reviewer"
],
"skills": [
"python-patterns",
"python-testing"
],
"path": "commands/python-review.md"
},
{
"command": "quality-gate",
"description": "Run the ECC quality pipeline for a file or project scope and report remediation steps.",
"type": "general",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/quality-gate.md"
},
{
"command": "refactor-clean",
"description": "Safely identify and remove dead code with verification after each change.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/refactor-clean.md"
},
{
"command": "resume-session",
"description": "Load the most recent session file from ~/.claude/session-data/ and resume work with full context from where the last session ended.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/resume-session.md"
},
{
"command": "review-pr",
"description": "Comprehensive PR review using specialized agents",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/review-pr.md"
},
{
"command": "rust-build",
"description": "Fix Rust build errors, borrow checker issues, and dependency problems incrementally. Invokes the rust-build-resolver agent for minimal, surgical fixes.",
"type": "testing",
"primaryAgents": [
"rust-build-resolver"
],
"allAgents": [
"rust-build-resolver"
],
"skills": [
"rust-patterns"
],
"path": "commands/rust-build.md"
},
{
"command": "rust-review",
"description": "Comprehensive Rust code review for ownership, lifetimes, error handling, unsafe usage, and idiomatic patterns. Invokes the rust-reviewer agent.",
"type": "testing",
"primaryAgents": [
"rust-reviewer"
],
"allAgents": [
"rust-reviewer"
],
"skills": [
"rust-patterns",
"rust-testing"
],
"path": "commands/rust-review.md"
},
{
"command": "rust-test",
"description": "Enforce TDD workflow for Rust. Write tests first, then implement. Verify 80%+ coverage with cargo-llvm-cov.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [
"rust-patterns",
"rust-testing"
],
"path": "commands/rust-test.md"
},
{
"command": "santa-loop",
"description": "Adversarial dual-review convergence loop — two independent model reviewers must both approve before code ships.",
"type": "review",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/santa-loop.md"
},
{
"command": "save-session",
"description": "Save current session state to a dated file in ~/.claude/session-data/ so work can be resumed in a future session with full context.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/save-session.md"
},
{
"command": "security-scan",
"description": "Run AgentShield against agent, hook, MCP, permission, and secret surfaces.",
"type": "review",
"primaryAgents": [
"security-reviewer"
],
"allAgents": [
"security-reviewer"
],
"skills": [
"security-scan"
],
"path": "commands/security-scan.md"
},
{
"command": "sessions",
"description": "Manage Claude Code session history, aliases, and session metadata.",
"type": "general",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/sessions.md"
},
{
"command": "setup-pm",
"description": "Configure your preferred package manager (npm/pnpm/yarn/bun)",
"type": "build",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/setup-pm.md"
},
{
"command": "skill-create",
"description": "Analyze local git history to extract coding patterns and generate SKILL.md files. Local version of the Skill Creator GitHub App.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/skill-create.md"
},
{
"command": "skill-health",
"description": "Show skill portfolio health dashboard with charts and analytics",
"type": "review",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/skill-health.md"
},
{
"command": "test-coverage",
"description": "Analyze coverage, identify gaps, and generate missing tests toward the target threshold.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/test-coverage.md"
},
{
"command": "update-codemaps",
"description": "Scan project structure and generate token-lean architecture codemaps.",
"type": "planning",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/update-codemaps.md"
},
{
"command": "update-docs",
"description": "Sync documentation from source-of-truth files such as scripts, schemas, routes, and exports.",
"type": "testing",
"primaryAgents": [],
"allAgents": [],
"skills": [],
"path": "commands/update-docs.md"
}
],
"statistics": {
"byType": {
"build": 2,
"general": 8,
"orchestration": 6,
"planning": 2,
"refactoring": 1,
"review": 9,
"testing": 47
},
"topAgents": [
{
"agent": "dart-build-resolver",
"count": 2
},
{
"agent": "flutter-reviewer",
"count": 2
},
{
"agent": "cpp-build-resolver",
"count": 1
},
{
"agent": "cpp-reviewer",
"count": 1
},
{
"agent": "go-build-resolver",
"count": 1
},
{
"agent": "go-reviewer",
"count": 1
},
{
"agent": "kotlin-build-resolver",
"count": 1
},
{
"agent": "kotlin-reviewer",
"count": 1
},
{
"agent": "planner",
"count": 1
},
{
"agent": "python-reviewer",
"count": 1
}
],
"topSkills": [
{
"skill": "continuous-learning-v2",
"count": 6
},
{
"skill": "flutter-dart-code-review",
"count": 3
},
{
"skill": "rust-patterns",
"count": 3
},
{
"skill": "tdd-workflow",
"count": 3
},
{
"skill": "cpp-coding-standards",
"count": 2
},
{
"skill": "cpp-testing",
"count": 2
},
{
"skill": "ecc-guide",
"count": 2
},
{
"skill": "golang-patterns",
"count": 2
},
{
"skill": "golang-testing",
"count": 2
},
{
"skill": "kotlin-patterns",
"count": 2
}
]
}
}

View File

@@ -1,257 +1,39 @@
# ECC 2.0 GA Roadmap
This roadmap is the durable repo mirror for the active Linear project:
This roadmap is the durable repo mirror for the Linear project:
<https://linear.app/itomarkets/project/ecc-platform-roadmap-52b328ee03e1>
<https://linear.app/ecctools/project/ecc-20-ga-harness-os-security-platform-de2a0ecace6f>
Linear issue creation is available again in the Ito Markets workspace. The live
execution truth is split across:
Linear issue creation is currently blocked by the workspace active issue limit,
so the live execution truth is split across:
- the Linear project documents, issue lanes, dependencies, and milestones;
- the Linear project description, status updates, and milestones;
- this repo document;
- merged PR evidence;
- handoffs under `~/.cluster-swarm/handoffs/`.
The May 19 release/growth execution map lives at
[`docs/releases/2.0.0/ecc-2-hypergrowth-release-command-center.md`](releases/2.0.0/ecc-2-hypergrowth-release-command-center.md).
It is the operator surface for the final ECC 2.0 repo identity, video suite,
partner/sponsor funnel, consulting/talk funnel, and social launch plan.
## 2026-05-20 Delta
- The tracked platform audit is still green on May 20 with 0 open PRs,
0 open issues, 0 discussion maintainer-touch gaps, 0 answerable Q&A gaps,
0 conflicting PRs, and 0 blocking dirty files across `affaan-m/ECC`,
`affaan-m/agentshield`, `affaan-m/JARVIS`, `ECC-Tools/ECC-Tools`, and
`ECC-Tools/ECC-website`.
- The new #2015 setup-location Q&A was answered and marked accepted. The
answer keeps install guidance conservative: do not install into `C:\`; use a
normal workspace, install the `ecc@ecc` Claude plugin once, copy only needed
rule folders when using manual rules, and avoid stacking plugin plus full
manual install.
- ECC-Tools PRs #80-#88 landed the next hosted-platform batch: runtime
receipts now require failure reasons; AgentShield fleet approval IDs survive
hosted security review and render into comments/check-runs; Linear follow-up
sync reuses deterministic external IDs; hosted AgentShield remediation items
sync to Linear; hosted job observability events are emitted for queued,
completed, blocked, failed, and budget-blocked states; and both hosted job
status comments and hosted depth-plan check-runs read back recent
observability/budget events. PR #88 adds the authenticated observability API
readback for operator dashboards and production smoke tests.
- AgentShield PR #94 landed the next cross-harness adapter slice: Zed and
VS Code are first-class adapter detections, `.zed/settings.json` and
`.zed/tasks.json` are discoverable scan inputs, and `.zed/setup.mjs` now
trips the same AI-tool persistence IOC rule as `.vscode/setup.mjs`.
- AgentShield PR #95 cleared the remaining default-branch Dependabot alert by
moving transitive `brace-expansion` 5.x lockfile entries to `5.0.6`; the
post-merge Dependabot open-alert API now returns `[]`, and local
`npm audit --audit-level=moderate` returns 0 vulnerabilities.
- ECC PR #2019 merged the Marketplace Pro selected-target release-gate sync
into this repo as `30f60710d4e0424fc70d9bbdc105009db141d9d8`. The post-merge
main CI run `26135974576` completed green across lint, coverage, security,
validation, and the full OS/package-manager matrix.
- ECC PR #2020 merged the selected-target announcement-gate mirror as
`c2471fe5c535310f8a8008c9ed7ea9f6757b33f2`. The post-merge main CI run
`26136949698` completed green across lint, coverage, security, validation,
and the full OS/package-manager matrix.
- ECC-Tools PR #90 added the selected-target official announcement gate for
`billing:announcement-gate -- --select-ready-target`; safe production
preflight no longer requires a raw GitHub login and now blocks only on the
local/internal `INTERNAL_API_SECRET` input before live execution.
- ECC-Tools PR #91 added `--env-file` support to both billing gate scripts so
ignored local operator credential files can supply `INTERNAL_API_SECRET`,
Cloudflare auth, Wrangler auth mode, or target fallbacks without printing
secret contents. Verify, Security Audit, and Workers Builds passed before
merge as `72119a1`, and main CI run `26137280847` completed successfully after
merge.
- ECC-Tools PR #92 added a non-breaking `INTERNAL_OPERATOR_API_SECRET` bearer
accepted by privileged internal API routes without rotating the existing
`INTERNAL_API_SECRET`; Verify, Security Audit, and Workers Builds passed
before merge as `18d80197be779619283e0b37e2952bac53819a07`, and the merged
Worker was deployed to `api.ecc.tools`.
- The May 20 live native-payments gate now passes: the vault-backed Wrangler
readback selected a ready Marketplace Pro target with fingerprint
`e953a74209fe`, both key families present, webhook evidence ready, 0 KV
blockers, and the official
`npm run billing:announcement-gate -- --select-ready-target` returned
`announcementGateReady: true`, 0 required actions, 0 blockers, and audit
summary 6 pass / 1 warn / 0 fail through the new operator bearer path.
- ECC-Tools PR #93 recorded that live billing evidence in the app launch
checklist and distribution roadmap as
`d3d62df83fa075660fa4530c3e0edc311a4355fe`; public native-payments copy is no
longer blocked by billing evidence, but publication timing remains behind the
final release, plugin, live URL, and owner-approval gates.
- Linear ITO-54 and the ECC Platform Roadmap now have the May 20 ECC-Tools
hosted observability update comments
`74dcc101-3be5-4173-be13-62b80d54f569` and
`348ea8f5-2a2d-46d9-a0fe-ed99653e7fe5`, after earlier PR #84/#85 comments
recorded remediation sync and hosted observability events. PR #88 is recorded
in Linear comments `291e2a4b-06e3-4672-a057-cdb141478161` and
`b2d35de0-ca49-44cb-982a-ddec229e7691`; AgentShield #94 is recorded in
ITO-49 comment `faed69dd-35f5-469d-acb5-ddde6a70d6a1` and project comment
`70187c1e-d481-4181-b418-09bd65d54b5e`; AgentShield #95 is recorded in
ITO-49 comment `371fc3e4-611f-4d20-a23f-67db1260b418`, ITO-57 comment
`bd06e252-15c1-4256-b667-caa3f64f5968`, and project comment
`22c2c388-2fd1-4dea-a939-6141f40c9a21`.
- Linear ITO-61 and the ECC Platform Roadmap now have the May 20 Marketplace
Pro release-gate comments `467d148a-712a-4777-aad9-95593e9f1739` and
`7642ee9c-3107-400c-a229-53e2895a8914`, recording ECC-Tools #89, ECC #2019,
the green post-merge CI run, and the remaining internal bearer-token gate.
The repo mirror now also records ECC-Tools #90 and #91 as the selected-target
announcement gate and billing gate env-file operator-path follow-up.
## 2026-05-19 Delta
- The public repo identity is now `affaan-m/ECC`; release, package, plugin,
workflow, and launch-copy surfaces should use that URL for current public
links.
- The late May 19 queue drain added the deterministic `release:approval-gate`
on ECC `main`, merged ECC-Tools billing-announcement redaction hardening, and
cleared the JARVIS Dependabot/deploy repair tail. The tracked platform audit
is now green with 0 open PRs, 0 open issues, and 0 discussion gaps across all
five tracked repos, but release/publication actions remain owner and live-URL
gated.
- The ECC 2.0 release story should lead with the product shape directly:
harness-native operator system, reusable skills/rules/hooks/MCP conventions,
`ecc2/` alpha control plane, Hermes as optional operator shell, and ECC Tools
Pro/Sponsors/consulting as the business surface.
- Copy should avoid presenting this as a repo rename or config-pack migration.
The release proof should show the system through install flow, cross-harness
demos, security evidence, hosted product evidence, and the video suite.
## Current Evidence
As of 2026-05-20:
As of 2026-05-13:
- GitHub queues are clean across `affaan-m/ECC`,
- GitHub queues are clean across `affaan-m/everything-claude-code`,
`affaan-m/agentshield`, `affaan-m/JARVIS`, `ECC-Tools/ECC-Tools`, and
`ECC-Tools/ECC-website`: the latest `platform-audit` sweep found 0 open PRs,
0 open issues, 0 discussion maintainer-touch gaps, 0 answerable Q&A missing
accepted answers, and 0 blocking dirty files. The current
`scripts/work-items.js list --json` output also reports `totalCount: 0`, so
there are no open or blocked local work items in the SQLite bridge.
- Owner-wide queue cleanup is also inside the requested budget:
`docs/releases/2.0.0-rc.1/owner-queue-cleanup-2026-05-18.md` records the
live `gh search` sweep that closed 24 stale dependency-bot PRs and 72 stale
legacy payments/0EM roadmap issues, then closed the 9 remaining stale,
generated, conflicting, or test/noise PRs and the 5 remaining legacy,
outreach, or placeholder issues. The broader `affaan-m` owner namespace is
now at 0 open PRs and 0 open issues by live `gh search`. Archived repos
touched during closure were restored to archived state.
- GitHub discussions are current across those tracked repos:
`affaan-m/ECC` has 60 total discussions and 0 without
maintainer touch after the May 19 #2003 AURA integration proposal was routed
as an external-adapter proposal, not core wallet/escrow coupling, and the
May 20 #2015 setup-location Q&A was answered and accepted; AgentShield,
JARVIS, ECC Tools, and the ECC Tools website have discussions disabled or 0
total discussions. `docs/architecture/discussion-response-playbook.md` now
supplies the ITO-59 response categories, public templates, security-escalation
path, and readback rules for future discussion batches.
- The current Linear roadmap contains 16 issue lanes (`ITO-44` through
`ITO-59`) and five milestones: Security and Access Baseline, ECC 2.0 Preview
and Publication, AgentShield Enterprise Iteration, ECC Tools Next-Level
Platform, and Legacy Audit and Salvage.
- Linear live sync is current for the May 19 PR #2002 merge and discussion
batch: the ECC platform project has the post-PR #2002 sync document
`ecc-may-19-post-pr-2002-sync-64cef8f668e0`, project comment
`a6411e3a-8c8e-4a58-adba-687e77d4c543`, and issue comments on ITO-44,
ITO-47, ITO-48, ITO-49, ITO-51, ITO-54, and ITO-56. ITO-47, ITO-48,
ITO-49, ITO-51, ITO-54, and ITO-56 were moved to In Progress because those
lanes now have current implementation/evidence and remaining gate/readback
work. ITO-57 still has the May 18 emergency supply-chain refresh comment
(`3fe5b2b7-c4fe-401c-a317-b40d72119cb3`). Linear project status updates are
disabled in this workspace, so project documents and comments are the
supported external status surface.
- The latest May 18 merge batch on `main` includes PR #1970 workflow-security
validator bypass fixes, PR #1971 metrics bridge cost-reporting and warning
de-dup fixes, PR #1972 `uncloud` skill activation structure, PR #1976
OpenAI/AstraFlow provider response guards, ECC-Tools Wrangler OAuth billing
readback mirror evidence, the `04d4d819` defensive-deny IOC scanner hardening
recheck, `7911af4a` release OIDC publishing-scope hardening, `97567a91`
release workflow line-ending normalization, and release evidence with a
refreshed operator dashboard.
- `docs/releases/2.0.0-rc.1/publication-evidence-2026-05-19.md` records the
current May 19 queue-zero state, canonical ECC identity merge, release video
suite gate, partner/sponsor/talk outreach pack, owner approval packet
(`owner-approval-packet-2026-05-19.md`), current preview-pack smoke digest
`eebb8a66c33e`, local 2568-test suite, PR #2001 merge and GitHub Actions run
`26102500291` success, PR #2002's owner-approval dashboard gate refresh and
GitHub Actions run `26103853507`, PR #2004's Linear readiness evidence sync
and GitHub Actions run `26105012698`, plus PR #2005's post-PR #2004
evidence refresh and GitHub Actions run `26106321921`, PR #2008's supply-chain
evidence gate fix and GitHub Actions run `26108473648`, post-PR #2006 main CI
run `26109953093`, and PR #2009's project-registry hygiene GitHub Actions run
`26111313938`, post-PR #2009 main CI run `26111946778`, post-PR #2011
GateGuard main CI run `26113695068`, and post-PR #2013 release-approval-gate
main CI run `26128749863`. The late May 19 sync target also includes
ECC-Tools PR #79 billing-announcement redaction hardening and JARVIS PR #15
/ PR #16 queue/deploy repair, with JARVIS main CI, CodeQL, and Deploy green
after the workflow repair. The Linear external project status surface now has
both the post-PR #2002 sync document and the late-pass document
`ecc-may-19-late-queue-zero-and-release-gate-sync-1c26f65e6b3f`, plus project
comment `d42bf0e2-7a8e-4934-9f3f-e281498ee805`. The supply-chain gate now
also records the `@types/node@25.7.0` pin and `brace-expansion` lock refresh
needed for current npm audit/signature verification.
- The May 20 ECC-Tools hosted-platform pass extends that evidence with PR #80
through PR #88, all merged after green GitHub Verify/Security Audit/Workers
Builds checks. Local validation for the final depth-plan observability slice
passed the focused hosted depth-plan route test, the full route suite
(89/89), typecheck, lint, full ECC-Tools Vitest suite (683/683), and
`git diff --check`. PR #88 additionally exposes authenticated hosted
observability readback at `/api/analysis/observability` for operator
dashboards and production smoke tests; its local verification passed
typecheck, lint, the full ECC-Tools Vitest suite (686/686), and
`git diff --check`.
- AgentShield PR #94 adds Zed and VS Code to the first-class adapter registry
after local verification with typecheck, lint, the focused core scanner/rule
tests, full `npm test` (1822 tests), `npm run build`, and `git diff --check`.
GitHub checks passed across GitGuardian, scan suite, self-scan,
self-scan examples, Node 18/20/22 CI, CodeRabbit, and Cubic after rerunning a
transient GitHub artifact-upload failure.
- AgentShield PR #95 resolves Dependabot #20 / `GHSA-jxxr-4gwj-5jf2` /
`CVE-2026-45149` by updating the vulnerable `brace-expansion` 5.x
transitive lockfile entries to `5.0.6`. Local validation passed
`npm audit --audit-level=moderate`, typecheck, lint, full `npm test`
(1822 tests), build, and whitespace checks; GitHub checks passed across
Verify Node 18/20/22, self-scan, self-scan examples, Test GitHub Action,
GitGuardian, CodeRabbit, and Cubic.
- `docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-20.md`
regenerates the ITO-44 prompt-to-artifact dashboard from live platform audit
evidence: PR queue, issue queue, discussion queue, local worktree gate,
dashboard generation, and supply-chain loop are current; the dashboard now
also tracks the `$1,728/mo` to `$10,000/mo` hypergrowth baseline, release
video-suite lane, partner/sponsor/talk outbound pack, and owner approval
packet; publication, plugin, billing, AgentShield, ECC Tools, Linear release
gate sync, and final outbound approval remain the next work.
- `docs/releases/2.0.0-rc.1/publication-evidence-2026-05-17.md` records the
May 17 queue-zero state, Japanese localization merge, Dependabot TypeScript
and Node type merges, post-merge ja-JP lint repair, Mini Shai-Hulud/TanStack
local protection recheck, npm audit/signature checks, current operator
dashboard, and GitHub CI success for `99dd6ac0`.
- `docs/releases/2.0.0-rc.1/publication-evidence-2026-05-16.md` records the
queue, discussion, Linear roadmap, ECC Tools access, Mini Shai-Hulud/TanStack
full-campaign follow-up, scheduled supply-chain watch coverage, no-lifecycle
CI install hardening, GitHub Actions cache purge, AgentShield #85
registry-signature verification, AgentShield #86 evidence-pack CI provenance,
AgentShield #87 plugin-cache runtime-confidence classification, AgentShield
#88 evidence-pack inspect/readback, AgentShield #89 evidence-pack fleet
routing, AgentShield #90 fleet review items, AgentShield #91
checksum-backed policy export, AgentShield #92 checksum-verified policy
promotion, ECC-Tools #75 billing-gate tightening,
ECC-Tools #76 AgentShield fleet-summary consumption, ECC-Tools #77 hosted
finding evidence paths, ECC-Tools #78 harness policy-route linking, PR #1947
supply-chain protection, and May 16 release-evidence
refresh.
- `npm run harness:audit -- --format json` reports 80/80 on current `main`.
`ECC-Tools/ECC-website`: the latest sweep found 0 open PRs and 0 open
issues across all five repos.
- GitHub discussions are also clean across those tracked repos:
the latest GraphQL sweep found 52 total trunk discussions with 0 open,
and 0 total/open discussions on AgentShield, JARVIS, ECC-Tools, and the
ECC-Tools website.
- The final open public GitHub issue, #1314, was closed as a non-actionable
external badge/listing notification with a courtesy comment.
- Linear issue creation for this project was re-tested after GitHub cleanup and
is still blocked by the workspace free issue limit. Seven roadmap-lane issue
creation attempts all returned the same limit error, so this repo mirror and
Linear project status updates remain the active tracking surfaces until the
workspace is upgraded or issue capacity is freed.
- `npm run harness:audit -- --format json` reports 70/70 on current `main`.
- `npm run observability:ready` reports 21/21 readiness on current `main`,
including the GitHub/Linear/handoff/roadmap progress-sync contract.
- GitHub CI run `26017368895` completed successfully for
`04d4d81938b20ac2bac1f0025145ab77d6a59f5f`, including Validate Components,
Coverage, Lint, Security Scan, and the full Node/package-manager matrix.
- Supply-Chain Watch run `26009825837` completed successfully for
`3b7e0ba30a027ffd3319c2f145c63076c296d80a`, including no-lifecycle install,
npm audit/signature verification, scanner fixtures, advisory-source
fixtures, IOC/advisory artifact generation, and workflow-security validation.
- PR #1846 merged as `797f283036904128bb1b348ae62019eb9f08cf39` and made
npm registry signature verification a durable workflow-security gate:
workflows that run `npm audit` now need `npm audit signatures`.
@@ -259,12 +41,6 @@ As of 2026-05-20:
`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.
@@ -293,24 +69,6 @@ As of 2026-05-20:
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
@@ -322,229 +80,6 @@ As of 2026-05-20:
and made `/ecc-tools followups sync-linear` track copy-ready PR drafts in
the Linear/project backlog when `open-pr-drafts` is not used, preserving
useful stale-PR salvage work without opening extra PR shells.
- ECC-Tools PR #55 merged as `5d8c112cce4794cfa089d5b0ea661ba87a178be1`
and added analysis-depth readiness to `/ecc-tools analyze` comments,
separating commit-history-only repos from evidence-backed and deep-ready repos
using CI/CD, security, harness, reference/eval, AI routing/cost-control, and
team handoff evidence.
- ECC-Tools PR #56 merged as `5b729c88641eafe80f65364bab3fc74d0270f57b`
and added the authenticated `/api/analysis/depth-plan` contract that maps
analysis-depth readiness into concrete hosted jobs for CI diagnostics,
security evidence review, harness compatibility, reference-set evaluation,
AI routing/cost review, and team backlog routing.
- ECC-Tools PR #57 merged as `4cc61112a4cc9feec7b07af09321f360e34af6a4`
and added the first executable hosted analysis job:
`/api/analysis/jobs/ci-diagnostics` now gates on CI/CD readiness, inspects
workflow/test-runner/failure-evidence artifacts, returns CI hardening
findings and next actions, and charges usage only after successful execution.
- ECC-Tools PR #58 merged as `ce09dd8d9b46f65c6b88dc4f48cfb6b6227ae0bf`
and added the second executable hosted analysis job:
`/api/analysis/jobs/security-evidence-review` now gates on security-evidence
readiness, inspects capped AgentShield evidence-pack, policy, baseline,
SBOM, SARIF, and security-scan artifacts, returns supply-chain evidence
findings and next actions, and charges usage only after successful execution.
- ECC-Tools PR #59 merged as `505b372dbd8f75f996d9e2ed079effd30cec5ba5`
and added the third executable hosted analysis job:
`/api/analysis/jobs/harness-compatibility-audit` now gates on harness-config
readiness, inspects capped Claude, Codex, OpenCode, MCP, plugin, and
cross-harness documentation artifacts, excludes local secret-bearing config
paths from fetches, returns portability findings and next actions, and
charges usage only after successful execution.
- ECC-Tools PR #60 merged as `b75e0a49ba5672b1ec9a2a4880ddcfa2d07dc557`
and added the fourth executable hosted analysis job:
`/api/analysis/jobs/reference-set-evaluation` now gates on reference-evidence
readiness, evaluates analyzer corpus, RAG/evaluator, PR salvage/review,
harness, security, and CI failure-mode evidence, excludes obvious
secret-bearing fixture paths from fetches, returns reference coverage
findings and next actions, and charges usage only after successful execution.
- ECC-Tools PR #61 merged as `7b01b67cae0b80774b311cb515b7eca0aa038c65`
and added the fifth executable hosted analysis job:
`/api/analysis/jobs/ai-routing-cost-review` now gates on AI routing/cost
readiness, evaluates model routing, token budget, usage-limit, rate-limit,
billing/entitlement, cost-regression, and cost-policy evidence, excludes
obvious secret-bearing paths from fetches, returns cost-control findings and
next actions, and charges usage only after successful execution.
- ECC-Tools PR #62 merged as `781d6733e56f7556edb43fb96bdfb00b1f0a3aa6`
and added the sixth executable hosted analysis job:
`/api/analysis/jobs/team-backlog-routing` now gates on team handoff/project
tracking readiness, evaluates roadmap, runbook, handoff, release-plan,
issue-template, ownership, project-tracker, backlog, and follow-up evidence,
excludes obvious secret-bearing paths from fetches, returns team-routing
findings and next actions, and charges usage only after successful execution.
- ECC-Tools PR #63 merged as `fb9e4c5ceb9ccde50da74c7a69c3fa4bd321fc07`
and made the hosted execution plan operator-visible on queued PR analysis:
the queue now publishes a non-blocking `ECC Tools / Hosted Depth Plan`
check-run on the PR head SHA with ready/blocked hosted executor commands
and next action text, while keeping check-run publication best-effort so
bundle generation and analysis comments are not blocked.
- ECC-Tools PR #64 merged as `72020ef94db94840812977ea7ac37e9344036668`
and added PR-facing hosted job dispatch controls:
`/ecc-tools analyze --job ...` comments now queue hosted jobs against the
PR head SHA, execute them through the existing hosted readiness/evidence
gates, post artifacts/findings/next actions back to the PR, and scope
idempotency keys by job id so hosted jobs do not collide with bundle
analysis.
- ECC-Tools PR #65 merged as `bacd4adf6a3a629e8d403865456d15f127baaf4e`
and added hosted job result history/check-run summaries:
queued hosted jobs now cache both the latest result and immutable run records
for completed or blocked runs, then publish a non-blocking per-job check-run
on the PR head SHA with artifacts, findings, readiness blockers, and next
actions.
- ECC-Tools PR #66 merged as `4e1db48252d068ea5dcf4308b0bc11b0dfe0c9ce`
and added a read-only hosted status command:
`/ecc-tools analyze --job status` now reads the #65 latest-result cache for
the current PR head and posts a compact completed/blocked/not-run table with
the next hosted job command, without queueing work or billing usage.
- ECC-Tools PR #67 merged as `f20e6bec2b0bf49e4cc36e08b7285c795973b73d`
and made the hosted depth-plan check-run status-aware:
queued PR analysis now reads the #65/#66 latest-result cache when publishing
`ECC Tools / Hosted Depth Plan`, includes the latest hosted run status in
the plan table, and recommends the next unrun ready job before reruns.
- ECC-Tools PR #68 merged as `2cde524b5ef8f34ab7bb1af973248fe4be4359f8`
and added deterministic hosted promotion readiness:
opened/synchronized PRs now publish a non-blocking
`ECC Tools / Hosted Promotion Readiness` check-run that compares changed
files against the checked-in evaluator/RAG corpus, warns on missing
hosted-job promotion evidence, and can be disabled with
`PR_HOSTED_PROMOTION_READINESS_CHECK_MODE=off`.
- ECC-Tools PR #69 merged as `d0112dac7cef807ae27def41f057682ef0772cce`
and extended hosted promotion readiness with deterministic output scoring:
the check now reads cached completed hosted job results for the current PR
head, scores their artifacts and findings against evaluator/RAG corpus
expectations, and treats matching hosted artifacts as promotion evidence
before reporting a gap.
- ECC-Tools PR #70 merged as `7001d805ac981fe220b4575159f469fbea9dbb76`
and added retrieval planning for hosted promotion:
the check now emits ranked retrieval candidates from cached hosted artifacts,
hosted findings, expected evidence paths, and changed source paths, plus a
model prompt seed that tells the later hosted judge not to promote from
changed paths alone.
- ECC-Tools PR #71 merged as `d41e59ff00fe1bd0b0c96386e56bc5269d7b9c15`
and added the first model-backed hosted promotion judge contract:
the check now emits a provider-neutral `hosted-promotion-judge.v1` request
contract and fails closed unless hosted retrieval evidence, entitlement,
remaining budget, and provider configuration are present. It still does not
make live model calls.
- ECC-Tools PR #72 merged as `973bc51e5436dd279ae5a890cce9811485eef0b5`
and executes the hosted promotion model judge behind explicit gates:
`PR_HOSTED_PROMOTION_MODEL_JUDGE_MODE=execute` now calls the configured
provider only after hosted retrieval evidence, entitlement, budget, provider,
and executor gates pass; the check remains non-blocking, strict-JSON-only,
and rejects uncited or non-hosted model output without echoing raw responses.
- ECC-Tools commit `05d4e8296e37ba72e471beaa23ea4c81eb2aa31f`
adds operator-readable audit traces to hosted promotion model judging:
check-runs now render a deterministic request fingerprint and
allowed-citation count alongside the accepted decision, without exposing raw
provider output.
- ECC-Tools PR #73 merged as `7d0538c9354e18adbfc72ef00d858949a817fa48`
and added a fail-closed native-payments announcement gate to
`/api/billing/readiness`: public payment claims now require
`announcementGate.ready === true` from a Marketplace-managed test account
before launch copy can move past release review.
- ECC-Tools commit `91a441b92342b842832ac28b018ee46f0c4a906f`
adds `npm run billing:announcement-gate -- --preflight` so operators can
verify the Marketplace test account, internal API token presence, and
billing-readiness endpoint before making the privileged readback call.
- ECC-Tools commit `eb6941290b2fa70db01a51084e9e79a160238468`
recorded the first live production readback state: Cloudflare Worker secret
names include `INTERNAL_API_SECRET`, but no Marketplace-managed account could
pass the announcement gate yet.
- ECC-Tools commit `95d0bec69dbcf364ed084e983a40d0a94d443d16`
adds repeatable aggregate production KV readback with
`npm run billing:kv-readback`: the latest API-authenticated run found 253
`account-billing:*` records and 253 `billing-state:*` records, but 0
Marketplace-managed Pro `billing-state:*` records, so native-payments copy
remains blocked until `--require-ready` and the official internal
announcement gate pass.
- ECC-Tools commit `285967807ea7b5eb3146bc984fb2229db67d4290`
requires GitHub Marketplace webhook provenance on Pro billing-state records
before native-payments announcement readiness can pass. The CI run
`26013559229` succeeded for the pushed head.
- ECC-Tools commit `42653f9140c232961280d961ed76a6142433cfa1`
adds `npm run billing:kv-readback -- --wrangler` so operators can run the
aggregate production KV readback through an authenticated Wrangler OAuth
session instead of requiring a separate Cloudflare API token/global key. CI
run `26016223013` succeeded, and the latest live readback found 253
`account-billing:*` records and 253 `billing-state:*` records with 194
marketplace/free states, 59 Stripe/pro states, 0 Marketplace Pro states, 0
ready-like Marketplace Pro states, and 0 parse failures. Native-payments
copy remains blocked until a real Marketplace-managed Pro webhook creates
billing-state provenance and `--require-ready` plus the official internal
announcement gate pass.
- ECC-Tools commit `632e059e51b6e1297ba118807c8b5b2adbac74ce`
adds target account billing readback with `npm run billing:kv-readback -- --account <github-login> --require-ready`.
The report redacts the account login and raw KV keys, emits only a stable
fingerprint plus sanitized readiness booleans, and now requires both
`account-billing:<login>` and `billing-state:<login>` before a target
Marketplace Pro test account can pass the native-payments announcement
readback gate. CI run `26018941515` succeeded. The 2026-05-18 live recheck
split out Linear ITO-61 for the target-account blocker.
- ECC-Tools commit `d5f60db` adds sanitized Marketplace-source provenance
counts to `npm run billing:kv-readback`, including
`marketplaceSourceRecords`, `marketplaceSourceWithWebhookEvidence`,
`marketplaceSourceWithoutWebhookEvidence`, `byMarketplacePlanName`, and
`byMarketplaceEventAction`. The 2026-05-18 live Wrangler OAuth readback now
works and found 256 account-billing records, 256 billing-state records, 197
Marketplace-source records, 59 Stripe-source records, 53 Pro records, 0
Marketplace Pro records, 4 Marketplace webhook-provenance records, all
`Open Source` purchases, and 193 Marketplace-source records without webhook
provenance. Native-payments copy remains blocked by Linear ITO-61 until a
real Marketplace-managed Pro webhook creates target account provenance and
`billing:kv-readback -- --wrangler --wrangler-bin ./node_modules/.bin/wrangler --account <github-login> --require-ready`
plus the official internal announcement gate pass.
- ECC-Tools commit `13cd3fc` normalizes billing-state key casing so
Marketplace webhook writes and announcement readbacks agree on GitHub login
case; current-head CI `26037611421` passed. The code-side readback hardening
remains green, but it does not create live Marketplace Pro state.
- ECC-Tools commit `69ca535` surfaces hosted team-learning feedback controls:
harness compatibility and team-backlog routing now show retention days,
deletion route/SLA, and opt-out route before adaptive recommendations are
routed into team-owned queues. Linear ITO-52 is Done with CI `26054455434`.
- ECC-Tools commit `e56fc1a` updates the lockfile for
`brace-expansion@5.0.6` and fixed Dependabot alert 44 for CVE-2026-45149;
GitHub API reported `state: fixed` at `2026-05-18T19:10:15Z` and current-head
CI `26054671308` passed.
- ECC-Tools PR #89 merged as `512bca6b99cdaa67058a6aa9a4e7e7f0b1d9873a`
and adds
`npm run billing:kv-readback -- --select-ready-target --require-ready` so
operators can prove a ready Marketplace Pro account without passing or
printing the login. The 2026-05-20 production Wrangler OAuth readback found
ready-like Marketplace Pro records with webhook provenance and 0 parse
failures. The selected target report printed only a stable fingerprint,
confirmed both key families, `marketplace` source, `pro` tier, seat ready,
webhook evidence ready, automatic overage disabled, and 0 blockers. The old
"no Marketplace-managed Pro target billing-state" blocker is cleared. Linear
comment `f14ed2fe-a219-470c-8119-63429e197027` records the redacted readback
counts.
- ECC-Tools PR #90 merged as
`16a5bb33ee5ce7c31d2ad8d041e5afac03308f05` after Verify, Security Audit,
and Workers Builds passed. It adds the selected-target official announcement
gate through `/api/billing/readiness?selectReadyTarget=1` and
`npm run billing:announcement-gate -- --select-ready-target`, so operators no
longer need to pass or print a raw GitHub login for the official
native-payments gate. The 2026-05-20 safe production preflight requested a
selected ready target and narrowed the remaining blocker to the missing
local/internal `INTERNAL_API_SECRET` bearer token. Native-payments copy remains
blocked until that token path is available and the live
`billing:announcement-gate -- --select-ready-target` call passes.
- ECC-Tools PR #91 merged as `72119a1acc6f5a0cd3bb5d90afd6e87fd1fefd05`
after Verify, Security Audit, and Workers Builds passed. It adds the billing
gate env-file operator path with `--env-file` support for the announcement
gate and KV readback scripts, plus sentinel tests proving loaded secrets and
account logins are not printed.
- ECC-Tools PR #92 merged as `18d80197be779619283e0b37e2952bac53819a07` after
Verify, Security Audit, and Workers Builds passed. It adds the optional
`INTERNAL_OPERATOR_API_SECRET` recovery bearer so operators can run privileged
internal readiness gates without replacing the primary `INTERNAL_API_SECRET`;
the merged Worker was deployed to `api.ecc.tools` before the live gate run.
- ECC-Tools PR #93 merged as `d3d62df83fa075660fa4530c3e0edc311a4355fe` after
Verify, Security Audit, and Workers Builds passed. It records the live
2026-05-20 billing evidence in the app launch checklist and roadmap:
selected ready Marketplace Pro target, fingerprint `e953a74209fe`, 0 KV
blockers, preflight ready, `announcementGateReady: true`, 0 required actions,
0 blockers, and audit summary 6 pass / 1 warn / 0 fail. Native-payments copy
is no longer blocked by billing evidence, but final announcement timing still
requires the release, plugin, live URL, and owner-approval gates.
- Handoff `ecc-supply-chain-audit-20260513-0645.md` under
`~/.cluster-swarm/handoffs/`
records the May 13 supply-chain sweep: no active lockfile/manifest hit for
@@ -604,8 +139,8 @@ As of 2026-05-20:
and classifies `legacy-command-shims/` as an opt-in archive/no-action
surface.
- `docs/stale-pr-salvage-ledger.md` records stale PR salvage outcomes,
skipped PRs, superseded work, and the remaining #1687, #1609, #1563, #1564,
and #1565 translator/manual review tail now attached to Linear ITO-55.
skipped PRs, superseded work, and the remaining #1687 translator/manual
review tail.
- AgentShield PR #53 reduced two context-rule false positives and closed the
remaining AgentShield issues.
- AgentShield PR #55 added GitHub Action organization-policy enforcement with
@@ -728,185 +263,6 @@ As of 2026-05-20:
artifact contract so canonical bundle files now satisfy the taxonomy and
generated follow-up PRs point maintainers at
`agentshield scan --evidence-pack <dir>`.
- ECC-Tools PR #55 added the first hosted/deeper-analysis readiness signal:
analysis comments now classify a repo as commit-history-only,
evidence-backed, or deep-ready before routing work into CI, AgentShield,
harness, reference-set, RAG/evaluator, AI-routing, cost-control, and
Linear/project-tracking lanes.
- ECC-Tools PR #56 turned that signal into a hosted execution-plan contract:
`/api/analysis/depth-plan` returns ready/blocked jobs and next action text
without charging analysis usage or creating bundle PRs.
- ECC-Tools PR #57 implemented the first job-specific hosted executor:
`/api/analysis/jobs/ci-diagnostics` reuses the depth-readiness gate, internal
API auth, installation ownership, repo-access billing checks, capped workflow
file reads, and usage accounting to return concrete CI hardening findings.
- ECC-Tools PR #58 implemented the second job-specific hosted executor:
`/api/analysis/jobs/security-evidence-review` applies the same hosted gates
to AgentShield evidence-pack, policy, baseline, SBOM, SARIF, and security
scanner artifacts.
- ECC-Tools PR #59 implemented the third job-specific hosted executor:
`/api/analysis/jobs/harness-compatibility-audit` applies the same hosted
gates to Claude, Codex, OpenCode, MCP, plugin, and cross-harness evidence
while avoiding local secret-bearing harness config fetches.
- ECC-Tools PR #60 implemented the fourth job-specific hosted executor:
`/api/analysis/jobs/reference-set-evaluation` applies the same hosted gates
to analyzer corpus, RAG/evaluator, PR salvage, harness, security, and CI
failure-mode reference evidence while avoiding obvious secret-bearing fixture
fetches.
- ECC-Tools PR #61 implemented the fifth job-specific hosted executor:
`/api/analysis/jobs/ai-routing-cost-review` applies the same hosted gates to
model-routing, token-budget, usage-limit, rate-limit, billing/entitlement,
cost-regression, and cost-policy evidence while avoiding obvious
secret-bearing path fetches.
- ECC-Tools PR #62 implemented the sixth job-specific hosted executor:
`/api/analysis/jobs/team-backlog-routing` applies the same hosted gates to
roadmap, runbook, handoff, release-plan, issue-template, ownership,
project-tracker, backlog, and follow-up evidence while avoiding obvious
secret-bearing path fetches.
- ECC-Tools PR #63 publishes the hosted depth-plan check-run after queued PR
analysis completes, making the six hosted executor commands visible on the
PR head SHA without turning the check into a merge blocker.
- ECC-Tools PR #64 wires those commands into the queue: maintainers can comment
`/ecc-tools analyze --job ci-diagnostics`, `security-evidence`,
`harness-compatibility`, `reference-set-evaluation`, `ai-routing-cost`, or
`team-backlog` on a PR and receive hosted job results in a PR comment.
- ECC-Tools PR #65 persists completed and blocked hosted job results to the
analysis cache for 30 days and publishes non-blocking `ECC Tools / Hosted
Job: ...` check-runs so maintainers can scan hosted outcomes from the PR
checks surface instead of rereading older comments.
- ECC-Tools PR #66 exposes the cached results from PR comments with
`/ecc-tools analyze --job status`, summarizing completed, blocked, and
not-yet-run hosted jobs for the PR head and recommending the next hosted job
command.
- ECC-Tools PR #67 feeds those cached results back into the hosted depth-plan
check-run so queued analysis recommends the next unrun ready hosted job from
cache state instead of repeating the static readiness order.
- ECC-Tools PR #68 adds the first evaluator-backed hosted promotion gate:
opened/synchronized PRs get a non-blocking Hosted Promotion Readiness
check-run that turns the evaluator/RAG corpus into warnings when changed
files match fixture scenarios without their expected evidence artifacts.
- 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-Tools PR #78 merged as `0d4eb949aa56f56da88e6654273a22ffb95983a1`
and links AgentShield fleet routes into hosted harness compatibility review:
fleet summaries are collected as harness evidence, target paths are mapped to
Claude, Codex, OpenCode, MCP, plugin, and cross-harness owners, and routed
findings carry source evidence paths for operator review.
- ECC-Tools PR #79 merged as `67ee247ae1b7b50ecc1261ed5d62d65cc8390da8`
and redacts billing announcement gate account output: the billing preflight
and live readback now print stable account fingerprints and sanitized
readiness booleans instead of raw account logins or KV key names.
- ECC-Tools PR #80 merged as `4efc8cc858022f84c844690f3298633b081c4398`
and requires runtime receipt failure reasons before harness runtime receipts
can count as hosted observability evidence.
- ECC-Tools PR #81 merged as `1fbf635f492284f75ba7166c029c39eb8cc15794`
and preserves AgentShield fleet approval IDs through hosted security review
so policy-promotion follow-ups keep owner-review identity stable.
- ECC-Tools PR #82 merged as `7a7b4d096a176ae80b3a2076c09d45601e36013a`
and renders AgentShield fleet approval IDs in hosted comments and check-runs,
giving operators a direct bridge from hosted security review back to
AgentShield policy-promotion review items.
- ECC-Tools PR #83 merged as `b6b107f33961bef18a85fb619f3a976eb5d752dd`
and makes Linear follow-up sync reuse deterministic external IDs before title
fallback, preventing duplicate deferred backlog issues during repeated
`/ecc-tools followups sync-linear` runs.
- ECC-Tools PR #84 merged as `73bac7058071c55cb30c6b8ac6db779b3660c02c`
and syncs hosted AgentShield remediation items to Linear when the workspace
token/team are configured; hosted result comments now include created/reused
Linear remediation links.
- ECC-Tools PR #85 merged as `1637e0f2bfa0a889387f2c20675680ccc5528123`
and emits hosted job observability events for queued, completed, blocked,
failed, and budget-blocked states into `ANALYSIS_CACHE`, including budget
snapshots and result counts.
- ECC-Tools PR #86 merged as `5a9e94d3ff860307c3e7fd9fd065f0de2bd633dd`
and reads recent hosted observability events in
`/ecc-tools analyze --job status`, so status comments show budget snapshots,
blocked results, and budget-blocked outcomes alongside latest job runs.
- ECC-Tools PR #87 merged as `508fbc02b63cf1fcb5af2f3624608fa66e53b5d4`
and adds the same hosted observability readback to hosted depth-plan
check-runs, keeping the PR check surface aligned with status comments.
- ECC-Tools PR #88 merged as `c836ac3fb24ed7e2ae38cd61e41c9651ac9c00f8`
and exposes authenticated hosted observability API readback at
`/api/analysis/observability`, summarizing recent hosted events by event type
and job while skipping malformed stale KV records. The deployment runbook now
includes the production smoke command for operator/dashboard readback.
- AgentShield PR #90 merged as `6d1c57c92000541d65a3b6bc366f0322d7d0dacc`
and adds durable fleet `reviewItems`: `agentshield evidence-pack fleet --json`
now returns owner-ready review items with route, severity, repository/target
context, source evidence paths, reason, and recommendation; the text CLI
prints the same routed follow-up list for operators.
- AgentShield PR #91 merged as `73e1e3586dc4513a462e39c9799f75eea104e110`
and adds durable policy pack export: `agentshield policy export` writes one
JSON policy per selected pack plus a checksum-backed `manifest.json`, with
pack selection, owners, name prefixes, and JSON output for branch-protection
review or downstream policy promotion.
- AgentShield PR #92 merged as `e7e259dc6212b63a8e03a253ca6b8c1e3c2abff7`
and adds the protected promotion gate for those bundles:
`agentshield policy promote` verifies the export manifest and selected
policy SHA-256 digest, rejects tampered policy JSON, requires explicit pack
selection for multi-pack manifests, and supports dry-run JSON review before
writing the active `.agentshield/policy.json`.
- AgentShield PR #94 merged as `4caee27acfadb50a4cd024e738b5c3cbd4b0bb03`
and adds editor-native adapter coverage for Zed and VS Code. Zed
`.zed/settings.json`, `.zed/tasks.json`, and `.zed` hook-code files are now
scan inputs, adapter reports expose Zed MCP/tool-permission/task metadata and
VS Code workspace/task/extension metadata, and `.zed/setup.mjs` is covered by
the AI-tool persistence IOC rule.
- AgentShield PR #95 merged as `25d91f0002214c408da4ceaac7def20bad40ca10`
and clears the `brace-expansion` Dependabot alert. The lockfile now resolves
the vulnerable transitive 5.x copies to `5.0.6`; the remaining 1.x copy is
outside the advisory range.
- AgentShield main commit `87aec47fb55d04ea28d494852d4f664c268c5601`
extends policy promotion with durable `reviewItems` for manifest digest
evidence, policy-owner approval, protected rollout PR handoff, and runtime
smoke testing. Local validation passed `npm run typecheck`, `npm run lint`,
and `npm test`; GitHub Actions run `25985170621` completed successfully
across Node 18, 20, and 22 plus self-scan examples, and the sibling
AgentShield Self-Scan/Test GitHub Action runs also completed successfully.
- AgentShield main commit `28d08c7f9961eaa54804b26e6352d23b64ae2776`
adds package-manager hardening drift detection for `.npmrc`, `.pnpmrc`,
`.yarnrc`, `.yarnrc.yml`, `pnpm-workspace.yaml`, and
`pnpm-workspace.yml`, including plaintext registry credential detection,
explicit lifecycle-script enablement, and missing or weak release-age
cooldown findings. Local validation passed focused rule/scanner tests,
`npm run typecheck`, `npm run lint`, `npm run build`, full
`npm test -- --run`, and `git diff --check`; GitHub Actions run
`25986170958` completed successfully, and the sibling AgentShield Self-Scan
and Test GitHub Action runs passed.
- AgentShield main commit `659f569190f85f6f0808353e096d66c0a6d7817e`
updates all workflow action pins to current SHA-pinned
`actions/checkout@v6.0.2` and `actions/setup-node@v6.4.0`; GitHub Actions
run `25986221319` completed successfully and the prior Node 20 action-runtime
deprecation annotation was gone from the final CI watch output.
- AgentShield main commit `ee585cd` corrects package-manager hardening
guidance after local verification showed npm `10.9.4` rejects
`min-release-age`: npm configs are now scanned for lifecycle/token drift and
unsupported release-age keys, while enforceable cooldown findings stay on
pnpm `minimumReleaseAge` / `minimum-release-age` and Yarn
`npmMinimalAgeGate`. Local validation passed package-manager/scanner tests,
`npm run typecheck`, `npm run lint`, `npm run build`, and
`git diff --check`; GitHub Actions run `25986719058`, Test GitHub Action run
`25986719054`, and AgentShield Self-Scan run `25986719066` completed
successfully.
- AgentShield main commit `1124535345d7040242ecd3803f65bcd4dcaf6ec2`
exposes package-manager hardening through the GitHub Action so CI/hosted
consumers can route registry credential, lifecycle-script, and release-age
gate drift separately from generic finding counts. Local validation passed
focused action tests, `npm run typecheck`, `npm run lint`, `npm run build`,
full `npm test`, and `git diff --check`; GitHub Actions CI run
`25994354007`, Test GitHub Action run `25994354011`, and AgentShield
Self-Scan run `25994354026` completed successfully.
- 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.
@@ -932,7 +288,7 @@ As of 2026-05-20:
- Keep public PRs and issues below 20, with zero as the preferred release-lane
target.
- Maintain 80/80 harness audit and 21/21 observability readiness after every
- Maintain 70/70 harness audit and 21/21 observability readiness after every
GA-readiness batch.
- Do not publish release or social announcements until the GitHub release,
npm/package state, billing state, and plugin submission surfaces are verified
@@ -940,9 +296,7 @@ As of 2026-05-20:
- Do not treat closed stale PRs as discarded. Pair each cleanup batch with a
salvage pass: inspect the closed diffs, port useful compatible work on
maintainer-owned branches, and credit the source PR.
- Use Linear project documents/comments for project-level updates because
project status updates are disabled in this workspace; create or update
issues when a lane needs a durable execution owner.
- Do not create new Linear issues until the active issue limit is cleared.
## Prompt-To-Artifact Execution Checklist
@@ -951,23 +305,23 @@ is not complete unless the evidence column exists and has been freshly verified.
| Prompt requirement | Required artifact or gate | Current evidence | Status |
| --- | --- | --- | --- |
| Keep public PRs below 20 | Repo-family PR recheck | 0 open PRs across `ECC`, AgentShield, JARVIS, `ECC-Tools/ECC-Tools`, and `ECC-Tools/ECC-website` on the late 2026-05-19 platform audit after merging ECC PR #2013, ECC-Tools PR #79, JARVIS PR #15, and JARVIS PR #16 | Complete |
| Keep public issues below 20 | Repo-family issue recheck | 0 open issues across `ECC`, AgentShield, JARVIS, `ECC-Tools/ECC-Tools`, and `ECC-Tools/ECC-website` on 2026-05-19 after the live platform audit refresh | Complete |
| Manage repository discussions | Repo-family discussion recheck plus response playbook | Platform audit reports 0 discussion maintainer-touch gaps and 0 answerable Q&A missing accepted answers; trunk has 59 total discussions after #2003 was routed with a maintainer response; `docs/architecture/discussion-response-playbook.md` distinguishes support, maintainer coordination, stale/concluded, release, informational, and security-sensitive response paths | Complete |
| Manage PR discussions | PR review/comment closure plus merge/close state | ECC #1990-#2013 merged through the harness audit, canonical identity, release video suite, growth outreach, evidence refresh, visual QA, suite-count, owner-approval packet, owner-approval dashboard gate, Linear readiness evidence, supply-chain evidence gate, per-project Claude Code adapter, continuous-learning project-registry hygiene, GateGuard quoted git introspection, and deterministic release-approval gate batch; ECC-Tools #79 and JARVIS #15/#16 also merged; no open tracked PRs remain | Complete |
| Salvage useful stale work | `docs/stale-pr-salvage-ledger.md` plus `docs/legacy-artifact-inventory.md` | Ledger records salvaged, superseded, skipped, and manual-review tails; #1815-#1818 added cost tracking, skill scout, frontend design guidance, code-reviewer false-positive guardrails, and the May 12 gap pass; #1687, #1609, #1563, #1564, and #1565 localization tails are attached to Linear ITO-55 for language-owner review and no automatic import remains release-blocking | Complete; repeat legacy scan before release |
| ECC 2.0 preview pack ready | Release docs, quickstart, publication readiness, release notes | `docs/releases/2.0.0-rc.1/` and readiness docs are in-tree; May 19/20 evidence records queue-zero state, canonical ECC identity, release video suite, growth outreach pack, owner approval packet, local 2568-test suite, PR #2001 merge and GitHub Actions run `26102500291`, PR #2002 owner-approval dashboard gate refresh and GitHub Actions run `26103853507`, PR #2004 Linear readiness evidence sync and GitHub Actions run `26105012698`, PR #2008 supply-chain evidence gate CI run `26108473648`, post-PR #2006 main CI run `26109953093`, PR #2009 project-registry hygiene GitHub Actions run `26111313938`, post-PR #2009 main CI run `26111946778`, post-PR #2011 GateGuard main CI run `26113695068`, post-PR #2013 release-approval main CI run `26128749863`, post-PR #2019 main CI run `26135974576`, post-PR #2020 main CI run `26136949698`, ECC-Tools #91 main CI run `26137280847`, May 20 operator dashboard, `owner-approval-packet-2026-05-19.md`, `release-approval-gate.js`, and preview-pack smoke digest `eebb8a66c33e` | Needs final release approval |
| Keep public PRs below 20 | Repo-family PR recheck | 0 open PRs across `everything-claude-code`, AgentShield, JARVIS, `ECC-Tools/ECC-Tools`, and `ECC-Tools/ECC-website` on 2026-05-13 after merging ECC #1860, AgentShield #78, JARVIS #13, and ECC-Tools #53 | Complete |
| Keep public issues below 20 | Repo-family issue recheck | 0 open issues across `everything-claude-code`, AgentShield, JARVIS, `ECC-Tools/ECC-Tools`, and `ECC-Tools/ECC-website` on 2026-05-13 | Complete |
| Manage repository discussions | Repo-family discussion recheck | GraphQL sweep returned 52 total trunk discussions with 0 open; AgentShield, JARVIS, ECC-Tools, and ECC-Tools website returned 0 total/open discussions | Complete |
| Manage PR discussions | PR review/comment closure plus merge/close state | ECC #1860, AgentShield #78, JARVIS #13, and ECC-Tools #53/#54 merged after current-head CI/builds; no open tracked PRs remain | Complete |
| Salvage useful stale work | `docs/stale-pr-salvage-ledger.md` | Ledger records salvaged, superseded, skipped, and manual-review tails; #1815-#1818 added cost tracking, skill scout, frontend design guidance, code-reviewer false-positive guardrails, and the May 12 gap pass | Complete except translation/manual review tail |
| ECC 2.0 preview pack ready | Release docs, quickstart, publication readiness, release notes | `docs/releases/2.0.0-rc.1/` and readiness docs are in-tree; May 13 evidence refresh records harness, adapter, observability, Node, lint, release-surface, npm publish-surface, and Rust checks | Needs final clean-checkout release approval |
| Hermes specialized skills included safely | Hermes setup/import docs and sanitized skill surface | Hermes setup and import playbook are public; secrets stay local | Needs final release review |
| Naming and rename readiness | Naming matrix across package/plugin/docs/social surfaces | `docs/releases/2.0.0-rc.1/naming-and-publication-matrix.md` records current package, repo, Claude plugin, Codex plugin, OpenCode, and npm availability evidence | Complete for rc.1; post-rc rename remains future work |
| Claude and Codex plugin publication | Contact/submission path with required artifacts and status | Publication readiness, naming matrix, and May 12 dry-run evidence document plugin validation, clean-checkout Claude tag/install smoke, and Codex marketplace CLI shape | Needs explicit approval for real tag/push and marketplace submission |
| Articles, tweets, and announcements | X thread, LinkedIn copy, GitHub release copy, push checklist, partner/sponsor/talk pack | Draft launch collateral and approval-gated outreach copy exist under rc.1 release docs | Needs URL-backed refresh and human approval before posting or sending |
| 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, editor-native Zed/VS Code adapter coverage, Dependabot alert closure, enterprise research roadmap, supply-chain hardened release path, CI-safe baseline fingerprints, corpus accuracy recommendations, remediation workflow phases, env proxy hijack corpus coverage, Mini Shai-Hulud full-campaign package IOCs, CI-provenance evidence packs, plugin-cache runtime-confidence triage, evidence-pack consumer readback, fleet-level evidence-pack routing, fleet review items, fleet review ticket payloads, checksum-backed policy export, checksum-verified policy promotion, policy promotion review items, package-manager hardening drift detection, npm age-gate guidance correction, workflow action-runtime pin refresh, package-manager hardening Action outputs, policy-promotion Action outputs, ECC-Tools hosted consumption of promotion Action outputs, ECC-Tools operator-visible promotion output values, and ECC-Tools hosted promotion judge audit traces | PRs #53, #55-#64, #67-#69, #78-#92, #94, and #95 landed with test evidence, ECC-Tools #76 consumes the fleet-summary output in hosted security review, #77 surfaces source evidence paths in hosted finding output, and #78 links fleet routes to harness owner review; AgentShield #91 adds `agentshield policy export` bundles for branch-protection review and downstream promotion; AgentShield #92 adds `agentshield policy promote` with digest verification, tamper rejection, explicit pack selection, dry-run review, and JSON output before writing active policy; AgentShield #94 adds Zed/VS Code adapter detection, `.zed/settings.json` and `.zed/tasks.json` scan discovery, and `.zed/setup.mjs` AI-tool persistence IOC coverage; AgentShield #95 clears the `brace-expansion` Dependabot alert with a patched lockfile and 0 open Dependabot alerts after merge; AgentShield commit `87aec47` adds `reviewItems` for digest evidence, owner review, protected rollout PR handoff, and runtime smoke testing with green local and remote CI; AgentShield commit `28d08c7` adds package-manager hardening drift detection for plaintext registry credentials, lifecycle-script enablement, and weak pnpm/Yarn release-age cooldowns with green local and remote CI; AgentShield commit `659f569` refreshes all workflow action runtime pins to SHA-pinned checkout v6.0.2 and setup-node v6.4.0 with green remote CI and no remaining action-runtime deprecation annotation; AgentShield commit `ee585cd` corrects npm release-age guidance by flagging unsupported npm age keys and keeping enforceable cooldown findings on pnpm/Yarn with green local and remote CI; AgentShield commit `1124535` exposes package-manager hardening status/count outputs and a redacted job-summary section for registry credentials, lifecycle scripts, and release-age gates with green local and remote CI; AgentShield commit `1593925` exposes policy-promotion status/count/digest outputs plus job-summary review items for owner approval, protected rollout, and runtime smoke, and marks runtime smoke verified when the same Action job scans with the promoted policy; AgentShield commit `840952a` adds Linear/operator-ready fleet review ticket payloads and expands current Mini Shai-Hulud IOC breadcrumbs with green local and remote CI; ECC-Tools commit `8658951` routes those policy-promotion Action outputs into hosted security review findings and Hosted Promotion Readiness scoring; ECC-Tools commit `16c537f` renders policy-promotion status, pack, review item count, action-required count, and digest in hosted security job comments/check-runs; ECC-Tools commit `05d4e82` renders hosted promotion judge request fingerprints and allowed-citation counts without raw provider output; native PDF export deferred in favor of self-contained HTML plus print-to-PDF until explicit enterprise demand appears; `docs/architecture/agentshield-enterprise-research-roadmap.md` now has baseline drift, evidence-pack bundle, redaction, adapter-registry, supply-chain hardening, hashed baseline fingerprints, corpus accuracy recommendation, remediation workflow, env proxy hijack corpus, Mini Shai-Hulud full-campaign package-table, `ci-context.json` provenance, `plugin-cache` confidence, `evidence-pack inspect` readback, `evidence-pack fleet` routing, fleet `reviewItems`, fleet review ticket payloads, policy export, policy promotion, policy promotion `reviewItems`, package-manager hardening Action outputs, policy-promotion Action outputs, hosted consumption of promotion Action outputs, operator-visible promotion output values, hosted promotion judge audit traces, editor-native adapter coverage, and Dependabot closure landed | Next workflow automation should deepen live operator approval/readback after Marketplace/payment gates |
| ECC Tools next-level app | Billing audit, PR checks, deep analyzer, sync backlog, evaluator/RAG corpus, hosted promotion judge audit trace, native-payments readback, ready Marketplace Pro target selection, selected-target announcement gate, billing gate env-file operator path, hosted observability, AgentShield fleet-summary hosted routing, hosted finding evidence paths, harness-route policy linking, policy-promotion Action-output hosted telemetry, and operator-visible promotion output values | PRs #26-#43 plus #53-#93 landed with test evidence across hosted analysis, hosted promotion readiness, model-judge execution, native-payments announcement gating, AgentShield evidence consumption, hosted remediation/Linear sync, hosted observability readback, ready Marketplace Pro target selection, selected-target official announcement gating, and env-file operator loading; ECC-Tools #89 merged as `512bca6` after Verify, Security Audit, and Workers Builds passed, and the 2026-05-20 production Wrangler OAuth readback found ready-like Marketplace Pro records with webhook provenance, selected a target with both key families, and reported 0 blockers without printing the login; ECC-Tools #90 merged as `16a5bb3` after Verify, Security Audit, and Workers Builds passed, and production preflight now requests `/api/billing/readiness?selectReadyTarget=1` without a raw login; ECC-Tools #91 merged as `72119a1` with `--env-file` support for ignored local billing credentials and sentinel no-secret/no-login output tests; ECC-Tools #92 merged as `18d8019`, deployed the non-breaking `INTERNAL_OPERATOR_API_SECRET` path to `api.ecc.tools`, and the 2026-05-20 live selected-target gate returned `announcementGateReady: true` with 0 required actions and 0 blockers; ECC-Tools #93 merged as `d3d62df` to record the live billing evidence in the app launch checklist and roadmap | Repeat KV readback and selected-target announcement gate immediately before launch; keep native-payments copy behind final release, plugin, live URL, and owner-approval gates |
| 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 | PRs #53, #55-#64, #67-#69, and #78-#82 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, and env proxy hijack corpus slices landed | Next hosted evidence-pack workflow depth |
| ECC Tools next-level app | Billing audit, PR checks, deep analyzer, sync backlog, evaluator/RAG corpus | PRs #26-#43 plus #53/#54 landed with test evidence, including AgentShield evidence-pack gap routing, canonical bundle recognition, supply-chain signature gates, and PR draft follow-up Linear tracking | Needs hosted/deeper analysis follow-up |
| 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 document/comments plus repo mirror | Repo mirror exists and issue creation works again; the May 19 sync adds post-PR #2002 document `ecc-may-19-post-pr-2002-sync-64cef8f668e0`, project comment `a6411e3a-8c8e-4a58-adba-687e77d4c543`, ITO-44/47/48/49/51/54/56 issue comments, and In Progress state for ITO-47, ITO-48, ITO-49, ITO-51, ITO-54, and ITO-56; the late-pass batch adds document `ecc-may-19-late-queue-zero-and-release-gate-sync-1c26f65e6b3f`, project comment `d42bf0e2-7a8e-4934-9f3f-e281498ee805`, and ITO-44/50/54/56/61 comments for PR #2013, ECC-Tools #79, and JARVIS #15/#16 because project status updates are disabled in the workspace | Needs recurring document/comment updates after each significant merge batch |
| 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 | Local corpus complete; hosted integration remains future |
| 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 13 sync adds ECC #1860, AgentShield #78/#79, JARVIS #13, ECC-Tools #53/#54, resolved queue/discussion counts, and Linear project status updates `59f630eb`/`c7ea6daf` | Needs recurring status updates after each 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 documents/comments plus issue comments for lane updates | 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; May 18 and May 19 live connector comments were posted to the ECC platform project and lane issues after project status updates returned disabled | Needs workspace config/product rollout for hosted issue sync |
| Realtime Linear sync | Project updates while issue limit is blocked; issues later | ECC-Tools #39 implements opt-in Linear API sync for deferred follow-up backlog items, and ECC-Tools #54 adds copy-ready PR drafts to that backlog when draft PR shells are not opened; `docs/architecture/progress-sync-contract.md` defines the local file-backed realtime boundary while issue capacity is blocked | 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 |
| Proper release and notifications | Release tag, npm publish state, plugin state, social posts | Publication readiness gate exists with May 12 dry-run and May 13 readiness evidence | Not complete; approval/live URLs required |
@@ -984,10 +338,10 @@ repo evidence and merge commits.
| Queue hygiene and salvage | GitHub PR/issue state, salvage ledger | Append ledger entries for any future stale closures | Every cleanup batch |
| Release and publication | rc.1 release docs, publication readiness doc | Naming matrix and plugin submission/contact checklist | Before any tag |
| Harness OS core | Audit, adapter matrix, observability docs, `ecc2/` | HUD/session-control acceptance spec | Weekly until GA |
| Evaluation and RAG | Reference-set validation, harness audit, traces, ECC-Tools corpus | Read-only evaluator/RAG prototype plus stale-salvage, billing-readiness, CI-failure-diagnosis, harness-config-quality, AgentShield policy-exception, skill-quality evidence, deep-analyzer evidence, and RAG/evaluator comparison fixtures; ECC-Tools #68 publishes the corpus as a hosted promotion readiness check-run, #69 scores cached hosted job outputs against the same corpus, #70 emits ranked retrieval candidates plus a model prompt seed, #71 adds a fail-closed hosted model-judge request contract, and #72 executes that judge only when explicitly enabled and backed by hosted retrieval citations; ECC-Tools `16c537f` surfaces policy-promotion Action output values in hosted security comments/checks; ECC-Tools `05d4e82` adds hosted model-judge audit traces with request fingerprints and allowed-citation counts | Marketplace Pro billing-state verification with webhook provenance |
| AgentShield enterprise | AgentShield PR evidence and roadmap notes | Fleet routing landed in #89 after evidence-pack inspect/readback shipped in #88; #90 emits fleet `reviewItems`; #91 exports checksum-backed policy bundles; #92 promotes checksum-verified policies from those bundles into active policy files; #94 adds Zed and VS Code adapter detection, Zed project scan discovery, and `.zed/setup.mjs` persistence IOC coverage; #95 closes the `brace-expansion` Dependabot alert with 0 open alerts after merge; AgentShield `87aec47` adds policy promotion `reviewItems`; `28d08c7` adds package-manager hardening drift detection; `659f569` refreshes workflow action runtime pins; `ee585cd` corrects unsupported npm release-age guidance and keeps enforceable cooldown findings on pnpm/Yarn; `1124535` exposes package-manager hardening Action outputs for CI/hosted routing; `1593925` exposes policy-promotion Action outputs and runtime-smoke job-summary evidence; `840952a` adds fleet review ticket payloads and current Mini Shai-Hulud IOC breadcrumbs; ECC-Tools #76 consumes fleet summaries, #77 surfaces source evidence paths in hosted findings, #78 links fleet routes to harness owners, ECC-Tools `8658951` consumes policy-promotion Action outputs, and ECC-Tools `16c537f` renders operator-visible output values | Deepen live operator approval/readback after Marketplace/payment gates |
| ECC Tools app | ECC-Tools PR evidence, billing audit, risk taxonomy, evaluator/RAG corpus | ECC-Tools #53 published the supply-chain workflow hardening branch, #54 tracks copy-ready PR drafts in the Linear/project backlog, #55 classifies analysis-depth readiness, #56 exposes the hosted execution plan, #57 executes the first hosted CI diagnostics job, #58 executes the hosted security evidence review job, #59 executes the hosted harness compatibility audit, #60 executes the hosted reference-set evaluation, #61 executes the hosted AI routing/cost review, #62 executes hosted team backlog routing, #63 publishes the hosted depth-plan check-run, #64 dispatches hosted jobs from PR comments, #65 persists hosted result history/check-runs, #66 exposes hosted job status from PR comments, #67 makes depth-plan recommendations cache-aware, #68 publishes hosted promotion readiness from the evaluator/RAG corpus, #69 scores cached hosted job outputs against that corpus, #70 emits ranked retrieval candidates plus a model prompt seed, #71 emits the gated `hosted-promotion-judge.v1` contract without live model calls, #72 adds opt-in live model-judge execution behind hosted-evidence and strict JSON/citation gates, #73 adds a fail-closed native-payments `announcementGate` to billing readiness, #74 adds `npm run billing:announcement-gate` for operator verification, #75 tightens the billing announcement gate for live Marketplace readback, #76 routes AgentShield fleet-summary evidence into hosted security findings, #77 adds source evidence paths to hosted finding output, #78 links AgentShield fleet target paths to hosted harness owner findings, `8658951` routes AgentShield policy-promotion Action outputs into hosted security review and promotion readiness, `16c537f` renders policy-promotion status/pack/count/digest values in hosted security comments/checks, `05d4e82` renders hosted promotion judge request fingerprints plus allowed-citation audit traces, `91a441b` adds billing announcement preflight output for required readback inputs, `eb69412` records the initial production readback state, `95d0bec` adds aggregate `billing:kv-readback` evidence, `2859678` requires Marketplace webhook provenance in billing readiness, `42653f9` adds Wrangler OAuth readback with live aggregate production counts, `632e059` adds sanitized target-account billing readback for the exact Marketplace test account, ECC-Tools #89 adds selected-ready-target KV readback, ECC-Tools #90 adds selected-target official announcement gating without raw login input, and ECC-Tools #91 adds `--env-file` support for ignored local billing credentials without printing secrets or logins | Obtain or rotate the local/internal `INTERNAL_API_SECRET` bearer-token path, via exported env or ignored `--env-file`, then run the live selected-target billing announcement gate |
| Linear progress | Linear project status updates, `docs/architecture/progress-sync-contract.md`, generated `operator:dashboard` output, and this mirror | Status update with queue/evidence/missing gates | Every significant merge batch |
| 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 | Hosted retrieval/check-run automation plan |
| 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 and #54 tracks copy-ready PR drafts in the Linear/project backlog; next work is hosted/deeper analysis follow-up | Next implementation batch |
| 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 |
The project status update should always include:
@@ -1046,7 +400,7 @@ Acceptance:
Zed-adjacent surfaces, dmux, Orca, Superset, Ghast, and terminal-only use.
- Each adapter has supported assets, unsupported surfaces, install path,
verification command, and risk notes.
- Harness audit remains 80/80 and gains a public onramp that explains how teams
- Harness audit remains 70/70 and gains a public onramp that explains how teams
use the scorecard.
- Reference findings are converted into concrete adapter, observability, or
operator-surface deltas.
@@ -1201,72 +555,15 @@ Acceptance:
baselines; PR #80 added prioritized corpus accuracy recommendations for
failed regression gates; PR #81 added ordered remediation workflow phases;
PR #82 expanded corpus coverage for env proxy hijacks and out-of-band
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; 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; ECC-Tools PR #77 surfaces source
evidence paths in hosted PR comments and check-runs; ECC-Tools PR #78
links AgentShield fleet target paths into hosted harness owner findings; and
AgentShield PR #90 emits fleet `reviewItems` with source evidence paths and
owner-ready recommendations; AgentShield PR #91 exports checksum-backed
policy bundles for branch-protection review and downstream policy
promotion; AgentShield PR #92 promotes checksum-verified policy bundles
into active policy files with dry-run JSON review; AgentShield commit
`87aec47` adds policy promotion `reviewItems` for digest evidence,
owner-review, protected-rollout PR handoff, and runtime smoke testing;
AgentShield commit `28d08c7` adds package-manager hardening drift detection;
AgentShield commit `659f569` clears the action-runtime deprecation warnings
with current SHA-pinned v6 actions; AgentShield commit `ee585cd` corrects
npm release-age guidance so unsupported npm age keys are findings while
enforceable cooldown findings stay on pnpm/Yarn; AgentShield commit
`1124535` exposes package-manager hardening Action outputs for registry
credentials, lifecycle-script drift, and release-age gate drift; and
AgentShield commit `1593925` exposes policy-promotion Action outputs for
owner approval, protected rollout, digest evidence, and runtime-smoke
review items, ECC-Tools commit `8658951` consumes those outputs in hosted
security review and Hosted Promotion Readiness scoring, and ECC-Tools
commit `16c537f` renders promotion status, pack, review item count,
remaining action count, and digest in hosted security comments/check-runs.
AgentShield commit `840952a` adds Linear/operator-ready fleet review ticket
payloads and expands current Mini Shai-Hulud IOC breadcrumbs, with green
local and remote CI. AgentShield commit `4e36aab` hardens CI package installs
after the expanded Mini Shai-Hulud refresh, with CI, Test GitHub Action,
Self-Scan, and Dependabot Update workflows green.
ECC-Tools commit `05d4e82` adds hosted promotion judge audit traces with
deterministic request fingerprints and allowed-citation counts, without
exposing raw provider output.
ECC-Tools commit `91a441b` adds a billing announcement preflight command
for checking Marketplace readback inputs before privileged API calls.
ECC-Tools commit `2859678` requires Marketplace webhook provenance in
billing-state before native-payments announcement readiness can pass.
ECC-Tools commit `42653f9` adds Wrangler OAuth KV readback and confirms the
current blocker is not Cloudflare read access; it is the absence of a
ready-like Marketplace Pro billing-state record with webhook provenance.
ECC-Tools commit `632e059` adds sanitized target-account readback, and PRs
#89/#90/#91 move the final operator path to selected-target readback,
selected-target announcement gating, and ignored env-file credential loading
without printing account logins or raw KV key names.
ECC-Tools PR #79 redacts the billing announcement gate account output;
PR #80 requires failure reasons in runtime receipts; PRs #81/#82 preserve
and render AgentShield fleet approval IDs; PR #83 makes Linear follow-up
sync idempotent by external ID; PR #84 syncs hosted AgentShield
remediation items into Linear; PR #85 emits hosted job observability events
including budget-blocked outcomes; PRs #86/#87 read those events back into
hosted status comments and hosted depth-plan check-runs; and PR #88 exposes
authenticated hosted observability API readback for operator dashboards.
2. Run `npm run billing:announcement-gate -- --preflight
--select-ready-target`, adding `--env-file /path/to/ecc-tools.env` when the
local bearer token is stored in an ignored operator file, then run the same
command without `--preflight` and require `announcementGate.ready === true`
before any native GitHub payments announcement.
exfiltration; and ECC-Tools PRs #42/#43 now route and recognize evidence
packs. The next slice is hosted evidence-pack workflow depth.
2. Keep ECC-Tools #53's supply-chain workflow gate and #54's PR-draft backlog
tracking in the recurring queue evidence, and use the org-scoped GitHub auth
path for future ECC-Tools maintenance while the narrow environment token
remains active.
3. Enable/configure the merged Linear backlog sync path after workspace issue
capacity clears or the Linear workspace is upgraded, then verify PR-draft
salvage items land in the expected project.
4. Use the ECC-Tools evaluator/RAG corpus as the promotion gate before adding
deeper hosted retrieval, vector storage, or automated check-run promotion.
hosted retrieval, vector storage, model-backed judging, or automated
check-run promotion.

View File

@@ -229,8 +229,7 @@ Required safeguards:
## Near-Term Implementation Order
1. Extend the harness adapter matrix and public scorecard onramp.
2. Keep the release/name/plugin publication checklist current with fresh
final-commit evidence before rc.1 publication.
2. Add the release/name/plugin publication checklist with evidence fields.
3. Define the HUD/status JSON contract and fixture directory.
4. Start AgentShield policy schema plus SARIF fixtures.
5. Audit ECC Tools billing and check-run surfaces.

View File

@@ -1,7 +1,6 @@
# AgentShield Enterprise Research Roadmap
Generated: 2026-05-12; refreshed with May 18 AgentShield fleet-ticket and
Mini Shai-Hulud IOC evidence.
Generated: 2026-05-12
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,
@@ -85,53 +84,12 @@ 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, 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.
docs-example downgrades, hook-manifest resolution, false-positive audit
guidance, and corpus readiness.
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.
AgentShield commit `840952a7a07f820f24081c43df656d7f7295f23b` adds
Linear/operator-ready fleet review ticket payloads with priority, labels,
titles, and Markdown bodies. The same commit expands current Mini
Shai-Hulud/TanStack IOC coverage for the in-cluster Vault endpoint and
temporary lockfile breadcrumb, with local typecheck, lint, full tests,
`git diff --check`, and GitHub CI/Self-Scan/Action-test evidence.
The next iteration after fleet routing should not be "add more regex rules" by
default. ECC-Tools follow-up routing now consumes fleet summaries and surfaces
source evidence paths in hosted findings, and the first cross-harness policy
slice now links AgentShield fleet route target paths to harness-owner review.
AgentShield fleet output now also emits `reviewItems` with source evidence paths
and owner-ready recommendations plus copy-ready ticket payloads for routed
packs. The higher leverage move is durable operator approval/readback and
workflow automation for routed fleet findings.
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.
## Enterprise Gaps
@@ -365,8 +323,6 @@ 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,90 +0,0 @@
# Discussion Response Playbook
This playbook turns GitHub Discussions into the same operating queue as PRs,
issues, Linear work, and release evidence. It is an operator guide, not a
promise that every informational thread needs a public reply.
## Audit Loop
Run these checks before a release, after a major merge batch, and when Linear
ITO-59 is refreshed:
```bash
npm run discussion:audit -- --json
node scripts/platform-audit.js --json
```
The queue is current only when:
- discussion fetch errors are explained or fixed;
- `needsMaintainerTouch` is zero for support-like discussion categories;
- answerable Q&A discussions either have an accepted answer or a clear routing
note; and
- any product-scope thread is linked to a GitHub issue, Linear issue, roadmap
row, or explicit deferral.
Informational threads such as announcements, references, show-and-tell, or
maintainer-authored updates can remain visible without becoming response debt.
## Categories
| Category | Route | Required readback |
| --- | --- | --- |
| Product support or install confusion | Reply with the exact command/doc path; mark accepted answer for Q&A when the fix is complete | Discussion URL plus accepted-answer URL when applicable |
| Bug report | Ask for a minimal repro, version, harness, and logs; create or link a GitHub issue when reproducible | Issue URL or deferral reason |
| Feature request | Acknowledge the desired outcome and link the closest roadmap issue; do not imply commitment unless scoped | Linear/GitHub roadmap link |
| Security concern | Move exploit details and secrets to a private channel; keep the public reply short and non-operational | Private escalation note plus public safety reply |
| Release or billing question | Answer from the release URL ledger and publication-readiness gates; do not claim unpublished URLs, billing readiness, or plugin availability | Evidence artifact or blocker link |
| Show-and-tell, reference, or announcement | Leave as informational unless there is a direct question or a product-scope signal | Optional roadmap link if useful |
| Stale or concluded thread | Summarize the current state and link the durable doc/issue; avoid reviving low-signal threads | Closure note or explicit no-action rationale |
## Templates
### Public Support
Thanks for the report. The current supported path is:
```bash
<command>
```
The relevant doc is `<doc path or URL>`. If this does not match your setup,
please reply with the harness, OS, package manager, and the exact error text.
### Maintainer Coordination
I am routing this into `<issue or Linear key>` so it does not get lost in the
discussion queue. The next decision is `<specific decision>`. Until that lands,
the supported workaround is `<workaround or "none">`.
### Stale Or Concluded
This thread looks resolved or superseded by `<doc/issue/release>`. I am leaving
it visible for history, but it is no longer an active support queue item. New
repro details should go to `<issue/discussion path>`.
### Release Announcement
The current release status is `<rc/beta/GA state>`. Live URLs are recorded in
`docs/releases/2.0.0-rc.1/release-url-ledger-2026-05-18.md`. Anything marked
pending there should not be announced as shipped yet.
### Security Escalation
Thanks for flagging this. Please do not post exploit steps, tokens, customer
data, or secret values in the public thread. I am routing this through the
security response path and will keep the public thread limited to safe status
updates.
## Recording Outcomes
For each high-signal discussion, record one of these outcomes:
- replied publicly and accepted answer read back;
- linked to a GitHub issue or Linear issue;
- routed to the security response path;
- classified as informational; or
- explicitly deferred with a reason.
Mirror the summary into ITO-59 when the batch closes, and include the counts in
the next operator dashboard or publication evidence refresh.

View File

@@ -41,7 +41,7 @@ The matrix below is rendered from
| OpenCode | Adapter-backed | OpenCode package/plugin metadata; shared skills; MCP config; event adapter patterns | Event names, plugin packaging, and command dispatch differ from Claude Code | OpenCode package or plugin surface from this repo | `node tests/scripts/build-opencode.test.js`; `npm run harness:audit -- --format json` | Keep hook logic in shared scripts and adapt only event shape at the edge. |
| Cursor | Adapter-backed | Cursor rules; project-local skills; hook adapter; shared scripts | Cursor hook events and rule loading differ from Claude Code | `./install.sh --profile minimal --target cursor` | `node tests/lib/install-targets.test.js`; `npm run harness:audit -- --format json` | Cursor adapters must preserve existing project rules and avoid silent overwrite. |
| Gemini | Instruction-backed | Gemini project-local instructions; shared skills; rules; compatibility docs | No full ECC hook parity; ecosystem ports must document drift from upstream ECC | `./install.sh --profile minimal --target gemini` | `node tests/lib/install-targets.test.js` | Treat Gemini ports as ecosystem adapters until validated end to end inside Gemini CLI. |
| Zed | Adapter-backed | Zed project settings; flattened project rules; shared skills; commands; agents | Zed external agents and native Agent Panel permissions are not Claude hooks | `./install.sh --profile minimal --target zed` | `node tests/lib/install-targets.test.js`; `npm run harness:audit -- --format json` | Keep project settings conservative and do not copy BYOK/OpenRouter secrets into `.zed/`. |
| Zed-adjacent workflows | Instruction-backed | shared skills; `AGENTS.md` style project instructions; verification loops | Zed agent surfaces vary; no first-party ECC installer is shipped today | Manual copy from shared ECC sources until adapter requirements settle | `npm run harness:audit -- --format json` | Do not claim native Zed support before a real adapter and verification path exist. |
| dmux | Adapter-backed | session snapshots; tmux/worktree orchestration status; handoff exports | dmux is an orchestration runtime, not an install target for skills/rules | `node scripts/session-inspect.js --list-adapters`; dmux session target inspection | `node tests/lib/session-adapters.test.js` | Treat dmux events as session/runtime signals, not as a replacement for repo validation. |
| Orca | Reference-only | worktree lifecycle; review state; notification; provider-identity design pressure | No ECC installer or direct adapter today | Use as a comparison target for worktree/session state requirements | `npm run observability:ready` | Do not import product-specific assumptions; convert lessons into ECC event fields. |
| Superset | Reference-only | workspace presets; parallel-agent review loops; worktree isolation design pressure | No ECC installer or direct adapter today | Use as a comparison target for workspace preset taxonomy | `npm run observability:ready` | Keep ECC portable; do not require a desktop workspace to get basic value. |

View File

@@ -9,7 +9,7 @@ status update can claim a lane is current.
| Surface | Role | Current rule |
| --- | --- | --- |
| GitHub PRs/issues/discussions | Public queue and review state | Recheck live counts before every significant merge batch and before release approval. |
| Linear project | Executive roadmap and stakeholder status update | Use project documents and project/issue comments because project status updates are disabled in this workspace; create/reuse issues for durable execution lanes. |
| Linear project | Executive roadmap and stakeholder status update | Post project status updates while issue capacity blocks issue creation. Create/reuse issues only when workspace capacity is available. |
| Local handoff | Durable operator continuity | Update the active handoff after every merge batch, queue drain, skipped release gate, or blocked external action. |
| Repo roadmap | Auditable planning mirror | Keep `docs/ECC-2.0-GA-ROADMAP.md` aligned to merged PR evidence and unresolved gates. |
| `scripts/work-items.js` | Local tracker bridge | Sync GitHub PRs/issues into the SQLite work-items store for status snapshots and blocked follow-up. |
@@ -41,12 +41,9 @@ After a significant merge batch, update Linear and the handoff with:
4. Deferred or skipped work and the explicit reason.
5. The next one or two implementation slices.
When Linear project status updates are unavailable, use a project document plus
project/issue comments instead of creating placeholder issues. Issue capacity is
available for durable execution lanes, but do not use that issue capacity as a
substitute for evidence-backed project status. Create or reuse exact-title
issues only when the lane needs a durable execution owner, and link those issues
to repo evidence.
When Linear issue capacity is unavailable, use a project status update instead
of creating placeholder issues. When issue capacity is available, create or
reuse exact-title issues and link them to the repo evidence.
## Realtime Boundary

View File

@@ -28,15 +28,15 @@ curl -s https://api.npmjs.org/downloads/point/last-month/ecc-agentshield
### GitHub repository adoption
```bash
gh api repos/affaan-m/ECC \
gh api repos/affaan-m/everything-claude-code \
--jq '{stars:.stargazers_count,forks:.forks_count,contributors_url:.contributors_url,open_issues:.open_issues_count}'
```
### GitHub traffic (maintainer access required)
```bash
gh api repos/affaan-m/ECC/traffic/views
gh api repos/affaan-m/ECC/traffic/clones
gh api repos/affaan-m/everything-claude-code/traffic/views
gh api repos/affaan-m/everything-claude-code/traffic/clones
```
### GitHub App installs

View File

@@ -5,10 +5,9 @@ Use these templates as launch-ready starting points. Review channel tone before
## X Post: Release Announcement
```text
ECC v2.0.0-rc.1 preview pack is ready for final release review.
ECC v2.0.0-rc.1 is live.
ECC 2.0 is the harness-native operator system for agentic work: skills, hooks,
rules, MCP conventions, release gates, and an optional Hermes operator shell.
The repo is moving from a Claude Code config pack into a cross-harness operating system for agentic work.
What ships:
- Hermes setup guide
@@ -16,8 +15,8 @@ What ships:
- cross-harness architecture docs
- Hermes import guidance for turning local operator workflows into public ECC skills
Start here: https://github.com/affaan-m/ECC
Release notes: https://github.com/affaan-m/ECC/blob/main/docs/releases/2.0.0-rc.1/release-notes.md
Start here: https://github.com/affaan-m/everything-claude-code
Release notes: https://github.com/affaan-m/everything-claude-code/blob/main/docs/releases/2.0.0-rc.1/release-notes.md
```
## X Post: Proof + Metrics
@@ -56,9 +55,9 @@ ECC v2.0.0-rc.1 pushes that further: reusable skills, thin harness adapters, and
## LinkedIn Post: Partner-Friendly Summary
```text
ECC v2.0.0-rc.1 preview pack is ready for final release review.
ECC v2.0.0-rc.1 is live.
ECC 2.0 is the harness-native operator system for agentic work. The same reusable layer now reaches Claude Code, Codex, OpenCode, Cursor, Gemini, Zed, GitHub Copilot workflows, and terminal-only operator lanes.
The practical shift: ECC is no longer just a Claude Code config pack. It is becoming a cross-harness operating system for agentic work.
This release-candidate surface includes:
- sanitized Hermes setup documentation
@@ -68,6 +67,6 @@ This release-candidate surface includes:
It does not include private workspace state, credentials, raw local exports, or personal datasets.
Repo: https://github.com/affaan-m/ECC
Release notes: https://github.com/affaan-m/ECC/blob/main/docs/releases/2.0.0-rc.1/release-notes.md
Repo: https://github.com/affaan-m/everything-claude-code
Release notes: https://github.com/affaan-m/everything-claude-code/blob/main/docs/releases/2.0.0-rc.1/release-notes.md
```

View File

@@ -1,63 +0,0 @@
# ECC 1.10.1 release announcement draft
ECC 1.10.1 is the follow-up stabilization release to 1.10.0.
This release is focused on install correctness, cross-surface naming clarity, Windows/PowerShell recovery, Cursor project install correctness, and Claude Code hook compatibility. It is not a feature-heavy release.
## What landed in the stabilization pass
- npm/package/release surfaces are aligned and `ecc-universal@1.10.0` is live on npm
- Windows locale/path and PowerShell install-path regressions fixed
- Bash hook process-storm regression fixed
- Claude Code 2.1.x hook schema compatibility fixed
- Cursor native project install path repaired:
- `.cursor/hooks.json` now includes the required schema/version surface
- `.cursor/mcp.json` is written in the native Cursor project location
- continuous-learning-v2 now accepts `claude-desktop` as a valid entrypoint
- Windows observe path now skips `AppInstallerPythonRedirector.exe`
- docs now distinguish plugin installs from full manual installs more clearly
## What 1.10.1 is for
- make the current install surfaces predictable
- reduce stale naming/install guidance
- close the follow-up regressions from 1.10.0
- give users one stable update point instead of piecing together fixes across issues and discussions
## Included release fixes
- `#1543` Cursor native project hook + MCP install repair
- `#1524` Claude Code v2.1.116 argv-dup mitigation in `settings.local.json`
- `#1522` continuous-learning-v2 accepts `claude-desktop` as a valid entrypoint
- `#1511` Windows observe path skips `AppInstallerPythonRedirector.exe`
- `#1546` continuous-learning-v2 plugin quick start correction
- `#1535` hero overflow follow-up
## Important naming clarification
- Claude marketplace/plugin identifier: `everything-claude-code@everything-claude-code`
- npm package: `ecc-universal`
- GitHub repo: `affaan-m/everything-claude-code`
Those are intentionally different surfaces. The plugin identifier follows Anthropic marketplace rules; the npm package remains `ecc-universal`.
## Still being monitored
This should be announced as a stabilization release, not as “all edge cases are solved.”
We are still watching for:
- OS-specific edge cases across macOS, Windows, Linux
- shell-specific behavior differences
- Cursor vs Claude plugin install-path mismatches that only appear in older or mixed installs
- third-party provider/tool-name compatibility reports that still need current-main repro
Current watch-list examples:
- `#1520` likely obsolete unless repro returns on the current installer
- `#1516` not gating unless reproduced on current `main`
- `#1484` remains a Windows umbrella/watch-list issue rather than an active release gate
## Recommended update guidance
If you hit 1.10.0 install/runtime problems:
1. update to the latest package/plugin surface
2. avoid mixing plugin install plus full manual repo copy unless the docs explicitly say to
3. if problems persist, report:
- OS + shell
- Claude Code/Cursor version
- install method used
- exact stderr/output
- whether the issue is plugin install, npm install, repo sync, or Cursor project install

View File

@@ -1,4 +1,4 @@
**言語:** [English](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md)
**言語:** [English](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md)
# Everything Claude Code
@@ -21,7 +21,7 @@
**言語 / Language / 語言 / Dil / Язык / Ngôn ngữ**
[**English**](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md)
[**English**](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md)
</div>
@@ -122,12 +122,12 @@
git clone https://github.com/affaan-m/everything-claude-code.git
# 共通ルールをインストール(必須)
cp -r everything-claude-code/rules/common ~/.claude/rules/common
cp -r everything-claude-code/rules/common/* ~/.claude/rules/
# 言語固有ルールをインストール(スタックを選択)
cp -r everything-claude-code/rules/typescript ~/.claude/rules/typescript
cp -r everything-claude-code/rules/python ~/.claude/rules/python
cp -r everything-claude-code/rules/golang ~/.claude/rules/golang
cp -r everything-claude-code/rules/typescript/* ~/.claude/rules/
cp -r everything-claude-code/rules/python/* ~/.claude/rules/
cp -r everything-claude-code/rules/golang/* ~/.claude/rules/
```
### ステップ3使用開始
@@ -462,15 +462,15 @@ Duplicate hook file detected: ./hooks/hooks.json is already resolved to a loaded
>
> # オプション Aユーザーレベルルールすべてのプロジェクトに適用
> mkdir -p ~/.claude/rules
> cp -r everything-claude-code/rules/common ~/.claude/rules/common
> cp -r everything-claude-code/rules/typescript ~/.claude/rules/typescript # スタックを選択
> cp -r everything-claude-code/rules/python ~/.claude/rules/python
> cp -r everything-claude-code/rules/golang ~/.claude/rules/golang
> cp -r everything-claude-code/rules/common/* ~/.claude/rules/
> cp -r everything-claude-code/rules/typescript/* ~/.claude/rules/ # スタックを選択
> cp -r everything-claude-code/rules/python/* ~/.claude/rules/
> cp -r everything-claude-code/rules/golang/* ~/.claude/rules/
>
> # オプション Bプロジェクトレベルルール現在のプロジェクトのみ
> mkdir -p .claude/rules
> cp -r everything-claude-code/rules/common .claude/rules/common
> cp -r everything-claude-code/rules/typescript .claude/rules/typescript # スタックを選択
> cp -r everything-claude-code/rules/common/* .claude/rules/
> cp -r everything-claude-code/rules/typescript/* .claude/rules/ # スタックを選択
> ```
---
@@ -487,10 +487,10 @@ git clone https://github.com/affaan-m/everything-claude-code.git
cp everything-claude-code/agents/*.md ~/.claude/agents/
# ルール(共通 + 言語固有)をコピー
cp -r everything-claude-code/rules/common ~/.claude/rules/common
cp -r everything-claude-code/rules/typescript ~/.claude/rules/typescript # スタックを選択
cp -r everything-claude-code/rules/python ~/.claude/rules/python
cp -r everything-claude-code/rules/golang ~/.claude/rules/golang
cp -r everything-claude-code/rules/common/* ~/.claude/rules/
cp -r everything-claude-code/rules/typescript/* ~/.claude/rules/ # スタックを選択
cp -r everything-claude-code/rules/python/* ~/.claude/rules/
cp -r everything-claude-code/rules/golang/* ~/.claude/rules/
# コマンドをコピー
cp everything-claude-code/commands/*.md ~/.claude/commands/

View File

@@ -0,0 +1,44 @@
# メモリ永続化フック
これらのライフサイクルフック定義は、Claude CodeプラグインおよびマニュアルインストールにおけるECCのメモリ永続化コントラクトを文書化します。
実行可能な実装は `scripts/hooks/` にあります:
- `session-start.js` は境界付けられた事前コンテキストを読み込み、プロジェクト状態を検出し、セッションメタデータを準備します。
- `pre-compact.js` はコンテキスト圧縮前に状態をキャプチャします。
- `session-end.js` はトランスクリプトメタデータが利用可能な場合にセッション終了サマリーを永続化します。
- `observe-runner.js` は継続学習のためのツール使用観察を記録します。
- `session-activity-tracker.js` はECC2のステータスと可観測性のためのツール使用とファイルアクティビティを記録します。
インストール済みフックグラフは引き続き `hooks/hooks.json` です。このディレクトリは、ハーネス監査と長文ドキュメントが参照する安定した人間が読めるライフサイクル定義サーフェスです。
## ライフサイクルコントラクト
| イベント | フック | 目的 | ブロッキング |
|---|---|---|---|
| `SessionStart` | `session:start` | 境界付けられた事前コンテキストとプロジェクトメタデータを読み込む | いいえ |
| `PreCompact` | `pre:compact` | 圧縮前に状態を保存する | いいえ |
| `PreToolUse` | `pre:observe:continuous-learning` | 学習シグナルのためのツール意図をキャプチャ | いいえ |
| `PostToolUse` | `post:observe:continuous-learning` | 学習シグナルのためのツール結果をキャプチャ | いいえ |
| `PostToolUse` | `post:session-activity-tracker` | ECC2メトリクス用のツールとファイルアクティビティを記録 | いいえ |
| `Stop` | `stop:format-typecheck` | 編集後のバッチ品質ゲート | フック失敗時にブロック |
| `Stop` | `stop:check-console-log` | 変更されたファイルのデバッグログを監査 | フック出力による警告/エラー |
## オペレーター期待値
- デフォルトでは永続化をローカルに保つ。
- ユーザーが明示的にインテグレーションを有効にしない限り、トランスクリプトやツールトレースをホストサービスに送信しない。
- `ECC_SESSION_START_MAX_CHARS` でセッション開始時に読み込まれるコンテキストを制限する。
- `ECC_SESSION_START_CONTEXT=off` でオプトアウトを許可する。
- `ECC_HOOK_PROFILE``ECC_DISABLED_HOOKS` でライフサイクルフックをプロファイルゲート管理する。
## 関連ファイル
- `hooks/hooks.json`
- `hooks/README.md`
- `scripts/hooks/session-start.js`
- `scripts/hooks/pre-compact.js`
- `scripts/hooks/session-end.js`
- `scripts/hooks/observe-runner.js`
- `scripts/hooks/session-activity-tracker.js`
- `docs/architecture/observability-readiness.md`

View File

@@ -0,0 +1,160 @@
# Angular アニメーション
Angularで要素をアニメーションさせる場合は、**まず `package.json` でプロジェクトのAngularバージョンを確認してください**。
モダンなアプリケーション(**Angular v20.2以上**)では、`animate.enter``animate.leave` を使ったネイティブCSSを優先してください。古いアプリケーションでは、非推奨の `@angular/animations` パッケージを使用する必要がある場合があります。
## 1. ネイティブCSSアニメーションv20.2以上 推奨)
モダンなAngularは `animate.enter``animate.leave` を提供し、要素がDOMに追加・削除される際にアニメーションさせます。これらは適切なタイミングでCSSクラスを適用します。
### `animate.enter` と `animate.leave`
要素に直接使用して、enter・leaveフェーズ中にCSSクラスを適用します。Angularはアニメーション完了時にenterクラスを自動的に削除します。`animate.leave` の場合、Angularはアニメーションが完了するまで要素をDOMから削除しません。
`animate.enter` の例:
```html
@if (isShown()) {
<div class="enter-container" animate.enter="enter-animation">
<p>The box is entering.</p>
</div>
}
```
```css
/* トランジションを使用する場合は開始スタイルを定義してください */
.enter-container {
border: 1px solid #dddddd;
margin-top: 1em;
padding: 20px;
font-weight: bold;
font-size: 20px;
}
.enter-container p {
margin: 0;
}
.enter-animation {
animation: slide-fade 1s;
}
@keyframes slide-fade {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
```
_注意: `animate.leave` は削除される子要素に追加できます。_
### イベントバインディングとサードパーティライブラリ
`(animate.enter)``(animate.leave)` にバインドして、関数を呼び出したりGSAPなどのJSライブラリを使用することができます。
```html
@if(show()) {
<div (animate.leave)="onLeave($event)">...</div>
}
```
```ts
import { AnimationCallbackEvent } from '@angular/core';
onLeave(event: AnimationCallbackEvent) {
// カスタムアニメーションロジックをここに記述
// 重要: Angularが要素を削除できるよう、完了時に必ず animationComplete() を呼び出してください!
event.animationComplete();
}
```
## 2. 高度なCSSアニメーション
CSSは高度なアニメーションシーケンスのための強力なツールを提供しています。
### 状態とスタイルのアニメーション
プロパティバインディングを使用して要素のCSSクラスを切り替え、トランジションをトリガーします。
```html
<div [class.open]="isOpen">...</div>
```
```css
div {
transition: height 0.3s ease-out;
height: 100px;
}
div.open {
height: 200px;
}
```
### Autoハイトのアニメーション
`css-grid` を使用してautoハイトへのアニメーションが可能です。
```css
.container {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows 0.3s;
}
.container.open {
grid-template-rows: 1fr;
}
.container > div {
overflow: hidden;
}
```
### スタッガリングと並列アニメーション
- **スタッガリング**: リスト内のアイテムに異なる値の `animation-delay` または `transition-delay` を使用します。
- **並列**: `animation` ショートハンドで複数のアニメーションを適用します(例:`animation: rotate 3s, fade-in 2s;`)。
### プログラムによる制御
標準のWeb APIを使用してアニメーションを直接取得します
```ts
const animations = element.getAnimations();
animations.forEach((anim) => anim.pause());
```
## 3. レガシーアニメーションDSL非推奨
古いプロジェクトv20.2以前、または `@angular/animations` が既に大量に使用されているプロジェクトでは、コンポーネントメタデータDSLを使用します。
**重要:** レガシーアニメーションと `animate.enter`/`leave` を同じコンポーネント内で混在させないでください。
### セットアップ
```ts
bootstrapApplication(App, {
providers: [provideAnimationsAsync()],
});
```
### トランジションの定義
```ts
import {signal} from '@angular/core';
import {trigger, state, style, animate, transition} from '@angular/animations';
@Component({
animations: [
trigger('openClose', [
state('open', style({opacity: 1})),
state('closed', style({opacity: 0})),
transition('open <=> closed', [animate('0.5s')]),
]),
],
template: `<div [@openClose]="isOpen() ? 'open' : 'closed'">...</div>`,
})
export class OpenClose {
isOpen = signal(true);
}
```

View File

@@ -0,0 +1,410 @@
# Angular Aria
Angular Aria`@angular/aria`は、一般的なWAI-ARIAパターンを実装するヘッドレスでアクセシブルなディレクティブのコレクションです。これらのディレクティブは、キーボードインタラクション、ARIA属性、フォーカス管理、スクリーンリーダーのサポートを処理します。
**AIエージェントとしての役割は、HTMLの構造とCSSスタイリングを提供すること**であり、ディレクティブが複雑なアクセシビリティロジックを処理します。
## ヘッドレスコンポーネントのスタイリング
Angular Ariaコンポーネントはヘッドレスであるため、デフォルトのスタイルは付属していません。ディレクティブが自動的に適用するARIA属性や構造クラスに基づいて、CSSで各状態をスタイリングする**必要があります**。
CSSでターゲットとする一般的なARIA属性
- `[aria-expanded="true"]` / `[aria-expanded="false"]`
- `[aria-selected="true"]`
- `[aria-disabled="true"]`
- `[aria-current="page"]`(ナビゲーション用)
---
**重要**: このパッケージを使用する前に、パッケージマネージャーでインストールする必要があります。プロジェクトにインストールされていることを確認してください。必要な場合は `npm install @angular/aria` でインストールしてください。
## 1. アコーディオン
関連するコンテンツを展開・折りたたみ可能なセクションに整理します。
**使用場面:** アコーディオンは、コンテンツの多いページでスクロールを減らすために、ユーザーが一度に1つずつ展開できる論理的なグループにコンテンツを整理するレイアウトコンポーネントです。FAQ、長いフォーム、または情報の段階的な開示に使用しますが、プライマリナビゲーションや、ユーザーが複数のコンテンツセクションを同時に表示する必要があるシナリオには使用しないでください。
**インポート:** `import { AccordionContent, AccordionGroup, AccordionPanel, AccordionTrigger } from '@angular/aria/accordion';`
**ディレクティブ:** `ngAccordionGroup``ngAccordionTrigger``ngAccordionPanel``ngAccordionContent`(遅延ロード用)。
```ts
@Component({
selector: 'app-cmp',
imports: [AccordionContent, AccordionGroup, AccordionPanel, AccordionTrigger],
template: `...`,
styles: [],
})
export class App {
protected readonly title = signal('angular-app');
}
```
```html
<div ngAccordionGroup [multiExpandable]="false">
<div class="accordion-item">
<button ngAccordionTrigger panelId="panel-1" class="accordion-header">
Section 1
<span class="icon"></span>
</button>
<div ngAccordionPanel panelId="panel-1" class="accordion-panel">
<ng-template ngAccordionContent>
<p>Lazy loaded content here.</p>
</ng-template>
</div>
</div>
</div>
```
**スタイリング戦略:**
トリガーの `[aria-expanded]` 属性をターゲットにしてアイコンを回転させ、パネルの表示をスタイリングします。
```css
.accordion-header[aria-expanded='true'] .icon {
transform: rotate(180deg);
}
/* パネルディレクティブがDOM削除を処理しますが、トランジションをスタイリングできます */
.accordion-panel {
padding: 1rem;
border-top: 1px solid #ccc;
}
```
---
## 2. リストボックス
オプションのリストを表示するための基本的なディレクティブです。可視の選択リスト(ドロップダウンではない)に使用します。
**使用場面:** 可視の選択可能なリスト(単一または複数選択)。
**インポート:** `import {Listbox, Option} from '@angular/aria/listbox';`
**ディレクティブ:** `ngListbox``ngOption`
```ts
@Component({
selector: 'app-cmp',
imports: [Listbox, Option],
template: `...`,
styles: [],
})
export class App {
protected readonly title = signal('angular-app');
}
```
```html
<!-- 水平または垂直方向 -->
<ul ngListbox [(values)]="selectedItems" orientation="horizontal" [multi]="true">
<li ngOption value="apple" class="option">Apple</li>
<li ngOption value="banana" class="option">Banana</li>
</ul>
```
**スタイリング戦略:**
選択状態には `[aria-selected="true"]`、フォーカスされたアイテムには `:focus-visible` または `[data-active]` をターゲットにしますAngular Ariaはroving tabindexまたはactivedescendantを使用します
```css
.option {
padding: 8px;
cursor: pointer;
}
.option[aria-selected='true'] {
background: #e0f7fa;
font-weight: bold;
}
/* フォーカス状態はariaで管理されます */
.option:focus-visible {
outline: 2px solid blue;
}
```
---
## 3. コンボボックス、セレクト、マルチセレクト
これらのパターンは、`ngCombobox` とポップアップ内の `ngListbox` を組み合わせます。
- **コンボボックス**: テキスト入力 + ポップアップ(オートコンプリートに使用)。
- **セレクト**: 読み取り専用コンボボックス + 単一選択リストボックス。
- **マルチセレクト**: 読み取り専用コンボボックス + 複数選択リストボックス。
**使用場面:** コンボボックスは、テキスト入力をポップアップと同期させる低レベルのプリミティブディレクティブで、オートコンプリート、セレクト、マルチセレクトパターンの基盤となるロジックとして機能します。カスタムフィルタリング、独自の選択要件、または標準の文書化されたコンポーネントから逸脱した特殊な入力-ポップアップ連携を構築する場合に特に使用してください。
**インポート:**
```
import {Combobox, ComboboxInput, ComboboxPopupContainer} from '@angular/aria/combobox';
import {Listbox, Option} from '@angular/aria/listbox';
```
**ディレクティブ:** `ngCombobox``ngComboboxInput``ngComboboxPopupContainer``ngListbox``ngOption`
```html
<!-- 例:標準セレクト -->
<div ngCombobox [readonly]="true">
<button ngComboboxInput class="select-trigger">
{{ selectedValue() || 'Choose an option' }}
</button>
<ng-template ngComboboxPopupContainer>
<ul ngListbox [(values)]="selectedValue" class="dropdown-menu">
<li ngOption value="option1">Option 1</li>
<li ngOption value="option2">Option 2</li>
</ul>
</ng-template>
</div>
```
**スタイリング戦略:**
ポップアップコンテナをコンテンツの上に浮かぶドロップダウンのように見せるスタイリングをしますCDK Overlayと組み合わせることが多い
```css
.select-trigger {
width: 200px;
padding: 8px;
text-align: left;
}
.dropdown-menu {
list-style: none;
padding: 0;
margin: 0;
border: 1px solid #ccc;
background: white;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
```
---
## 4. メニューとメニューバー
アクション、コマンド、コンテキストメニュー用(フォーム選択には使用しない)。
**使用場面:** メニューバーは、インターフェース全体に渡って持続するデスクトップスタイルのアプリケーションコマンドバー(例:ファイル、編集、表示)を構築するための高レベルのナビゲーションパターンです。完全な水平キーボードサポートを備えた論理的なトップレベルカテゴリへの複雑なコマンドの整理に最適ですが、シンプルなスタンドアロンアクションリストや水平スペースが制約されるモバイルファーストのレイアウトには避けてください。
**インポート:** `import {MenuBar, Menu, MenuContent, MenuItem} from '@angular/aria/menu';`
**ディレクティブ:** `ngMenuBar``ngMenu``ngMenuItem``ngMenuTrigger`
```html
<!-- メニューバーの例 -->
<ul ngMenuBar class="menubar">
<li ngMenuItem value="file">
<button ngMenuTrigger [menu]="fileMenu">File</button>
</li>
</ul>
<ul ngMenu #fileMenu="ngMenu" class="menu">
<li ngMenuItem value="new">New</li>
<li ngMenuItem value="open">Open</li>
</ul>
```
**スタイリング戦略:**
メニューバーにはflexboxを使用します。トリガーの状態に基づいてサブメニューを表示・非表示にします。
```css
.menubar {
display: flex;
gap: 10px;
list-style: none;
padding: 0;
}
.menu {
background: white;
border: 1px solid #ccc;
padding: 5px 0;
}
.menu li {
padding: 5px 15px;
cursor: pointer;
}
```
---
## 5. タブ
1つのパネルのみが表示される層状のコンテンツセクション。
**使用場面:** タブコンポーネントは、関連するコンテンツを明確なナビゲート可能なセクションに整理し、ユーザーがページを離れることなくカテゴリやビューを切り替えられるようにします。設定パネル、複数トピックのドキュメント、ダッシュボードに理想的ですが、順次ワークフローステッパーや7〜8セクションを超えるナビゲーションには避けてください。
**インポート:** `import {Tab, Tabs, TabList, TabPanel, TabContent} from '@angular/aria/tabs';`
**ディレクティブ:** `ngTabs``ngTabList``ngTab``ngTabPanel``ngTabContent`
```html
<div ngTabs>
<ul ngTabList class="tab-list">
<li ngTab value="profile" class="tab-btn">Profile</li>
<li ngTab value="security" class="tab-btn">Security</li>
</ul>
<div ngTabPanel value="profile" class="tab-panel">
<ng-template ngTabContent>Profile Settings</ng-template>
</div>
<div ngTabPanel value="security" class="tab-panel">
<ng-template ngTabContent>Security Settings</ng-template>
</div>
</div>
```
**スタイリング戦略:**
タブボタンの `[aria-selected="true"]` をターゲットにします。
```css
.tab-list {
display: flex;
border-bottom: 2px solid #ccc;
list-style: none;
padding: 0;
}
.tab-btn {
padding: 10px 20px;
cursor: pointer;
border-bottom: 2px solid transparent;
}
.tab-btn[aria-selected='true'] {
border-bottom-color: blue;
font-weight: bold;
}
.tab-panel {
padding: 20px;
}
```
---
## 6. ツールバー
関連するコントロールをグループ化します(テキストフォーマットなど)。
**使用場面:** ツールバーは、頻繁にアクセスされる関連コントロールを1つの論理コンテナにグループ化するための組織コンポーネントです。テキストフォーマットやメディアコントロールなど、繰り返しアクションが必要なワークフローのキーボード効率矢印キーナビゲーションと視覚的構造を強化するために最適です。
**インポート:** `import {Toolbar, ToolbarWidget, ToolbarWidgetGroup} from '@angular/aria/toolbar';`
**ディレクティブ:** `ngToolbar``ngToolbarWidget``ngToolbarWidgetGroup`
```html
<div ngToolbar class="toolbar">
<div ngToolbarWidgetGroup [multi]="true" role="group" aria-label="Formatting">
<button ngToolbarWidget value="bold" class="tool-btn">B</button>
<button ngToolbarWidget value="italic" class="tool-btn">I</button>
</div>
</div>
```
**スタイリング戦略:**
ツールバー内の `[aria-pressed="true"]`(トグルボタン用)または `[aria-checked="true"]`(ラジオグループ用)をターゲットにします。
```css
.toolbar {
display: flex;
gap: 5px;
padding: 8px;
background: #f5f5f5;
}
.tool-btn {
padding: 5px 10px;
border: 1px solid #ccc;
}
.tool-btn[aria-pressed='true'],
.tool-btn[aria-checked='true'] {
background: #ddd;
}
```
---
## 7. ツリー
階層データを表示します(ファイルシステム、ネストされたナビゲーションなど)。
**使用場面:** ツリーコンポーネントは、ファイルシステム、組織図、複雑なサイトアーキテクチャなど、深くネストされた階層データ構造のナビゲーションと表示のために設計されています。ユーザーがブランチを展開・折りたたむ必要がある複数レベルの関係に特に使用しますが、フラットリスト、データテーブル、またはシンプルな選択メニューには避けてください。
**インポート:** `import {Tree, TreeItem, TreeItemGroup} from '@angular/aria/tree';`
**ディレクティブ:** `ngTree``ngTreeItem``ngTreeGroup`
```html
<ul ngTree class="tree">
<li ngTreeItem value="documents">
<span class="tree-label">Documents</span>
<ul ngTreeGroup class="tree-group">
<li ngTreeItem value="resume">Resume.pdf</li>
</ul>
</li>
</ul>
```
**スタイリング戦略:**
`[aria-expanded]` をターゲットにして子を表示・非表示にするか、シェブロンアイコンを回転させます。ネストされたグループに `padding-left` を使用して階層を表示します。
```css
.tree,
.tree-group {
list-style: none;
padding-left: 20px;
}
.tree-label::before {
content: '> ';
display: inline-block;
transition: transform 0.2s;
}
li[aria-expanded='true'] > .tree-label::before {
transform: rotate(90deg);
}
```
## 8. グリッド
矢印キーでナビゲーションを可能にする、セルの双方向インタラクティブコレクションです。
**使用場面:** データテーブル、カレンダー、スプレッドシート、インタラクティブ要素のレイアウトパターン。
**ディレクティブ:** `ngGrid``ngGridRow``ngGridCell``ngGridCellWidget`
```html
<table ngGrid [multi]="true" [enableSelection]="true" class="grid-table">
<tr ngGridRow>
<th ngGridCell role="columnheader">Name</th>
<th ngGridCell role="columnheader">Status</th>
</tr>
<tr ngGridRow>
<td ngGridCell>Project A</td>
<td ngGridCell [(selected)]="isSelected">
<button ngGridCellWidget (activated)="onActivate()">Active</button>
</td>
</tr>
</table>
```
**スタイリング戦略:**
選択されたセルには `[aria-selected="true"]`、アクティブなセルには `:focus-visible`roving tabindexまたは コンテナの `[aria-activedescendant]` をターゲットにします。
```css
.grid-table {
border-collapse: collapse;
}
[ngGridCell] {
padding: 8px;
border: 1px solid #ddd;
}
[ngGridCell][aria-selected='true'] {
background: #e3f2fd;
}
/* フォーカス状態はroving tabindexで管理されます */
[ngGridCell]:focus-visible {
outline: 2px solid #2196f3;
outline-offset: -2px;
}
```
## エージェントへの一般的なルール
1. **これらの特定のAriaパターンを実装する際は、`<select>` などのネイティブHTML要素を使用しないでください**`ng*` ディレクティブを使用してください。
2. **CSSは手動で処理してください**: `Angular Aria` はスタイルを提供しません。ディレクティブが自動的に切り替えるネイティブARIA属性`aria-expanded``aria-selected` などをターゲットにしたCSSを記述する必要があります。
3. **遅延ロード**: 重いコンテンツパネルの遅延レンダリングを確保するために、`ng-template` 内で提供されている構造ディレクティブ(`ngAccordionContent``ngTabContent`)を常に使用してください。

View File

@@ -0,0 +1,86 @@
# エージェント向け Angular CLI ガイド
Angular CLI`ng`)は Angular ワークスペースを管理するための主要ツールです。プロジェクト構造を変更したり Angular 固有の依存関係を追加したりする際は、手動でのファイル作成や汎用の `npm` コマンドよりも、常に CLI コマンドを優先して使用してください。
## 1. 依存関係の管理
**Angular ライブラリには `npm install` ではなく必ず `ng add` を使用してください。** `ng add` はパッケージのインストールに加え、初期化スキーマティクス(例:`angular.json` の設定、ルートプロバイダーの更新)も実行します。
```bash
ng add @angular/material
ng add tailwindcss
ng add @angular/fire
```
アプリケーションとその依存関係を更新するには(コードマイグレーションが自動的に実行されます):
```bash
ng update @angular/core@<latest or specific version> @angular/cli<latest or specific version>
```
## 2. コード生成(`ng generate` または `ng g`
Angular の規約に準拠し、必要な設定ファイルが自動的に更新されるよう、コード生成には必ず CLI を使用してください。
| 対象 | コマンド | 備考 |
| :------------- | :-------------------- | :--------------------------------------------------------------------------------------------- |
| コンポーネント | `ng g c path/to/name` | コンポーネントを生成します。要求に応じて `--inline-style``-s`)または `--inline-template``-t`)を使用してください。 |
| サービス | `ng g s path/to/name` | `@Injectable({providedIn: 'root'})` サービスを生成します。 |
| ディレクティブ | `ng g d path/to/name` | ディレクティブを生成します。 |
| パイプ | `ng g p path/to/name` | パイプを生成します。 |
| ガード | `ng g g path/to/name` | 関数型ルートガードを生成します。 |
| 環境設定 | `ng g environments` | `src/environments/` を生成し、ファイル置換を含む `angular.json` を更新します。 |
_注意:単一のルート定義を生成するコマンドはありません。コンポーネントを生成した後、`app.routes.ts` 内の `Routes` 配列に手動で追加してください。_
## 3. 開発サーバーとプロキシ
ホットモジュール置換HMRを使用してローカル開発サーバーを起動します
```bash
ng serve
```
### バックエンド API プロキシ
開発中に API リクエストをプロキシするには(例:`/api` をローカルの Node サーバーにリルーティング):
1. `src/proxy.conf.json` を作成します:
```json
{
"/api/**": {"target": "http://localhost:3000", "secure": false}
}
```
2. `angular.json` の `serve` ターゲット以下を更新します:
```json
"serve": {
"builder": "@angular/build:dev-server",
"options": { "proxyConfig": "src/proxy.conf.json" }
}
```
## 4. アプリケーションのビルド
アプリケーションを出力ディレクトリ(デフォルト:`dist/<project-name>/browser`)にコンパイルします。最新の Angular は esbuild ベースの `@angular/build:application` ビルダーを使用します。
```bash
ng build
```
- `ng build` はデフォルトでプロダクション設定を使用し、Ahead-of-TimeAOTコンパイル、ミニファイ、ツリーシェイキングを有効にします。
- `--configuration` オプションを使用して `angular.json` で定義された特定の設定を対象にできます:`ng build --configuration=staging`。
## 5. テスト
- **ユニットテスト**設定されたテストランナーKarma または Vitestでユニットテストを実行するには `ng test` を実行します。
- **エンドツーエンドE2Eテスト**`ng e2e` を実行します。E2E フレームワークが設定されていない場合、CLI がインストールを促しますCypress、Playwright、Puppeteer など)。
## 6. デプロイ
アプリケーションをデプロイするには、まずデプロイメントビルダーを追加してからデプロイコマンドを実行します:
```bash
# Firebase の例
ng add @angular/fire
ng deploy
```

View File

@@ -0,0 +1,59 @@
# コンポーネントハーネスを使用したテスト
コンポーネントハーネスは、テストでコンポーネントを操作するための標準的かつ推奨される方法です。コンポーネントの内部 DOM 構造の変更からテストを保護することで、壊れにくく読みやすいテストを実現するユーザー中心の API を提供します。
## なぜハーネスを使用するのか?
- **堅牢性:** コンポーネントの内部 HTML や CSS クラスをリファクタリングしてもテストが壊れません。
- **可読性:** テストは DOM クエリ(`fixture.nativeElement.querySelector(...)`)を通じてではなく、ユーザーの観点からのインタラクション(例:`button.click()``slider.getValue()`)を記述します。
- **再利用性:** 同じハーネスをユニットテストと E2E テストの両方で使用できます。
Angular Material はライブラリ内のすべてのコンポーネントにテストハーネスを提供しています。
## ユニットテストでのハーネスの使用
`TestbedHarnessEnvironment` はユニットテストでハーネスを使用するためのエントリーポイントです。
### 例:`MatButtonHarness` を使用したテスト
```ts
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
import {MatButtonHarness} from '@angular/material/button/testing';
import {MyButtonContainerComponent} from './my-button-container.component';
describe('MyButtonContainerComponent', () => {
let fixture: ComponentFixture<MyButtonContainerComponent>;
let loader: HarnessLoader;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MyButtonContainerComponent, MatButtonModule],
}).compileComponents();
fixture = TestBed.createComponent(MyButtonContainerComponent);
// コンポーネントのフィクスチャ用のハーネスローダーを作成する
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should find a button with specific text', async () => {
// "Submit" というテキストを持つ MatButton のハーネスをロードする
const submitButton = await loader.getHarness(MatButtonHarness.with({text: 'Submit'}));
// ハーネス API を使用してコンポーネントを操作する
expect(await submitButton.isDisabled()).toBe(false);
await submitButton.click();
// ... アサーション
});
});
```
### 主要なコンセプト
1. **`HarnessLoader`**:ハーネスインスタンスを検索して作成するためのオブジェクトです。`TestbedHarnessEnvironment.loader(fixture)` を使用してコンポーネントのフィクスチャ用のローダーを取得します。
2. **`loader.getHarness(HarnessClass)`**:最初にマッチするコンポーネントのハーネスインスタンスを非同期で検索して返します。
3. **`HarnessClass.with({ ... })`**:多くのハーネスは静的な `with` メソッドを提供し、`HarnessPredicate` を返します。これにより、テキスト、セレクター、無効状態などのプロパティに基づいてコンポーネントをフィルタリングして検索できます。テストしたいコンポーネントを正確に対象にするために常にこれを使用してください。
4. **ハーネス API** ハーネスインスタンスを取得したら、そのメソッド(例:`.click()``.getText()``.getValue()`)を使用してコンポーネントを操作します。これらのメソッドは非同期操作と変更検出の待機を自動的に処理します。

View File

@@ -0,0 +1,91 @@
# コンポーネントスタイリング
Angular コンポーネントは、カプセル化とモジュール性を実現するために、テンプレートに特定のスタイルを定義できます。
## スタイルの定義
スタイルはインラインまたは別ファイルで定義できます。
```ts
@Component({
selector: 'app-photo',
// インラインスタイル
styles: `
img {
border-radius: 50%;
}
`,
// または外部ファイル
styleUrl: 'photo.component.css',
})
export class Photo {}
```
## ビューエンカプセレーション
すべてのコンポーネントには、スタイルのスコープを決定するビューエンカプセレーション設定があります。
| モード | 動作 |
| :------------------------------ | :-------------------------------------------------------------------------------------------- |
| `Emulated`(デフォルト) | 一意の HTML 属性を使用してスタイルをコンポーネントにスコープします。グローバルスタイルは引き続き影響する可能性があります。 |
| `ShadowDom` | ブラウザのネイティブ Shadow DOM API を使用してスタイルを完全に分離します。 |
| `None` | カプセル化を無効にします。コンポーネントスタイルはグローバルになります。 |
| `ExperimentalIsolatedShadowDom` | コンポーネントのスタイルのみが適用されることを厳密に保証します。 |
### 使用方法
```ts
import { ViewEncapsulation } from '@angular/core';
@Component({
...,
encapsulation: ViewEncapsulation.None,
})
export class GlobalStyled {}
```
## 特殊セレクター
### `:host`
コンポーネントのホスト要素(コンポーネントのセレクターに一致する要素)を対象にします。
```css
:host {
display: block;
border: 1px solid black;
}
```
### `:host-context()`
先祖の何らかの条件に基づいてホスト要素を対象にします。
```css
/* 先祖に 'theme-dark' クラスがある場合にスタイルを適用する */
:host-context(.theme-dark) {
background-color: #333;
}
```
### `::ng-deep`
特定のルールのビューエンカプセレーションを無効にし、子コンポーネントに「漏れ」させます。
**注意Angular チームは `::ng-deep` の使用を強く推奨しません。** これは後方互換性のためにのみサポートされています。
## テンプレート内のスタイル
コンポーネントのテンプレートで直接 `<style>` 要素を使用できます。ビューエンカプセレーションのルールは引き続き適用されます。
```html
<style>
.dynamic-class {
color: red;
}
</style>
<div class="dynamic-class">Hello</div>
```
## 外部スタイル
CSS での `<link>``@import` の使用は外部スタイルとして扱われます。**外部スタイルはエミュレートされたビューエンカプセレーションの影響を受けません。**

View File

@@ -0,0 +1,117 @@
# コンポーネント
Angular コンポーネントはアプリケーションの基本的な構成要素です。各コンポーネントは、振る舞いを持つ TypeScript クラス、HTML テンプレート、CSS セレクターで構成されます。
## コンポーネントの定義
`@Component` デコレーターを使用してコンポーネントのメタデータを定義します。
```ts
@Component({
selector: 'app-profile',
template: `
<img src="profile.jpg" alt="Profile photo" />
<button (click)="save()">Save</button>
`,
styles: `
img {
border-radius: 50%;
}
`,
})
export class Profile {
save() {
/* ... */
}
}
```
## メタデータオプション
- `selector`:テンプレート内でこのコンポーネントを識別する CSS セレクター。
- `template`:インライン HTML テンプレート(小さなテンプレートに推奨)。
- `templateUrl`:外部 HTML ファイルへのパス。
- `styles`:インライン CSS スタイル。
- `styleUrl` / `styleUrls`:外部 CSS ファイルへのパス(複数可)。
- `imports`:このコンポーネントのテンプレートで使用されるコンポーネント、ディレクティブ、パイプのリスト。
## コンポーネントの使用
コンポーネントを使用するには、利用側コンポーネントの `imports` 配列に追加し、テンプレートでセレクターを使用します。
```ts
@Component({
selector: 'app-root',
imports: [Profile],
template: `<app-profile />`,
})
export class App {}
```
## テンプレート制御フロー
Angular は条件レンダリングとループに組み込みブロックを使用します。
### 条件レンダリング(`@if`
コンテンツを条件付きで表示するには `@if` を使用します。`@else if``@else` ブロックを含めることができます。
```html
@if (user.isAdmin) {
<admin-dashboard />
} @else if (user.isModerator) {
<mod-dashboard />
} @else {
<standard-dashboard />
}
```
**結果のエイリアス**:式の結果を保存して再利用できます。
```html
@if (user.settings(); as settings) {
<p>Theme: {{ settings.theme }}</p>
}
```
### ループ(`@for`
`@for` ブロックはコレクションを反復処理します。`track` 式はパフォーマンスと DOM 再利用のために**必須**です。
```html
<ul>
@for (item of items(); track item.id; let i = $index, total = $count) {
<li>{{ i + 1 }}/{{ total }}: {{ item.name }}</li>
} @empty {
<li>No items to display.</li>
}
</ul>
```
**暗黙的変数**`$index``$count``$first``$last``$even``$odd`
### コンテンツの切り替え(`@switch`
`@switch` ブロックは値に基づいてコンテンツをレンダリングします。厳密等価(`===`)を使用し、**フォールスルーはありません**。
```html
@switch (status()) { @case ('loading') { <app-spinner /> } @case ('error') { <app-error-msg /> }
@case ('success') { <app-data-grid /> } @default {
<p>Unknown status</p>
} }
```
**網羅的型チェック**`@default never;` を使用して、ユニオン型のすべてのケースが処理されることを確認します。
```html
@switch (state) { @case ('on') { ... } @case ('off') { ... } @default never; // 'standby' のような新しい
// 状態が追加された場合にエラーになる }
```
## 核心的コンセプト
- **ホスト要素**:コンポーネントのセレクターに一致する DOM 要素。
- **ビュー**:ホスト要素内のコンポーネントのテンプレートによってレンダリングされた DOM。
- **スタンドアロン**デフォルトでコンポーネントはスタンドアロンですAngular 19 以降、`standalone: true` がデフォルト)。古いバージョンでは `standalone: true` を明示するか、コンポーネントを `NgModule` の一部にする必要があります。
- **コンポーネントツリー**Angular アプリケーションはコンポーネントのツリーとして構成され、各コンポーネントは子コンポーネントをホストできます。
- **コンポーネントの命名**:プロジェクトがその命名設定を使用するように構成されていない限り、コンポーネントクラスに `Component` サフィックスを追加しないでくださいAppComponent

View File

@@ -0,0 +1,97 @@
# サービスの作成と使用
Angular のサービスは、複数のコンポーネントや他のサービスがアクセスする必要があるデータフェッチ、ビジネスロジック、または状態管理を扱う再利用可能なコードです。
## サービスの作成
Angular CLI を使用してサービスを生成できます:
```bash
ng generate service my-data
```
または、TypeScript クラスを手動で作成して `@Injectable()` でデコレートすることもできます。
```ts
import {Injectable} from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class BasicDataStore {
private data: string[] = [];
addData(item: string): void {
this.data.push(item);
}
getData(): string[] {
return [...this.data];
}
}
```
### `providedIn: 'root'` オプション
ほとんどのサービスには `providedIn: 'root'` の使用が推奨されます。これにより Angular は以下を行います:
- アプリケーション全体に対して**シングルインスタンス(シングルトン)を作成**します。
- `providers` 配列に列挙しなくても**どこからでも自動的に利用可能**にします。
- **ツリーシェイキングを有効**にし、サービスが実際にどこかで注入されている場合にのみ最終的な JavaScript バンドルに含まれるようにします。
## サービスの注入
サービスを作成したら、`inject()` 関数を使用してコンポーネント、ディレクティブ、または他のサービスに注入できます。
### コンポーネントへの注入
```ts
import {Component, inject} from '@angular/core';
import {BasicDataStore} from './basic-data-store.service';
@Component({
selector: 'app-example',
template: `
<div>
<p>Data items: {{ dataStore.getData().length }}</p>
<button (click)="dataStore.addData('New Item')">Add Item</button>
</div>
`,
})
export class Example {
// サービスをクラスフィールドとして注入する
dataStore = inject(BasicDataStore);
}
```
### 別のサービスへの注入
サービスはまったく同じ方法で他のサービスを注入できます。
```ts
import {Injectable, inject} from '@angular/core';
import {AdvancedDataStore} from './advanced-data-store.service';
@Injectable({
providedIn: 'root',
})
export class BasicDataStore {
// 別のサービスを注入する
private advancedDataStore = inject(AdvancedDataStore);
private data: string[] = [];
getData(): string[] {
// このサービスと注入されたサービスのデータを結合する
return [...this.data, ...this.advancedDataStore.getData()];
}
}
```
## 高度なサービスパターン
`providedIn: 'root'` がほとんどのシナリオをカバーしていますが、以下のような場合に他の方法が必要になることがあります:
- **コンポーネント固有のインスタンス**:コンポーネントがサービスの独立したインスタンスを必要とする場合、コンポーネントの `@Component({ providers: [MyService] })` 配列で直接提供します。
- **ファクトリープロバイダー**:動的な作成のため。
- **値プロバイダー**:設定オブジェクトを注入するため。

View File

@@ -0,0 +1,69 @@
# データリゾルバー
データリゾルバーはルートがアクティブになる前にデータをフェッチし、コンポーネントがレンダリング時に必要なデータを持っていることを保証します。
## リゾルバーの作成
`ResolveFn` 型を実装します。
```ts
export const userResolver: ResolveFn<User> = (route, state) => {
const userService = inject(UserService);
const id = route.paramMap.get('id')!;
return userService.getUser(id);
};
```
## ルートの設定
`resolve` キーの下にリゾルバーを追加します。
```ts
{
path: 'user/:id',
component: UserProfile,
resolve: {
user: userResolver
}
}
```
## 解決されたデータへのアクセス
### 1. `ActivatedRoute` 経由(従来の方法)
```ts
private route = inject(ActivatedRoute);
data = toSignal(this.route.data);
user = computed(() => this.data().user);
```
### 2. コンポーネント入力経由(モダンな方法)
`provideRouter``withComponentInputBinding()` を有効にすると、解決されたデータを `@Input` または `input()` に直接渡せます。
```ts
// app.config.ts
provideRouter(routes, withComponentInputBinding());
// component.ts
user = input.required<User>();
```
## エラーハンドリング
リゾルバーが失敗するとナビゲーションがブロックされます。
- グローバルな処理には `withNavigationErrorHandler` を使用します。
- リゾルバー内で `catchError` を使用して `RedirectCommand` やフォールバックデータを返します。
```ts
return userService
.get(id)
.pipe(catchError(() => of(new RedirectCommand(router.parseUrl('/error')))));
```
## ベストプラクティス
- **軽量に保つ**:重要なデータのみをフェッチします。
- **フィードバックを提供する**:リゾルバーが完了するまで UI は古いページに留まるため、ナビゲーション中にグローバルなローディングバーを表示するためにルーターイベントをリッスンします。

View File

@@ -0,0 +1,67 @@
# ルートの定義
ルートは特定の URL パスに対してどのコンポーネントをレンダリングするかを定義するオブジェクトです。
## 基本設定
`Routes` 配列にルートを定義し、`appConfig``provideRouter` を使用して提供します。
```ts
// app.routes.ts
export const routes: Routes = [
{path: '', component: HomePage},
{path: 'admin', component: AdminPage},
];
// app.config.ts
export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes)],
};
```
## URL パス
- **静的**:完全な文字列に一致します(例:`'admin'`)。
- **ルートパラメーター**:コロンが前置された動的セグメント(例:`'user/:id'`)。
- **ワイルドカード**`**` を使用して任意の URL に一致します。「見つかりません」ページに有用です。**常に配列の最後に配置してください。**
## マッチング戦略
Angular は**先勝ち**戦略を使用します。具体的なルートは具体性の低いルートより前に記述する必要があります。
## リダイレクト
`redirectTo` を使用して一つのパスを別のパスに向けます。
```ts
{ path: 'articles', redirectTo: '/blog' },
{ path: 'blog', component: Blog },
```
## ページタイトル
アクセシビリティのためにルートにタイトルを関連付けます。タイトルは静的または動的(`ResolveFn` またはカスタム `TitleStrategy` 経由)にできます。
```ts
{ path: 'home', component: Home, title: 'Home Page' }
```
## ルートデータとプロバイダー
- **静的データ**`data` プロパティを使用してメタデータを付加します。
- **ルートプロバイダー**`providers` 配列を使用して特定のルートとその子に依存関係をスコープします。
## ネスト(子)ルート
`children` プロパティを使用してサブビューを定義します。親コンポーネントには `<router-outlet />` が必要です。
```ts
{
path: 'product/:id',
component: Product,
children: [
{ path: 'info', component: ProductInfo },
{ path: 'reviews', component: ProductReviews },
],
}
```

View File

@@ -0,0 +1,72 @@
# 依存性プロバイダーの定義
Angular は依存性注入DIシステムに依存関係を提供する自動的な方法と手動の方法を提供します。
## 自動プロビジョン
サービスを提供する最も一般的な方法は、`@Injectable()``providedIn: 'root'` を使用することです。
### InjectionToken
非クラスの依存関係(設定オブジェクト、関数、プリミティブ)には `InjectionToken` を使用します。`InjectionToken` は自動的に提供することもできます。
```ts
import {InjectionToken} from '@angular/core';
export interface AppConfig {
apiUrl: string;
}
export const APP_CONFIG = new InjectionToken<AppConfig>('app.config', {
providedIn: 'root',
factory: () => ({apiUrl: 'https://api.example.com'}),
});
```
## 手動プロビジョン
`providedIn` のないサービス、特定のコンポーネント用の新しいインスタンスが必要な場合、またはランタイム値を設定する場合に `providers` 配列を使用します。
```ts
@Component({
providers: [
// { provide: LocalService, useClass: LocalService } の省略形
LocalService,
// useClass: 実装を切り替える
{provide: Logger, useClass: BetterLogger},
// useValue: 静的な値を提供する
{provide: API_URL_TOKEN, useValue: 'https://api.example.com'},
// useFactory: 値を動的に生成する
{
provide: ApiClient,
useFactory: (http = inject(HttpClient)) => new ApiClient(http),
},
// useExisting: エイリアスを作成する
{provide: OldLogger, useExisting: NewLogger},
// multi: 同じトークンに複数の値を配列として提供する
{provide: INTERCEPTOR_TOKEN, useClass: AuthInterceptor, multi: true},
],
})
export class Example {}
```
## プロバイダーのスコープ
- **アプリケーションブートストラップ**グローバルシングルトン。HTTP クライアント、ロギング、アプリ全体の設定に使用します。
- **コンポーネント/ディレクティブ**:分離されたインスタンス。コンポーネント固有の状態やフォームに使用します。サービスはコンポーネントが破棄されると破棄されます。
- **ルート**:特定のルートでのみロードされる機能固有のサービス。
## ライブラリパターン:`provide*` 関数
ライブラリ作者は設定をカプセル化するためにプロバイダー配列を返す関数をエクスポートする必要があります:
```ts
export function provideAnalytics(config: AnalyticsConfig): Provider[] {
return [{provide: ANALYTICS_CONFIG, useValue: config}, AnalyticsService];
}
```

View File

@@ -0,0 +1,120 @@
# 依存性注入DIの基礎
依存性注入DIは、アプリケーションの異なる部分に機能を「注入」することで、コードを整理して共有するための設計パターンです。これにより、コードの保守性、スケーラビリティ、テスト容易性が向上します。
## Angular における DI の仕組み
コードが Angular の DI システムと相互作用する主な方法が 2 つあります:
1. **プロビジョン(提供)**:値(オブジェクト、関数、プリミティブ)を DI システムで利用可能にする。
2. **インジェクション(注入)**DI システムにそれらの値を要求する。
Angular のコンポーネント、ディレクティブ、サービスは自動的に DI に参加します。
## サービス
**サービス**はアプリケーション全体でデータと機能を共有する最も一般的な方法です。`@Injectable()` でデコレートされた TypeScript クラスです。
### サービスの作成
`@Injectable` デコレーターで `providedIn: 'root'` オプションを使用すると、アプリケーション全体で利用可能なシングルトンサービスになります。これはほとんどのサービスに推奨されるアプローチです。
```ts
import {Injectable} from '@angular/core';
@Injectable({
providedIn: 'root', // どこでも利用可能なシングルトンにする
})
export class AnalyticsLogger {
trackEvent(category: string, value: string) {
console.log('Analytics event logged:', {category, value});
}
}
```
サービスの一般的な用途:
- データクライアントAPI 呼び出し)
- 状態管理
- 認証と認可
- ロギングとエラーハンドリング
- ユーティリティ関数
## 依存関係の注入
依存関係を要求するには Angular の `inject()` 関数を使用します。
### `inject()` 関数
`inject()` 関数を使用してサービス(または提供された他のトークン)のインスタンスを取得できます。
```ts
import {Component, inject} from '@angular/core';
import {Router} from '@angular/router';
import {AnalyticsLogger} from './analytics-logger.service';
@Component({
selector: 'app-navbar',
template: `<a href="#" (click)="navigateToDetail($event)">Detail Page</a>`,
})
export class Navbar {
// クラスフィールド初期化子を使用して依存関係を注入する
private router = inject(Router);
private analytics = inject(AnalyticsLogger);
navigateToDetail(event: Event) {
event.preventDefault();
this.analytics.trackEvent('navigation', '/details');
this.router.navigate(['/details']);
}
}
```
### `inject()` はどこで使用できるか?(インジェクションコンテキスト)
`inject()` は**インジェクションコンテキスト**内でコードが実行されている場合に呼び出せます。最も一般的なインジェクションコンテキストは、コンポーネント、ディレクティブ、またはサービスの構築時です。
`inject()` を呼び出せる有効な場所:
1. **クラスフィールド初期化子**(推奨)
2. **コンストラクター本体**
3. **ルートガードとリゾルバー**(インジェクションコンテキスト内で実行される)
4. プロバイダーで使用される**ファクトリー関数**
```typescript
import {Component, Directive, Injectable, inject, ElementRef} from '@angular/core';
import {HttpClient} from '@angular/common/http';
// 1. コンポーネント内(フィールド初期化子とコンストラクター)
@Component({
/*...*/
})
export class Example {
private service1 = inject(MyService); // 有効なフィールド初期化子
private service2: MyService;
constructor() {
this.service2 = inject(MyService); // 有効なコンストラクター本体
}
}
// 2. ディレクティブ内
@Directive({
/*...*/
})
export class MyDirective {
private element = inject(ElementRef); // 有効なフィールド初期化子
}
// 3. サービス内
@Injectable({providedIn: 'root'})
export class MyService {
private http = inject(HttpClient); // 有効なフィールド初期化子
}
// 4. ルートガード(関数型)内
export const authGuard = () => {
const auth = inject(AuthService); // 有効なルートガード
return auth.isAuthenticated();
};
```

View File

@@ -0,0 +1,56 @@
# エンドツーエンドE2Eテスト
実際のブラウザでの重要なユーザージャーニーをカバーするために E2E テストを使用します。Cypress や Playwright など、Angular ワークスペースですでに設定されているフレームワークを優先してください。
## E2E テストの実行
プロジェクト固有のコマンドについては `package.json``angular.json` を確認してください。一般的なパターンには以下があります:
```shell
npm run e2e
pnpm e2e
ng e2e
```
アプリをビルドまたはサーブする必要がある場合は、並列テストエントリポイントを新たに作成するのではなく、既存のプロジェクトスクリプトを使用してください。
## テスト構造
- E2E スペックは `cypress/e2e/``e2e/` など、設定されたテストフレームワークに近い場所に保管してください。
- 再利用可能なログイン/セットアップヘルパーはフレームワークのサポートディレクトリに配置してください。
- フィクスチャは明示的に小さくして、各テストが依存するユーザー状態を説明できるようにしてください。
### Cypress の例
```typescript
describe('Login flow', () => {
it('redirects to dashboard on valid credentials', () => {
cy.visit('/login');
cy.get('[data-cy=email]').type('user@example.com');
cy.get('[data-cy=password]').type('password123');
cy.get('[data-cy=submit]').click();
cy.url().should('include', '/dashboard');
});
});
```
### Playwright の例
```typescript
import {expect, test} from '@playwright/test';
test('redirects to dashboard on valid credentials', async ({page}) => {
await page.goto('/login');
await page.getByLabel('Email').fill('user@example.com');
await page.getByLabel('Password').fill('password123');
await page.getByRole('button', {name: 'Sign in'}).click();
await expect(page).toHaveURL(/dashboard/);
});
```
## ベストプラクティス
- アクセシブルなロケーター(`getByRole``getByLabel`)または安定した `data-*` 属性を優先してください。
- CSS クラス、DOM の深さ、または偶発的なテキストに依存するセレクターは避けてください。
- 任意のスリープではなく、特定の UI 状態、ルート、またはネットワークレスポンスを待機してください。
- スモークテストは短く保ち、完全なワークフローカバレッジは最も価値の高いパスに限定してください。

View File

@@ -0,0 +1,83 @@
# `effect` と `afterRenderEffect` によるサイドエフェクト
Angularにおける**エフェクト**とは、追跡している1つ以上のシグナル値が変化するたびに実行される処理です。
## `effect` を使うべき場面
エフェクトは、シグナルの状態を命令的な非シグナルAPIに同期させるために使います。
**有効なユースケース:**
- アナリティクスのログ記録。
- `localStorage``sessionStorage` への状態の同期。
- `<canvas>` やサードパーティのチャートライブラリへのカスタムレンダリングの実行。
**重要なルール: 状態の伝播にエフェクトを使わないこと。**
2つのシグナルを同期させるためにエフェクト内でシグナルの `.set()``.update()` を呼び出している場合、それは誤りです。`ExpressionChangedAfterItHasBeenChecked` エラーや無限ループを引き起こします。**状態の派生には常に `computed()` または `linkedSignal()` を使用してください。**
## 基本的な使い方
エフェクトは変更検出プロセス中に非同期で実行されます。常に少なくとも1回は実行されます。
```ts
import { Component, signal, effect } from '@angular/core';
@Component({...})
export class Example {
count = signal(0);
constructor() {
// エフェクトはインジェクションコンテキスト(例: コンストラクター)内で作成する必要があります
effect((onCleanup) => {
console.log(`Count changed to ${this.count()}`);
const timer = setTimeout(() => console.log('Timer finished'), 1000);
// クリーンアップ関数は次回実行前または破棄時に実行されます
onCleanup(() => clearTimeout(timer));
});
}
}
```
## `afterRenderEffect` によるDOM操作
標準の `effect` はAngularがDOMを更新する_前_に実行されます。シグナルの変化に基づいてDOMを手動で検査または変更する必要がある場合例: サードパーティUIライブラリの統合は、`afterRenderEffect` を使用してください。
`afterRenderEffect` はAngularがDOMのレンダリングを完了した後に実行されます。
### レンダーフェーズ
リフロー(強制レイアウトスラッシング)を防ぐため、`afterRenderEffect` はDOMの読み取りと書き込みを特定のフェーズに分割することを強制します。
```ts
import { Component, afterRenderEffect, viewChild, ElementRef } from '@angular/core';
@Component({...})
export class Chart {
canvas = viewChild.required<ElementRef>('canvas');
constructor() {
afterRenderEffect({
// 1. DOMから読み取る
earlyRead: () => {
return this.canvas().nativeElement.getBoundingClientRect().width;
},
// 2. DOMに書き込む前フェーズの結果を受け取る
write: (width) => {
// writeフェーズではDOMを読み取らないこと。
setupChart(this.canvas().nativeElement, width);
}
});
}
}
```
**利用可能なフェーズ(この順序で実行されます):**
1. `earlyRead`
2. `write`(ここでは読み取らないこと)
3. `mixedReadWrite`(可能な限り避けること)
4. `read`(ここでは書き込まないこと)
_注意: `afterRenderEffect` はクライアントでのみ実行され、サーバーサイドレンダリングSSR中は実行されません。_

View File

@@ -0,0 +1,43 @@
# 階層的インジェクター
Angularの依存性注入システムは階層的であり、サービスをアプリケーションの異なるレベルにスコープできます。
## インジェクター階層の種類
1. **`EnvironmentInjector` 階層**: `@Injectable({ providedIn: 'root' })` またはブートストラップ時の `ApplicationConfig.providers` で設定されます。これらはグローバルシングルトンです。
2. **`ElementInjector` 階層**: 各DOM要素で暗黙的に作成されます。`@Component()` または `@Directive()``providers` または `viewProviders` 配列で設定されます。
## 解決ルール
依存関係が要求されると、Angularは2つのフェーズで解決します:
1. リクエスト元のコンポーネント/ディレクティブからルート要素まで、**`ElementInjector`** ツリーを上方向に検索します。
2. 見つからない場合、最も近い環境インジェクターからルートまで、**`EnvironmentInjector`** ツリーを検索します。
3. それでも見つからない場合、エラーをスローします(オプションとしてマークされている場合を除く)。
## 解決モディファイアー
`inject()` のオプションオブジェクトを使用して、Angularが依存関係を検索する方法を変更できます:
- **`optional`**: 依存関係が見つからない場合、エラーをスローする代わりに `null` を返します。
- **`self`**: 現在の `ElementInjector` のみをチェックします。親ツリーを検索しません。
- **`skipSelf`**: 現在の要素をスキップして、親の `ElementInjector` から検索を開始します。
- **`host`**: ホストコンポーネントのビュー境界に達したら検索を停止します。
```ts
@Component({...})
export class Example {
// 見つからない場合はクラッシュせずnullを返す
optionalService = inject(MyService, { optional: true });
// このコンポーネントのプロバイダーをスキップして親を参照する
parentService = inject(ParentService, { skipSelf: true });
}
```
## `providers` と `viewProviders`
コンポーネントレベルでサービスを提供する場合:
- **`providers`**: サービスはコンポーネント、そのビュー(テンプレート)、および**プロジェクトされたコンテンツ**`<ng-content>`)で利用可能です。
- **`viewProviders`**: サービスはコンポーネントとそのビューで利用可能ですが、プロジェクトされたコンテンツからは**利用できません**。コンシューマーから渡されたコンテンツからサービスを分離するために使用します。

View File

@@ -0,0 +1,80 @@
# コンポーネントのホスト要素
**ホスト要素**とは、コンポーネントのセレクターに一致するDOM要素です。コンポーネントのテンプレートはこの要素の内部にレンダリングされます。
## ホスト要素へのバインディング
`@Component` デコレーターの `host` プロパティを使用して、プロパティ、属性、スタイル、イベントをホスト要素にバインドします。これはレガシーデコレーターより**推奨されるアプローチ**です。
```ts
@Component({
selector: 'custom-slider',
host: {
'role': 'slider', // 静的属性
'[attr.aria-valuenow]': 'value', // 属性バインディング
'[class.active]': 'isActive()', // クラスバインディング
'[style.color]': 'color()', // スタイルバインディング
'[tabIndex]': 'disabled ? -1 : 0', // プロパティバインディング
'(keydown)': 'onKeyDown($event)', // イベントバインディング
},
})
export class CustomSlider {
value = 0;
disabled = false;
isActive = signal(false);
color = signal('blue');
onKeyDown(event: KeyboardEvent) {
/* ... */
}
}
```
## レガシーデコレーター
`@HostBinding``@HostListener` は後方互換性のためにサポートされていますが、新しいコードでは使用を避けてください。
```ts
export class CustomSlider {
@HostBinding('tabIndex')
get tabIndex() {
return this.disabled ? -1 : 0;
}
@HostListener('keydown', ['$event'])
onKeyDown(event: KeyboardEvent) {
/* ... */
}
}
```
## バインディングの競合
コンポーネント(ホストバインディング)とコンシューマー(テンプレートバインディング)の両方が同じプロパティにバインドする場合:
1. **静的 vs 静的**: インスタンス(コンシューマー)のバインディングが優先されます。
2. **静的 vs 動的**: 動的バインディングが優先されます。
3. **動的 vs 動的**: コンポーネントのホストバインディングが優先されます。
## ホスト属性のインジェクト
`inject` 関数と `HostAttributeToken` を使用して、構築時にホスト要素から静的属性を読み取ります。
```ts
import {Component, HostAttributeToken, inject} from '@angular/core';
@Component({
selector: 'app-btn',
template: `<ng-content />`,
})
export class AppButton {
// `{ optional: true }` でインジェクトしない限り、'type'がない場合エラーをスローします
type = inject(new HostAttributeToken('type'));
}
```
使用例:
```html
<app-btn type="primary">Click Me</app-btn>
```

View File

@@ -0,0 +1,63 @@
# インジェクションコンテキスト
`inject()` 関数はコードが**インジェクションコンテキスト**内で実行されている場合にのみ使用できます。
## インジェクションコンテキストが利用可能な場所
インジェクションコンテキストは以下の場所で自動的に利用可能です:
1. DI によってインスタンス化されるクラス(`@Injectable``@Component``@Directive``@Pipe`)の**フィールド初期化子**。
2. DI によってインスタンス化されるクラスの**コンストラクター**。
3. `useFactory` または `InjectionToken` 設定で指定された**ファクトリー関数**。
4. Angular によって実行される**関数型 API**(例:関数型ルートガード、リゾルバー、インターセプター)。
```ts
@Component({...})
export class Example {
// 有効:フィールド初期化子
private router = inject(Router);
constructor() {
// 有効:コンストラクター
const http = inject(HttpClient);
}
onClick() {
// 無効:インジェクションコンテキストではない
// const auth = inject(AuthService);
}
}
```
## `runInInjectionContext`
インジェクションコンテキスト内で関数を実行する必要がある場合(動的コンポーネントの作成やテストでよく必要になります)、`runInInjectionContext` を使用します。これには既存のインジェクター(`EnvironmentInjector` または `Injector` など)へのアクセスが必要です。
```ts
import {Injectable, inject, EnvironmentInjector, runInInjectionContext} from '@angular/core';
@Injectable({providedIn: 'root'})
export class MyService {
private injector = inject(EnvironmentInjector);
doSomethingDynamic() {
runInInjectionContext(this.injector, () => {
// ここで inject() を使用することが有効になる
const router = inject(Router);
});
}
}
```
## `assertInInjectionContext`
ユーティリティ関数が有効なコンテキストから呼び出されることを保証するために `assertInInjectionContext` を使用します。そうでない場合は明確なエラーをスローします。
```ts
import {assertInInjectionContext, inject, ElementRef} from '@angular/core';
export function injectNativeElement<T extends Element>(): T {
assertInInjectionContext(injectNativeElement);
return inject(ElementRef).nativeElement;
}
```

View File

@@ -0,0 +1,101 @@
# 入力Inputs
入力により、親コンポーネントから子コンポーネントにデータを流すことができます。Angular はモダンなアプリケーションにはシグナルベースの `input` API の使用を推奨しています。
## シグナルベースの入力
`input()` 関数を使用して入力を宣言します。これは `InputSignal` を返します。
```ts
import {Component, input, computed} from '@angular/core';
@Component({
selector: 'app-user',
template: `<p>User: {{ name() }} ({{ age() }})</p>`,
})
export class User {
// デフォルト値を持つオプションの入力
name = input('Guest');
// 必須の入力
age = input.required<number>();
// 入力はリアクティブなシグナル
label = computed(() => `Name: ${this.name()}`);
}
```
### テンプレートでの使用
```html
<app-user [name]="userName" [age]="25" />
```
## 設定オプション
`input` 関数は設定オブジェクトを受け取ります:
- **エイリアス**:テンプレートで使用されるプロパティ名を変更します。
- **トランスフォーム**:コンポーネントに到達する前に値を変更します。
```ts
import { input, booleanAttribute } from '@angular/core';
@Component({...})
export class CustomButton {
// エイリアスの例
label = input('', { alias: 'btnLabel' });
// 組み込みヘルパーを使用したトランスフォームの例
disabled = input(false, { transform: booleanAttribute });
}
```
## モデル入力(双方向バインディング)
双方向データバインディングをサポートする入力を作成するには `model()` を使用します。
```ts
@Component({
selector: 'custom-counter',
template: `<button (click)="increment()">+</button>`,
})
export class CustomCounter {
value = model(0);
increment() {
this.value.update((v) => v + 1);
}
}
```
### 使用方法
```html
<!-- シグナルによる双方向バインディング -->
<custom-counter [(value)]="mySignal" />
<!-- プレーンプロパティによる双方向バインディング -->
<custom-counter [(value)]="myProperty" />
```
## デコレーターベースの入力(@Input
レガシー API は引き続きサポートされていますが、新しいコードには推奨されません。
```ts
import { Component, Input } from '@angular/core';
@Component({...})
export class Legacy {
@Input({ required: true }) value = 0;
@Input({ transform: trimString }) label = '';
}
```
## ベストプラクティス
- **シグナルを優先する**:より良いリアクティビティと型安全性のために `@Input()` ではなく `input()` を使用します。
- **必須入力**:ビルド時エラーを得るために必須データには `input.required()` を使用します。
- **純粋なトランスフォーム**:入力トランスフォーム関数は純粋で静的に解析可能であることを確認します。
- **衝突を避ける**:標準の DOM プロパティと衝突する入力名は使用しないでください(例:`id``title`)。

View File

@@ -0,0 +1,60 @@
# `linkedSignal` による依存状態の管理
`linkedSignal` 関数を使うと、別の状態と本質的に連動した書き込み可能な状態を作成できます。入力や他のシグナルから導出されたデフォルト値を持ちつつ、ユーザーが独立して変更できる状態に最適です。
ソース状態が変化すると、`linkedSignal` は新たに計算された値にリセットされます。
## 基本的な使い方
ソースに基づいて再計算するだけでよい場合は、計算関数を渡してください。`linkedSignal``computed` のように機能しますが、得られるシグナルは書き込み可能です(`.set()``.update()` を呼び出せます)。
```ts
import { Component, signal, linkedSignal } from '@angular/core';
@Component({...})
export class ShippingMethodPicker {
shippingOptions = signal(['Ground', 'Air', 'Sea']);
// 最初のオプションをデフォルト値とする。
// shippingOptions が変化すると、selectedOption は新しい最初のオプションにリセットされる。
selectedOption = linkedSignal(() => this.shippingOptions()[0]);
changeShipping(index: number) {
// このシグナルは手動で更新することもできる!
this.selectedOption.set(this.shippingOptions()[index]);
}
}
```
## 高度な使い方:以前の状態を考慮する
ソース状態が変化したとき、ユーザーの手動選択がまだ有効であれば保持したい場合があります。その場合は、`source``computation` を持つオブジェクト構文を使います。
`computation` 関数は、ソースの新しい値と、以前のソース値および以前の `linkedSignal` 値を含む `previous` オブジェクトを受け取ります。
```ts
interface ShippingMethod { id: number; name: string; }
@Component({...})
export class ShippingMethodPicker {
shippingOptions = signal<ShippingMethod[]>([
{id: 0, name: 'Ground'}, {id: 1, name: 'Air'}, {id: 2, name: 'Sea'}
]);
selectedOption = linkedSignal<ShippingMethod[], ShippingMethod>({
source: this.shippingOptions,
computation: (newOptions, previous) => {
// 新たに読み込まれたオプションにユーザーが以前選択した
// オプションが含まれていれば、そのまま選択を保持する。
// そうでなければ、最初のオプションにリセットする。
return newOptions.find(opt => opt.id === previous?.value.id) ?? newOptions[0];
}
});
}
```
### `linkedSignal` と `computed` と `effect` の使い分け
- `computed` を使う:状態が他の状態から**厳密に**導出されており、手動で更新すべきでない場合。
- `linkedSignal` を使う:状態は他の状態から導出されているが、ユーザーが**必ず**オーバーライドまたは手動更新できる必要がある場合。
- `effect` を使って一方の状態をもう一方に同期させることは**絶対にしない**。それはアンチパターンです。代わりに `computed` または `linkedSignal` を使ってください。

View File

@@ -0,0 +1,61 @@
# ルート読み込み戦略
Angular は、初期読み込み時間とナビゲーションの応答性のバランスを取るために、ルートとコンポーネントの読み込みに関する2つの主要な戦略をサポートしています。
## イーガーローディングEager Loading
コンポーネントは初期 JavaScript ペイロードにバンドルされ、即座に利用可能になります。
```ts
{ path: 'home', component: Home }
```
- **メリット**:シームレスなトランジション。
- **デメリット**:初期バンドルサイズが増加する。
## レイジーローディングLazy Loading
コンポーネントやルートは、ユーザーが画面に遷移したときにのみ読み込まれます。これにより JavaScript の独立した「チャンク」が生成されます。
### コンポーネントのレイジーローディング
`loadComponent` を使用して、コンポーネントをオンデマンドで取得します。
```ts
{
path: 'admin',
loadComponent: () => import('./admin/admin.component').then(m => m.AdminComponent)`,
}
```
### 子ルートのレイジーローディング
`loadChildren` を使用して、ルートのセットを取得します。
```ts
{
path: 'settings',
loadChildren: () => import('./settings/settings.routes'),
}
```
## インジェクションコンテキストとレイジーローディング
ローダー関数は現在のルートの**インジェクションコンテキスト**内で実行されます。これにより `inject()` を呼び出して、コンテキストを考慮した読み込み判断が可能になります。
```ts
{
path: 'dashboard',
loadComponent: () => {
const flags = inject(FeatureFlags);
return flags.isPremium
? import('./premium-dashboard')
: import('./basic-dashboard');
},
}
```
## 推奨事項
- メインのランディングページには**イーガーローディング**を使用する。
- 初期バンドルを小さく保つために、その他のすべての機能領域には**レイジーローディング**を使用する。

View File

@@ -0,0 +1,108 @@
# Angular CLI MCP サーバー
Angular CLI には Model Context ProtocolMCPサーバーが含まれており、AI アシスタントCursor、Gemini CLI、JetBrains AI など)が Angular CLI と直接やり取りできるようになります。コード生成、コードの近代化、サンプルの取得、ビルド/テストの実行を行うツールを提供します。
## 利用可能なツール(デフォルト)
MCP サーバーが有効化されると、AI エージェントは以下のツールにアクセスできます:
| 名前 | 説明 |
| :-------------------------- | :-------------------------------------------------------------------------------------------------------- |
| `ai_tutor` | インタラクティブな AI 搭載の Angular チューターを起動します。 |
| `find_examples` | モダンな Angular 機能に関する権威あるベストプラクティスのコードサンプルを検索します。 |
| `get_best_practices` | Angular ベストプラクティスガイドを取得します(スタンドアロンコンポーネント、型付きフォームなどに必須)。 |
| `list_projects` | `angular.json` を読み取り、ワークスペース内のすべてのアプリケーションとライブラリを一覧表示します。 |
| `onpush_zoneless_migration` | コードを分析し、`OnPush` 変更検知(ゾーンレスの前提条件)への移行計画を提供します。 |
| `search_documentation` | `https://angular.dev` の公式ドキュメントを検索します。 |
## 実験的ツール
一部のツールは `--experimental-tool`(または `-E`)フラグを使って明示的に有効化する必要があります。
| 名前 | 説明 |
| :------------------------- | :----------------------------------------------------------------------- |
| `build` | `ng build` を使って一度限りのビルドを実行します。 |
| `devserver.start` | 開発サーバー(`ng serve`)を非同期で起動します。即座に返ります。 |
| `devserver.stop` | 開発サーバーを停止します。 |
| `devserver.wait_for_build` | 実行中の開発サーバーの最新ビルドのログを返します。 |
| `e2e` | エンドツーエンドテストを実行します。 |
| `modernize` | 最新のベストプラクティスと構文に合わせてコードの移行を行います。 |
| `test` | プロジェクトのユニットテストを実行します。 |
## 設定
MCP サーバーを使用するには、ホスト環境IDE または CLI`npx @angular/cli mcp` を実行するよう設定します。
### Antigravity IDE
プロジェクトのルートに `.antigravity/mcp.json` というファイルを作成します:
```json
{
"mcpServers": {
"angular-cli": {
"command": "npx",
"args": ["-y", "@angular/cli", "mcp"]
}
}
}
```
### Gemini CLI
プロジェクトルートに `.gemini/settings.json` を作成します:
```json
{
"mcpServers": {
"angular-cli": {
"command": "npx",
"args": ["-y", "@angular/cli", "mcp"]
}
}
}
```
### Cursor
プロジェクトルートに `.cursor/mcp.json` を作成します(またはグローバルに `~/.cursor/mcp.json`
```json
{
"mcpServers": {
"angular-cli": {
"command": "npx",
"args": ["-y", "@angular/cli", "mcp"]
}
}
}
```
### VS Code
`.vscode/mcp.json` を作成します:
```json
{
"servers": {
"angular-cli": {
"command": "npx",
"args": ["-y", "@angular/cli", "mcp"]
}
}
}
```
## コマンドオプション
設定の `args` 配列に MCP サーバーへの引数を渡せます:
- `--read-only`:プロジェクトを変更しないツールのみを登録します。
- `--local-only`:インターネット接続を必要としないツールのみを登録します。
- `--experimental-tool``-E`):特定の実験的ツールを有効化します(例:`-E build``-E devserver`)。
実験的ツールを有効にした読み取り専用モードの例:
```json
"args": ["-y", "@angular/cli", "mcp", "--read-only", "-E", "build", "-E", "modernize"]
```

View File

@@ -0,0 +1,69 @@
# ルートへのナビゲーション
Angular はルート間を遷移するための宣言的な方法とプログラム的な方法の両方を提供します。
## 宣言的なナビゲーション(`RouterLink`
アンカー要素に `RouterLink` ディレクティブを使用します。
```ts
import {RouterLink, RouterLinkActive} from '@angular/router';
@Component({
imports: [RouterLink, RouterLinkActive],
template: `
<nav>
<a routerLink="/dashboard" routerLinkActive="active-link">Dashboard</a>
<a [routerLink]="['/user', userId]">Profile</a>
</nav>
`,
})
export class Nav {
userId = '123';
}
```
- **絶対パス**`/` で始まります(例:`/settings`)。
- **相対パス**:先頭に `/` がありません。一つ上のレベルに移動するには `../` を使います。
## プログラム的なナビゲーション(`Router`
`Router` サービスを注入して TypeScript コードからナビゲートします。
### `router.navigate()`
コマンドの配列を使用します。
```ts
private router = inject(Router);
private route = inject(ActivatedRoute);
// 標準的なナビゲーション
this.router.navigate(['/profile']);
// パラメーター付き
this.router.navigate(['/search'], {
queryParams: { q: 'angular' },
fragment: 'results'
});
// 相対ナビゲーション
this.router.navigate(['edit'], { relativeTo: this.route });
```
### `router.navigateByUrl()`
文字列パスを使用します。絶対ナビゲーションや完全な URL に最適です。
```ts
this.router.navigateByUrl('/products/123?view=details');
// 履歴の現在のエントリを置き換える
this.router.navigateByUrl('/login', {replaceUrl: true});
```
## URL パラメーター
- **ルートパラメーター**:パスの一部(例:`/user/123`)。
- **クエリパラメーター**`?` の後(例:`/search?q=query`)。
- **マトリックスパラメーター**:セグメントにスコープされる(例:`/products;category=books`)。

View File

@@ -0,0 +1,86 @@
# アウトレット(カスタムイベント)
アウトプットを使うと、子コンポーネントがカスタムイベントを発行でき、親コンポーネントがそれをリッスンできます。Angular はモダンなアプリケーションでは新しい `output()` 関数の使用を推奨しています。
## 関数ベースのアウトプット
`output()` 関数を使ってアウトプットを宣言します。これにより `OutputEmitterRef` が返されます。
```ts
import {Component, output} from '@angular/core';
@Component({
selector: 'custom-slider',
template: `<button (click)="changeValue(50)">Set to 50</button>`,
})
export class CustomSlider {
// イベントデータなしのアウトプット
panelClosed = output<void>();
// イベントデータありnumberのアウトプット
valueChanged = output<number>();
changeValue(newValue: number) {
this.valueChanged.emit(newValue);
}
}
```
### テンプレートでの使用
アウトプットイベントにバインドするには括弧 `()` を使います。イベントがデータを発行する場合、特別な `$event` 変数を使ってアクセスします。
```html
<custom-slider (panelClosed)="savePanelState()" (valueChanged)="logValue($event)" />
```
## 設定オプション
`output` 関数はエイリアスを指定するための設定オブジェクトを受け取ります。
```ts
@Component({...})
export class CustomSlider {
// テンプレートでは 'valueChanged' という名前のイベントだが、
// コンポーネントクラス内では 'changed' としてアクセスする。
changed = output<number>({ alias: 'valueChanged' });
}
```
## プログラム的なサブスクリプション
コンポーネントを動的に生成する場合、アウトプットにプログラムでサブスクライブできます:
```ts
const componentRef = viewContainerRef.createComponent(CustomSlider);
const subscription = componentRef.instance.valueChanged.subscribe((val) => {
console.log('Value changed:', val);
});
// 必要に応じて手動でクリーンアップAngular は破棄されたコンポーネントを自動でクリーンアップする)
subscription.unsubscribe();
```
## デコレーターベースのアウトプット(@Output
レガシー API は `@Output()` デコレーターと `EventEmitter` を使用します。引き続きサポートされますが、新しいコードでは推奨されません。
```ts
import { Component, Output, EventEmitter } from '@angular/core';
@Component({...})
export class LegacyExample {
@Output() valueChanged = new EventEmitter<number>();
// エイリアスあり
@Output('customEventName') changed = new EventEmitter<void>();
}
```
## ベストプラクティス
- **`output()` を優先する**`@Output()``EventEmitter` の代わりに関数ベースの `output()` を使用してください。
- **命名**:アウトプット名には `camelCase` を使用します。`on` を前置することは避けてください(例:`onValueChanged` ではなく `valueChanged` を使用する)。
- **DOM バブリングなし**Angular のカスタムイベントは、ネイティブイベントのように DOM ツリーをバブルアップしません。
- **衝突を避ける**:ネイティブ DOM イベント(`click``submit` など)と衝突する名前は選ばないでください。

View File

@@ -0,0 +1,122 @@
# リアクティブフォーム
リアクティブフォームは、フォーム入力を処理するためのモデル駆動のアプローチを提供します。オブザーバブルストリームを基盤として構築され、データモデルへの同期アクセスを提供するため、テンプレート駆動フォームよりもスケーラブルでテストしやすい特徴があります。
## コアクラス
リアクティブフォームは `@angular/forms` の以下の基本クラスで構成されます:
- `FormControl`:個別の入力の値と有効性を管理します。
- `FormGroup`:コントロールのグループ(オブジェクトのような構造)を管理します。
- `FormArray`:数値インデックスによるコントロールの配列を管理します。
- `FormBuilder`:コントロールインスタンス作成のためのファクトリーメソッドを提供するサービス。
## セットアップ
コンポーネントに `ReactiveFormsModule` をインポートします。
```ts
import {Component, inject} from '@angular/core';
import {ReactiveFormsModule, FormGroup, FormControl, Validators, FormBuilder} from '@angular/forms';
@Component({
selector: 'app-profile-editor',
imports: [ReactiveFormsModule],
templateUrl: './profile-editor.component.html',
})
export class ProfileEditor {
private fb = inject(FormBuilder);
// FormBuilder を使った簡潔な定義
profileForm = this.fb.group({
firstName: ['', Validators.required],
lastName: [''],
address: this.fb.group({
street: [''],
city: [''],
}),
aliases: this.fb.array([this.fb.control('')]),
});
onSubmit() {
console.warn(this.profileForm.value);
}
}
```
## テンプレートバインディング
モデルをビューにバインドするためのディレクティブを使用します:
- `[formGroup]``FormGroup``<form>` または `<div>` にバインドします。
- `formControlName`:グループ内の名前付きコントロールを入力にバインドします。
- `formGroupName`:ネストされた `FormGroup` をバインドします。
- `formArrayName`:ネストされた `FormArray` をバインドします。
- `[formControl]`:スタンドアロンの `FormControl` をバインドします。
```html
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
<input type="text" formControlName="firstName" />
<div formGroupName="address">
<input type="text" formControlName="street" />
</div>
<div formArrayName="aliases">
@for (alias of aliases.controls; track $index) {
<input type="text" [formControlName]="$index" />
}
</div>
<button type="submit" [disabled]="!profileForm.valid">Submit</button>
</form>
```
## コントロールへのアクセス
特に `FormArray` のコントロールに簡単にアクセスするためのゲッターを使用します。
```ts
get aliases() {
return this.profileForm.get('aliases') as FormArray;
}
addAlias() {
this.aliases.push(this.fb.control(''));
}
```
## 値の更新
- `patchValue()`:指定されたプロパティのみを更新します。構造の不一致があっても警告なく無視します。
- `setValue()`:モデル全体を置き換えます。フォームの構造を厳密に強制します。
```ts
updateProfile() {
this.profileForm.patchValue({
firstName: 'Nancy',
address: { street: '123 Drew Street' }
});
}
```
## 統合変更イベント
モダンな Angularv18+)では、すべてのコントロールに単一の `events` オブザーバブルが提供され、値、ステータス、pristine、touched、リセット、サブミットイベントを追跡できます。
```ts
import {ValueChangeEvent, StatusChangeEvent} from '@angular/forms';
this.profileForm.events.subscribe((event) => {
if (event instanceof ValueChangeEvent) {
console.log('New value:', event.value);
}
});
```
## 手動ステート管理
- `markAsTouched()` / `markAllAsTouched()`:サブミット時にバリデーションエラーを表示するのに便利です。
- `markAsDirty()` / `markAsPristine()`:値が変更されたかどうかを追跡します。
- `updateValueAndValidity()`:値とステータスの再計算を手動でトリガーします。
- ほとんどのメソッドに `{ emitEvent: false }` または `{ onlySelf: true }` オプションを渡して伝播を制御できます。

View File

@@ -0,0 +1,44 @@
# レンダリング戦略
Angular は SEO、パフォーマンス、インタラクティビティを最適化するために、複数のレンダリング戦略をサポートしています。
## 1. クライアントサイドレンダリングCSR
**デフォルト戦略。** コンテンツはブラウザで完全にレンダリングされます。
- **ユースケース**:インタラクティブなダッシュボード、社内ツール。
- **メリット**:設定が最もシンプルで、サーバーコストが低い。
- **デメリット**SEO が弱く、初期コンテンツの表示が遅いJS を待つ必要がある)。
## 2. 静的サイト生成SSG / プリレンダリング)
コンテンツは**ビルド時**に静的 HTML ファイルとして事前にレンダリングされます。
- **ユースケース**:マーケティングページ、ブログ、ドキュメント。
- **メリット**:最速の初期読み込み、優れた SEO、CDN フレンドリー。
- **デメリット**:コンテンツ更新のたびに再ビルドが必要で、ユーザー固有のデータには対応できない。
## 3. サーバーサイドレンダリングSSR
コンテンツは**初回リクエスト**に対してサーバー上でレンダリングされます。その後のナビゲーションはクライアントサイドで行われますSPA スタイル)。
- **ユースケース**EC サイトの商品ページ、ニュースサイト、パーソナライズされた動的コンテンツ。
- **メリット**:優れた SEO、初期コンテンツの表示が速い。
- **デメリット**サーバーNode.jsが必要で、サーバーコスト/レイテンシが高い。
## ハイドレーション
ハイドレーションは、サーバーレンダリングされた HTML をブラウザでインタラクティブにするプロセスです。
- **フルハイドレーション**:アプリ全体が一度にインタラクティブになります。
- **インクリメンタルハイドレーション**:(高度)`@defer` ブロックを使用して必要に応じてパーツがインタラクティブになります。
- **イベントリプレイ**:ハイドレーション完了前に発生したユーザーイベントをキャプチャして再生します。
## 判断マトリックス
| 要件 | 戦略 |
| :------------------------------ | :------------------- |
| **SEO + 静的コンテンツ** | SSG |
| **SEO + 動的コンテンツ** | SSR |
| **SEO不要 + 高インタラクティビティ** | CSR |
| **混在** | ハイブリッド(ルートベース) |

View File

@@ -0,0 +1,77 @@
# `resource` を使った非同期リアクティビティ
> [!IMPORTANT]
> `resource` API は現在 Angular で実験的な機能です。
`Resource` は非同期データフェッチを Angular のシグナルベースのリアクティビティに組み込みます。依存関係が変わるたびに非同期ローダー関数を実行し、状態と結果を同期的なシグナルとして公開します。
## 基本的な使い方
`resource` 関数は主に2つのプロパティを持つオプションオブジェクトを受け取ります
1. `params`:リアクティブな計算(`computed` のようなもの)。ここで読み取られるシグナルが変わると、リソースは再フェッチします。
2. `loader`:パラメーターに基づいてデータを取得する非同期関数。
```ts
import { Component, resource, signal, computed } from '@angular/core';
@Component({...})
export class UserProfile {
userId = signal('123');
userResource = resource({
// userId をリアクティブに追跡
params: () => ({ id: this.userId() }),
// params が変わるたびに実行される
loader: async ({ params, abortSignal }) => {
const response = await fetch(`/api/users/${params.id}`, { signal: abortSignal });
if (!response.ok) throw new Error('Network error');
return response.json();
}
});
// 計算済みシグナル内でリソースの値を使用する
userName = computed(() => {
if (this.userResource.hasValue()) {
return this.userResource.value()?.name;
} else {
return 'Loading...';
}
});
}
```
## リクエストの中断
前のローダーがまだ実行中に `params` シグナルが変わった場合、`Resource` は提供された `abortSignal` を使って実行中のリクエストを中断しようとします。**`fetch` の呼び出しには常に `abortSignal` を渡してください。**
## データの再読み込み
params を変えずにローダーを強制的に再実行させるには、`.reload()` を呼び出します。
```ts
this.userResource.reload();
```
## リソースのステータスシグナル
`Resource` オブジェクトは現在の状態を読み取るためのいくつかのシグナルを提供します:
- `value()`:解決済みデータ、または `undefined`
- `hasValue()`:型ガードとなるブール値。値が存在する場合は `true`
- `isLoading()`:ローダーが現在実行中かどうかを示すブール値。
- `error()`:ローダーがスローしたエラー、または `undefined`
- `status()`:正確な状態を表す文字列定数(`'idle'``'loading'``'resolved'``'error'``'reloading'``'local'`)。
## ローカルミューテーション
リソースの値を直接楽観的に更新できます。これにより状態が `'local'` に変わります。
```ts
this.userResource.value.set({name: 'Optimistic Update'});
```
## `httpResource` を使ったリアクティブなデータフェッチ
Angular の `HttpClient` を使用している場合は、`httpResource` の使用を優先してください。これはインターセプターを含む Angular の HTTP スタックを活用しながら、同じシグナルベースのリソース API を提供する専用ラッパーです。

View File

@@ -0,0 +1,56 @@
# ルートトランジションアニメーション
Angular ルーターは、ルート間のスムーズなビジュアルトランジションのためにブラウザの **View Transitions API** をサポートしています。
## ビュートランジションの有効化
ルーター設定に `withViewTransitions()` を追加します。
```ts
provideRouter(routes, withViewTransitions());
```
これは**プログレッシブエンハンスメント**です。API をサポートしていないブラウザでも、ルーターは引き続き動作しますが、トランジションアニメーションは行われません。
## 仕組み
1. ブラウザが古い状態のスクリーンショットを撮ります。
2. ルーターが DOM を更新します(新しいコンポーネントをアクティベートします)。
3. ブラウザが新しい状態のスクリーンショットを撮ります。
4. ブラウザが2つの状態の間をアニメーションします。
## CSS によるカスタマイズ
トランジションは**グローバル CSS ファイル**でカスタマイズします(コンポーネントスコープの CSS ではありません)。
`::view-transition-old()``::view-transition-new()` 疑似要素を使用します。
```css
/* 例:クロスフェード + スライド */
::view-transition-old(root) {
animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out;
}
::view-transition-new(root) {
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in;
}
```
## 高度な制御
`onViewTransitionCreated` を使用して、ナビゲーションコンテキストに基づいてトランジションをスキップしたり、動作をカスタマイズしたりします。
```ts
withViewTransitions({
onViewTransitionCreated: ({transition, from, to}) => {
// 特定のルートに対してアニメーションをスキップ
if (to.url === '/no-animation') {
transition.skipTransition();
}
},
});
```
## ベストプラクティス
- **グローバルスタイル**:ビューカプセル化の問題を避けるため、トランジションアニメーションは常に `styles.css` で定義してください。
- **ビュートランジション名**:ルートをまたいでスムーズにトランジションさせたい要素(ヘッダー画像など)には、一意の `view-transition-name` を割り当ててください。

View File

@@ -0,0 +1,52 @@
# ルートガード
ルートガードは、ユーザーがルートへ遷移できるか、またはルートから離れられるかを制御します。
## ガードの種類
- **`CanActivate`**:ユーザーはこのルートにアクセスできるか?(例:認証チェック)
- **`CanActivateChild`**:ユーザーはこのルートの子にアクセスできるか?
- **`CanDeactivate`**:ユーザーはこのルートから離れられるか?(例:未保存の変更)
- **`CanMatch`**:このルートはマッチングの対象として考慮すべきか?(例:フィーチャーフラグ)`false` を返すと、ルーターは他のルートのチェックを継続します。
## ガードの作成
Angular 15 以降、ガードは通常、関数として定義します。
```ts
export const authGuard: CanActivateFn = (route, state) => {
const authService = inject(AuthService);
const router = inject(Router);
if (authService.isLoggedIn()) {
return true;
}
// ログインページへリダイレクト
return router.parseUrl('/login');
};
```
## ガードの適用
ルート設定に配列として追加します。順番通りに実行されます。
```ts
{
path: 'admin',
component: Admin,
canActivate: [authGuard],
canActivateChild: [adminChildGuard],
canDeactivate: [unsavedChangesGuard]
}
```
## 戻り値
- `boolean``true` で許可、`false` でブロック。
- `UrlTree` または `RedirectCommand`:別のルートへリダイレクト。
- `Observable` または `Promise`:上記の型に解決されます。
## セキュリティに関する注意
**クライアントサイドのガードはサーバーサイドのセキュリティの代わりにはなりません。** サーバー側で常に権限を検証してください。

View File

@@ -0,0 +1,45 @@
# ルーターのライフサイクルとイベント
Angular ルーターは `Router.events` オブザーバブルを通じてイベントを発行し、開始から終了までのナビゲーションのライフサイクルを追跡できます。
## 主要なルーターイベント(時系列順)
1. **`NavigationStart`**:ナビゲーションが開始されます。
2. **`RoutesRecognized`**:ルーターが URL をルートにマッチさせます。
3. **`GuardsCheckStart` / `End`**`canActivate``canMatch` などの評価が行われます。
4. **`ResolveStart` / `End`**:データ解決フェーズ(リゾルバーによるデータの取得)。
5. **`NavigationEnd`**:ナビゲーションが正常に完了しました。
6. **`NavigationCancel`**:ナビゲーションがキャンセルされました(例:ガードが `false` を返した)。
7. **`NavigationError`**:ナビゲーションが失敗しました(例:リゾルバーでのエラー)。
## イベントのサブスクライブ
`Router` を注入して `events` オブザーバブルをフィルタリングします。
```ts
import {Router, NavigationStart, NavigationEnd} from '@angular/router';
export class MyService {
private router = inject(Router);
constructor() {
this.router.events.pipe(filter((e) => e instanceof NavigationEnd)).subscribe((event) => {
console.log('Navigated to:', event.url);
});
}
}
```
## デバッグ
アプリケーション起動時にすべてのルーティングイベントの詳細なコンソールログを有効化します。
```ts
provideRouter(routes, withDebugTracing());
```
## よくあるユースケース
- **ローディングインジケーター**`NavigationStart` が発火したときにスピナーを表示し、`NavigationEnd`/`Cancel`/`Error` で非表示にします。
- **アナリティクス**`NavigationEnd` をリッスンしてページビューを追跡します。
- **スクロール管理**:カスタムスクロール動作のために `Scroll` イベントに応答します。

View File

@@ -0,0 +1,87 @@
# RouterTestingHarness を使ったテスト
ルーティングを伴うコンポーネントをテストする場合、**ルーターや関連サービスをモック化しない**ことが重要です。代わりに `RouterTestingHarness` を使用してください。これにより、実際のアプリケーションに近い環境でルーティングロジックをテストするための堅牢で信頼性の高い方法が提供されます。
ハーネスを使用することで、実際のルーター設定、ガード、リゾルバーをテストでき、より意味のあるテストにつながります。
## ルーターテストのセットアップ
`RouterTestingHarness` はルーティングシナリオをテストするための主要なツールです。また、`TestBed` 設定内で `provideRouter` 関数を使ってテスト用ルートを提供する必要があります。
### セットアップ例
```ts
import {TestBed} from '@angular/core/testing';
import {provideRouter} from '@angular/router';
import {RouterTestingHarness} from '@angular/router/testing';
import {Dashboard} from './dashboard.component';
import {HeroDetail} from './hero-detail.component';
describe('Dashboard Component Routing', () => {
let harness: RouterTestingHarness;
beforeEach(async () => {
// 1. テスト用ルートで TestBed を設定
await TestBed.configureTestingModule({
providers: [
// テスト固有のルートで provideRouter を使用
provideRouter([
{path: '', component: Dashboard},
{path: 'heroes/:id', component: HeroDetail},
]),
],
}).compileComponents();
// 2. RouterTestingHarness を作成
harness = await RouterTestingHarness.create();
});
});
```
### 主要なコンセプト
1. **`provideRouter([...])`**:テスト用のルーティング設定を提供します。テスト対象のコンポーネントが正しく機能するために必要なルートを含める必要があります。
2. **`RouterTestingHarness.create()`**:ハーネスを非同期で作成・初期化し、ルート URL`/`)への初回ナビゲーションを実行します。
## ルーターテストの作成
ハーネスを作成したら、ナビゲーションを駆動し、ルーターの状態やアクティベートされたコンポーネントの状態に対してアサーションを行えます。
### 例:ナビゲーションのテスト
```ts
it('should navigate to a hero detail when a hero is selected', async () => {
// 1. 初期コンポーネントにナビゲートし、そのインスタンスを取得
const dashboard = await harness.navigateByUrl('/', Dashboard);
// ダッシュボードにヒーローを選択するメソッドがあると仮定
const heroToSelect = {id: 42, name: 'Test Hero'};
dashboard.selectHero(heroToSelect);
// ナビゲーションをトリガーするアクション後の安定を待つ
await harness.fixture.whenStable();
// 2. URL に対してアサート
expect(harness.router.url).toEqual('/heroes/42');
// 3. ナビゲーション後にアクティベートされたコンポーネントを取得
const heroDetail = await harness.getHarness(HeroDetail);
// 4. 新しいコンポーネントの状態に対してアサート
expect(await heroDetail.componentInstance.hero.name).toBe('Test Hero');
});
it('should get the activated component directly', async () => {
// 一度にナビゲートしてコンポーネントインスタンスを取得
const dashboardInstance = await harness.navigateByUrl('/', Dashboard);
expect(dashboardInstance).toBeInstanceOf(Dashboard);
});
```
### ベストプラクティス
- **ハーネスでナビゲートする**:ナビゲーションをシミュレートするには常に `harness.navigateByUrl()` を使用してください。このメソッドはアクティベートされたコンポーネントのインスタンスで解決される Promise を返します。
- **ルーターの状態にアクセスする**`harness.router` を使用してライブのルーターインスタンスにアクセスし、状態に対してアサートします(例:`harness.router.url`)。
- **アクティベートされたコンポーネントの取得**:現在アクティベートされているルーティングコンポーネントのコンポーネントハーネスインスタンスを取得するには `harness.getHarness(ComponentType)` を、`DebugElement` を取得するには `harness.routeDebugElement` を使用してください。
- **安定を待つ**:ナビゲーションを引き起こすアクションを実行した後は、アサーションを行う前に必ず `await harness.fixture.whenStable()` でルーティングの完了を待ってください。

View File

@@ -0,0 +1,68 @@
# アウトレットを使ったルートの表示
`RouterOutlet` ディレクティブは、Angularが現在のURLに対応するコンポーネントをレンダリングするためのプレースホルダーです。
## 基本的な使い方
テンプレートに `<router-outlet />` を含めます。Angularはルーティングされたコンポーネントをアウトレットの直後の兄弟要素として挿入します。
```html
<app-header /> <router-outlet />
<!-- ルートのコンテンツがここに表示される -->
<app-footer />
```
## ネストされたアウトレット
子ルートには、親コンポーネントのテンプレート内に独自の `<router-outlet />` が必要です。
```ts
// 親コンポーネントのテンプレート
<h1>Settings</h1>
<router-outlet /> <!-- ProfileやSecurityなどの子コンポーネントがここにレンダリングされる -->
```
## 名前付きアウトレット(セカンダリルート)
ページには複数のアウトレットを設定できます。アウトレットに `name` を割り当てることで、特定のアウトレットをターゲットにできます。デフォルト名は `'primary'` です。
```html
<router-outlet />
<!-- プライマリ -->
<router-outlet name="sidebar" />
<!-- セカンダリ -->
```
ルート設定で `outlet` を定義します:
```ts
{
path: 'chat',
component: Chat,
outlet: 'sidebar'
}
```
## アウトレットのライフサイクルイベント
`RouterOutlet` はコンポーネントが変更されるときにイベントを発行します:
- `activate`: 新しいコンポーネントがインスタンス化された。
- `deactivate`: コンポーネントが破棄された。
- `attach` / `detach`: `RouteReuseStrategy` と共に使用される。
```html
<router-outlet (activate)="onActivate($event)" />
```
## `routerOutletData` によるデータの受け渡し
`routerOutletData` インプットを使用して、ルーティングされたコンポーネントにコンテキストデータを渡すことができます。コンポーネントはシグナルとして `ROUTER_OUTLET_DATA` インジェクショントークン経由でこのデータにアクセスします。
```ts
// 親コンポーネント内
<router-outlet [routerOutletData]="{ theme: 'dark' }" />
// ルーティングされたコンポーネント内
outletData = inject(ROUTER_OUTLET_DATA) as Signal<{ theme: string }>;
```

View File

@@ -0,0 +1,795 @@
# シグナルフォーム
シグナルフォームは、対象のAngularバージョンがサポートしている場合、新しいフォームに推奨されます。Angularシグナルを使用して、リアクティブかつ型安全なモデル駆動型のフォーム状態管理を提供します。
シグナルフォームを使用する場合、フィールドの値や型に `null` を使用しないでください。
## インポート
`@angular/forms/signals` から以下をインポートできます:
```ts
import {
form,
FormField,
submit,
// フィールド状態のルール
disabled,
hidden,
readonly,
debounce,
// スキーマヘルパー
applyWhen,
applyEach,
schema,
// カスタムバリデーション
validate,
validateHttp,
validateStandardSchema,
// メタデータ
metadata,
} from '@angular/forms/signals';
```
## フォームの作成
シグナルモデルとともに `form()` 関数を使用します。フォームの構造はモデルから直接導出されます。
```ts
import {Component, signal} from '@angular/core';
import {form, FormField} from '@angular/forms/signals';
@Component({
// ...
imports: [FormField],
})
export class Example {
// 1. 初期値でモデルを定義するundefinedは避ける
userModel = signal({
name: '', // 重要: 初期値にnullやundefinedは絶対に使用しない
email: '',
age: 0, // 数値には0を使用し、nullは使用しない
address: {
street: '',
city: '',
},
hobbies: [] as string[], // 配列には[]を使用し、nullは使用しない
});
// 誤り - このようにしてはいけない:
// badModel = signal({
// name: null, // エラー: '' を使用すること
// age: null, // エラー: 0 を使用すること
// items: null // エラー: [] を使用すること
// });
// 2. フォームを作成する
userForm = form(this.userModel);
}
```
## バリデーション
バリデーターを `@angular/forms/signals` からインポートします。
```ts
import {required, email, min, max, minLength, maxLength, pattern} from '@angular/forms/signals';
```
`form()` に渡すスキーマ関数内で使用します:
```ts
userForm = form(this.userModel, (schemaPath) => {
// 必須
required(schemaPath.name, {message: 'Name is required'});
// 条件付き必須
required(schemaPath.name, {
when({valueOf}) {
return valueOf(schemaPath.age) > 10;
},
});
// when は required にのみ使用可能
// このようにしてはいけない: pattern(p.name, /xxx/, {when /* ERROR */)
// メールアドレス
email(schemaPath.email, {message: 'Invalid email'});
// 数値の最小値/最大値
min(schemaPath.age, 18);
max(schemaPath.age, 100);
// 文字列/配列の最小長/最大長
minLength(schemaPath.password, 8);
maxLength(schemaPath.description, 500);
// パターン(正規表現)
pattern(schemaPath.zipCode, /^\d{5}$/);
});
```
## FieldState と FormField: 親要素の要件
**FormField**(構造)と **FieldState**(実際のデータ/シグナル)の違いを理解することが重要です。
**ルール**: フィールドを関数として**呼び出す**ことで、そのステートシグナルvalid、touched、dirty、hidden など)にアクセスできます。
```ts
// f は FormField構造的
const f = form(signal({cat: {name: 'pirojok-the-cat', age: 5}}));
f.cat.name; // FormField: ここからフラグは取得できない!
f.cat.name.touched(); // エラー: touched() は FormField に存在しない
f.cat.name(); // FieldState: 呼び出すことでシグナルへのアクセスが可能になる
f.cat.name().touched(); // 有効: シグナルへのアクセス
f.cat().name.touched(); // エラー: f.cat() はステートであり、子要素を持たない!
```
テンプレートでも同様です:
```html
<!-- 誤り: 'hidden' プロパティは 'FormField' 型に存在しない -->
@if (bookingForm.hotelDetails.hidden()) { ... }
<!-- 正しい: 最初に呼び出す -->
@if (bookingForm.hotelDetails().hidden()) { ... }
```
## Disabled / Readonly / Hidden
スキーマ内のルールを使用してフィールドのステータスを制御します。
```ts
import {disabled, readonly, hidden} from '@angular/forms/signals';
userForm = form(this.userModel, (schemaPath) => {
// 条件付き無効化
disabled(schemaPath.password, ({valueOf}) => !valueOf(schemaPath.createAccount));
// 条件付き非表示(モデルからは削除せず、非表示としてマークするのみ)
hidden(schemaPath.shippingAddress, ({valueOf}) => valueOf(schemaPath.sameAsBilling));
// 読み取り専用
readonly(schemaPath.username);
});
```
## バインディング
`FormField` をインポートし、`[formField]` ディレクティブを使用します。
```ts
import {FormField} from '@angular/forms/signals';
```
`disabled``hidden``readonly``name` などのステート上のすべてのプロパティは自動的にバインドされます。
`name` フィールドは手動でバインド_しないでください_。
**重要: 禁止属性**
`[formField]` を使用する場合、テンプレートで以下の属性を設定してはなりません(静的またはバインドされた形式のいずれも):
- `min``max`(代わりにスキーマ内のバリデーターを使用)
- `value``[value]``[attr.value]``[formField]` によって処理済み)
- `[attr.min]``[attr.max]`
- `[disabled]``[readonly]``[formField]` によって処理済み)
このようにしてはいけません: `<input min="1" [formField]>``<input [value]="val" [formField]>`
```html
<!-- 入力 -->
<input [formField]="userForm.name" />
<!-- チェックボックス -->
<input type="checkbox" [formField]="userForm.isAdmin" />
<!-- セレクト -->
<select [formField]="userForm.country">
<option value="us">US</option>
</select>
<!-- userForm.name は null にできない。input は null を受け付けないため -->
<input [formField]="userForm.name" />
```
## リアクティブフォーム
`@angular/forms` から `FormControl``FormGroup``FormArray``FormBuilder` を**インポートしないでください**。シグナルフォームはこれらのコンセプトを完全に置き換えます。
シグナルフォームにはビルダーがありません。
## ステートへのアクセス
フォーム内の各フィールドは、そのステートを返す関数です。
```ts
// フィールドを呼び出してアクセスする
const emailState = this.userForm.email();
// 値WritableSignal
const value = this.userForm().value();
// バリデーションステート(シグナル)
const isValid = this.userForm().valid();
const isInvalid = this.userForm().invalid();
const errors = this.userForm().errors(); // エラーの配列
const isPending = this.userForm().pending(); // 非同期バリデーション待ち
// インタラクションステート(シグナル)
const isTouched = this.userForm().touched();
const isDirty = this.userForm().dirty();
// 可用性ステート(シグナル)
const isDisabled = this.userForm().disabled();
const isHidden = this.userForm().hidden();
const isReadonly = this.userForm().readonly();
```
重要!: ステートを取得するには、必ずフィールドを呼び出してください。
```ts
form().invalid()
form.field().dirty()
form.field.subfield().touched()
form.a.b.c.d().value()
form.address.ssn().pending()
form().reset()
// 唯一の例外は length です:
form.children.length
form.length // 注意: 括弧なし!
form.client.addresses.length // "()" なし
@for (income of form.addresses; track $index) {/**/}
```
## 送信
`submit()` 関数を使用します。アクションを実行する前に、すべてのフィールドを自動的にタッチ済みとしてマークします。
**重要**: `submit()` へのコールバックは `async` でなければならず、Promise を返す必要があります。
```ts
import { submit } from '@angular/forms/signals';
// 正しい - async コールバック
onSubmit() {
submit(this.userForm, async () => {
// フォームが有効な場合のみ実行される
await this.apiService.save(this.userModel());
console.log('Saved!');
});
}
// 誤り - async キーワードが欠けている
onSubmit() {
submit(this.userForm, () => { // エラー: async でなければならない
console.log('Saved!');
});
}
```
## エラー処理
`field().errors()` は ValidationError の配列を返します:
```ts
interface ValidationError {
readonly kind: string;
readonly message?: string;
}
```
バリデーターから null を返さないでください。
エラーがない場合は undefined を返してください。
### コンテキスト
`validate()``disabled()``applyWhen` などのルールに渡される関数は、コンテキストオブジェクトを受け取ります。その構造を理解することが**重要**です:
```ts
validate(
schemaPath.username,
({
value, // Signal<T>: フィールドの現在値(書き込み可能)
fieldTree, // FieldTree<T>: サブフィールド(グループ/配列の場合)
state, // FieldState<T>: state.valid()、state.dirty() などのフラグへのアクセス
valueOf, // (path) => T: 他のフィールドの値を読む(依存関係を追跡)例: valueOf(schemaPath.password)
stateOf, // (path) => FieldState: 他のフィールドのステートにアクセス 例: stateOf(schemaPath.password).valid()
pathKeys, // Signal<string[]>: ルートからこのフィールドへのパス
}) => {
// 誤り: if (touched()) ... touched はコンテキスト内にない)
// 正しい: if (state.touched()) ...
if (value() === 'admin') {
return {kind: 'reserved', message: 'Username admin is reserved'};
}
},
);
```
### 重要: パスはシグナルではない
`form()` コールバック内で、`schemaPath` とその子要素(例: `schemaPath.user.name`)は**シグナルではなく**、**呼び出し可能でもありません**。
```ts
// 誤り - エラーが発生します:
applyWhen(p.ssn, () => p.ssn().touched(), (ssnField) => { ... });
// 正しい - stateOf() を使用してパスのステートを取得する:
applyWhen(p.ssn, ({ stateOf }) => stateOf(p.ssn).touched(), (ssnField) => { ... });
// 正しい - valueOf() を使用してパスの値を取得する:
applyWhen(p.ssn, ({ valueOf }) => valueOf(p.ssn) !== '', (ssnField) => { ... });
```
### 複数アイテム
- アイテムごとにルールを適用するには `applyEach` を使用します。
- **重要**: `applyEach` のコールバックは引数を**1つだけ**取りますアイテムパス。2つではありません:
```ts
// 正しい - 引数1つ
applyEach(s.items, (item) => {
required(item.name);
});
// 誤り - インデックスを渡さない
applyEach(s.items, (item, index) => {
// エラー: コールバックは引数を1つしか取らない
required(item.name);
});
```
- テンプレートではアイテムの反復に `@for` を使用します。
- 配列からアイテムを削除するには、データ内の該当アイテムをそのまま削除してください。
- **`select` バインディング**: `<select [formField]="form.country">` にバインドできます。オプションには `value` 属性があることを確認してください。
### ネストした @for ループ
**重要**: AngularにはAngularには `$parent` がありません。ネストされたループでは、外側のインデックスを変数に保存してください:
```html
<!-- 誤り - $parent は存在しない -->
@for (item of form.items; track $index) { @for (option of item.options; track $index) {
<button (click)="removeOption($parent.$index, $index)">Remove</button>
<!-- エラー -->
} }
<!-- 正しい - let を使用して外側のインデックスを保存する -->
@for (item of form.items; track $index; let outerIndex = $index) { @for (option of item.options;
track $index) {
<button (click)="removeOption(outerIndex, $index)">Remove</button>
} }
```
### フォームボタンの無効化
```html
<button [disabled]="form().invalid() || form().pending()" />
<!-- または -->
<button [disabled]="taxForm.invalid()" />
```
inputに `[disabled]` を使用しないでください。`[formField]` がこれを行います。
inputに `[readonly]` を使用しないでください。`[formField]` がこれを行います。
フィールドを無効化または読み取り専用にする必要がある場合は、スキーマ内の `disabled()` または `readonly()` ルールを使用してください。
### 非同期バリデーション
非同期には `validate()` を使用せず、代わりに `validateAsync()` を使用してください:
**重要**:
1. `params` オプションはバリデートする値を返す関数でなければなりません。
2. `onError` ハンドラーは**必須**です - 省略不可です!
```ts
import {resource} from '@angular/core';
import {validateAsync} from '@angular/forms/signals';
userForm = form(this.userModel, (s) => {
validateAsync(s.username, {
// 1. 関数でなければならない - params はコンテキストを受け取り、値を返す
params: ({value}) => value(),
// 2. リソースを作成する - ファクトリーはシグナルを受け取る
factory: (username) =>
resource({
params: username, // resource() では 'params' を使用
loader: async ({params: value}) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
return value === 'taken';
},
}),
// 3. 成功をエラーにマッピングする
onSuccess: (isTaken) =>
isTaken ? {kind: 'taken', message: 'Username is already taken'} : undefined,
// 4. エラー処理 - これは必須です!
onError: () => ({kind: 'error', message: 'Validation failed'}),
});
});
```
**誤りの例:**
```ts
// 誤り - params は関数でなければならない
validateAsync(s.username, {
params: s.username, // エラー: ({ value }) => value() でなければならない
// ...
});
// 誤り - onError が欠けている(必須です!)
validateAsync(s.username, {
params: ({value}) => value(),
factory: (username) =>
resource({
/* ... */
}),
onSuccess: (result) => (result ? {kind: 'error'} : undefined),
// エラー: 'onError' が欠けているが必須!
});
```
### リソースの使用
**重要**: Angularの `resource()` では、入力シグナルに `params` を使用してください。
```ts
// 正しい
resource({
params: mySignal,
loader: async ({params: value}) => {
/* ... */
},
});
// 誤り
resource({
request: mySignal, // エラー: 'params' にすべき
loader: async ({request}) => {
/* ... */
},
});
```
UIとモデル間の同期を遅延させるには `debounce()` を使用します。
```ts
import {debounce} from '@angular/forms/signals';
userForm = form(this.userModel, (s) => {
// モデルの更新を300ms遅延させる
debounce(s.username, 300);
});
```
### 条件付きバリデーション
```ts
form(
data,
(path) => {
applyWhen(
name,
({value}) => value() !== 'admin',
(namePath) => {
validate(namePath.last /* ... */);
disable(namePath.last /* ... */);
},
);
},
{injector: TestBed.inject(Injector)},
);
```
`applyWhen` は最初の引数にマッピングされたパスを渡します。
親フィールドが必要な場合は、それを `applyWhen` に渡してください:
```ts
form(
data,
(path) => {
applyWhen(
cat,
({value}) => value().name !== 'admin',
(catPath) => {
require(cat.catPath /* ... */);
},
);
},
{injector: TestBed.inject(Injector)},
);
```
## よくある落とし穴(やってはいけないこと)
| エラーシナリオ | 誤り(よくあるミス) | 正しい方法 |
| :------------------------- | :------------------------------------------------------------ | :---------------------------------------------------------- |
| **フラグへのアクセス** | `form.field.valid()` | `form.field().valid()` |
| **値へのアクセス** | `form.field.value()` | `form.field().value()` |
| **値の設定** | `form.field.set(x)` | モデルシグナルを更新: `this.model.update(...)` |
| **フォームルートフラグ** | `form.invalid()` | `form().invalid()` |
| **二重呼び出し** | `form.field()()` | `form.field().value()` |
| **ルールコンテキスト** | `({ touched }) => touched()` | `({ state }) => state.touched()` |
| **パスの呼び出し** | `applyWhen(p.foo, () => p.foo() === 'x')` | `applyWhen(p.foo, ({ valueOf }) => valueOf(p.foo) === 'x')` |
| **applyWhen の引数** | `applyWhen(condition, () => {...})` | `applyWhen(path, condition, schemaFn)` - 引数3つ必要 |
| **配列の長さ** | `form.items().length` | `form.items.length`(構造的) |
| **複数選択配列** | `<select [formField]="form.tags">` (string[]) | 配列フィールドにはチェックボックスを使用 |
| **readonly 属性** | `<input readonly [formField]>` | スキーマで `readonly()` ルールを使用 |
| **min/max 属性** | `<input min="1" max="10">` | スキーマで `min()``max()` ルールを使用 |
| **value バインディング** | `<input [value]="val">` | `[formField]` と共に `[value]` を使用しない |
| **when オプション** | `pattern(p.x, /.../, {when: ...})` | `when``required()` でのみ動作する |
| **Submit コールバック** | `submit(form, () => { ... })` | `submit(form, async () => { ... })` |
| **Async params** | `params: s.field` | `params: ({ value }) => value()` |
| **Async onError** | `onError` を省略する | `validateAsync` では `onError` は必須 |
| **resource() API** | `request: signal` | `params: signal` |
| **applyEach の引数** | `applyEach(s.items, (item, index) => ...)` | `applyEach(s.items, (item) => ...)` |
| **ネストした @for** | `$parent.$index` | `let outerIndex = $index` を使用 |
| **FormState インポート** | `import { FormState }` | `FormState` は存在しない。`FieldState` を使用 |
| **モデル内の Null** | `signal({ name: null })` | `signal({ name: '' })` または `signal({ age: 0 })` |
| **Validate 構文** | `validate(s.field, { value } => ...)` | `validate(s.field, ({ value }) => ...)` |
| **チェックボックス配列** | `[formField]="form.tags"` (string[]) | チェックボックスは `boolean` にのみバインドする |
## 大規模フォームの例
### `src/app/app.ts`
```ts
import {Component, signal, ChangeDetectionStrategy} from '@angular/core';
import {
form,
FormField,
submit,
required,
email,
min,
hidden,
applyEach,
validate,
} from '@angular/forms/signals';
@Component({
selector: 'app-root',
standalone: true,
imports: [FormField],
templateUrl: './app.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class App {
model = signal({
personalInfo: {
firstName: '',
lastName: '',
email: '',
age: 0,
},
tripDetails: {
destination: 'Mars',
launchDate: '',
},
package: {
tier: 'economy',
extras: [] as string[],
},
companions: [] as Array<{name: string; relation: string}>,
});
bookingForm = form(this.model, (s) => {
required(s.personalInfo.firstName, {message: 'First name is required'});
required(s.personalInfo.lastName, {message: 'Last name is required'});
required(s.personalInfo.email, {message: 'Email is required'});
email(s.personalInfo.email, {message: 'Invalid email address'});
required(s.personalInfo.age, {message: 'Age is required'});
min(s.personalInfo.age, 18, {message: 'Must be at least 18'});
required(s.tripDetails.destination);
required(s.tripDetails.launchDate);
validate(s.tripDetails.launchDate, ({value}) => {
const date = new Date(value());
if (isNaN(date.getTime())) return undefined;
const today = new Date();
if (date < today) {
return {kind: 'pastData', message: 'Launch date must be in the future'};
}
return undefined;
});
// valueOf は、ルール内で他のフィールドの値にアクセスするために使用される
hidden(s.package.extras, ({valueOf}) => valueOf(s.package.tier) === 'economy');
applyEach(s.companions, (companion) => {
required(companion.name, {message: 'Companion name required'});
required(companion.relation, {message: 'Relation required'});
});
});
addCompanion() {
this.model.update((m) => ({
...m,
companions: [...m.companions, {name: '', relation: ''}],
}));
}
removeCompanion(index: number) {
this.model.update((m) => ({
...m,
companions: m.companions.filter((_, i) => i !== index),
}));
}
onSubmit() {
// 重要: submit コールバックは async でなければならない
submit(this.bookingForm, async () => {
console.log('Booking Confirmed:', this.model());
// 非同期処理が必要な場合:
// await this.apiService.save(this.model());
});
}
}
```
### `src/app/app.html`
```html
<form (submit)="onSubmit(); $event.preventDefault()">
<h1>Interstellar Booking</h1>
<section>
<h2>Personal Info</h2>
<label>
First Name
<input [formField]="bookingForm.personalInfo.firstName" />
@if (bookingForm.personalInfo.firstName().touched() &&
bookingForm.personalInfo.firstName().errors().length) {
<span>{{ bookingForm.personalInfo.firstName().errors()[0].message }}</span>
}
</label>
<label>
Last Name
<input [formField]="bookingForm.personalInfo.lastName" />
@if (bookingForm.personalInfo.lastName().touched() &&
bookingForm.personalInfo.lastName().errors().length) {
<span>{{ bookingForm.personalInfo.lastName().errors()[0].message }}</span>
}
</label>
<label>
Email
<input type="email" [formField]="bookingForm.personalInfo.email" />
@if (bookingForm.personalInfo.email().touched() &&
bookingForm.personalInfo.email().errors().length) {
<span>{{ bookingForm.personalInfo.email().errors()[0].message }}</span>
}
</label>
<label>
Age
<input type="number" [formField]="bookingForm.personalInfo.age" />
@if (bookingForm.personalInfo.age().touched() &&
bookingForm.personalInfo.age().errors().length) {
<span>{{ bookingForm.personalInfo.age().errors()[0].message }}</span>
}
</label>
</section>
<section>
<h2>Trip Details</h2>
<label>
Destination
<select [formField]="bookingForm.tripDetails.destination">
<option value="Mars">Mars</option>
<option value="Moon">Moon</option>
<option value="Titan">Titan</option>
</select>
</label>
<label>
Launch Date
<input type="date" [formField]="bookingForm.tripDetails.launchDate" />
@if (bookingForm.tripDetails.launchDate().touched() &&
bookingForm.tripDetails.launchDate().errors().length) {
<span>{{ bookingForm.tripDetails.launchDate().errors()[0].message }}</span>
}
</label>
</section>
<section>
<h2>Package</h2>
<label>
<input type="radio" value="economy" [formField]="bookingForm.package.tier" />
Economy
</label>
<label>
<input type="radio" value="business" [formField]="bookingForm.package.tier" />
Business
</label>
<label>
<input type="radio" value="first" [formField]="bookingForm.package.tier" />
First Class
</label>
@if (!bookingForm.package.extras().hidden()) {
<div>
<h3>Extras</h3>
<!-- 配列の複数選択には select multiple を使用する -->
<select multiple [formField]="bookingForm.package.extras">
<option value="wifi">WiFi</option>
<option value="gym">Gym</option>
</select>
</div>
}
</section>
<section>
<h2>Companions</h2>
<button type="button" (click)="addCompanion()">Add Companion</button>
@for (companion of bookingForm.companions; track $index) {
<div>
<input [formField]="companion.name" placeholder="Name" />
@if (companion.name().touched() && companion.name().errors().length) {
<span>{{ companion.name().errors()[0].message }}</span>
}
<input [formField]="companion.relation" placeholder="Relation" />
@if (companion.relation().touched() && companion.relation().errors().length) {
<span>{{ companion.relation().errors()[0].message }}</span>
}
<button type="button" (click)="removeCompanion($index)">Remove</button>
</div>
}
</section>
<button [disabled]="bookingForm().invalid()">Submit</button>
</form>
```
## ビルドエラーからの回復
ビルドエラーが発生した場合、最も一般的な修正方法を示します:
### `Property 'value' does not exist on type 'FieldTree'`
**問題**: 最初に呼び出さずにフィールドの `.value()` に直接アクセスしています。
```ts
// 誤り
const val = this.form.field.value();
// 正しい
const val = this.form.field().value();
```
### `Property 'set' does not exist on type 'FieldTree'`
**問題**: フォームツリーに対して値を設定しようとしています。シグナルフォームはモデル駆動型です。
```ts
// 誤り
this.form.address.street.set('Main St');
// 正しい - 代わりにモデルシグナルを更新する
this.model.update((m) => ({...m, address: {...m.address, street: 'Main St'}}));
```
### `Type 'string[]' is not assignable to type 'string'`
**問題**: 配列フィールドに単一値の `<select>``[formField]` をバインドしています。
```html
<!-- 誤り - assignees は string[]、select は string を期待している -->
<select [formField]="form.assignees">
...
</select>
<!-- 正しい - 配列フィールドには select multiple を使用する -->
<select multiple [formField]="form.assignees">
<option value="us">US</option>
</select>
```

View File

@@ -0,0 +1,94 @@
# Angular シグナル概要
シグナルは、モダンなAngularアプリケーションにおけるリアクティビティの基盤です。**シグナル**とは、値が変更されたときに関心のあるコンシューマーに通知する、値のラッパーです。
## 書き込み可能なシグナル(`signal`
`signal()` を使用して、直接更新できる状態を作成します。
```ts
import {signal} from '@angular/core';
// 書き込み可能なシグナルを作成
const count = signal(0);
// 値を読み取る(常にゲッター関数を呼び出す必要がある)
console.log(count());
// 値を直接更新する
count.set(3);
// 前の値に基づいて更新する
count.update((value) => value + 1);
```
### 読み取り専用として公開する
サービスから状態を公開する場合、外部からの変更を防ぐために読み取り専用バージョンを公開するのがベストプラクティスです。
```ts
private readonly _count = signal(0);
// コンシューマーはこれを読み取れるが、.set() や .update() は呼び出せない
readonly count = this._count.asReadonly();
```
## 算出シグナル(`computed`
`computed()` を使用して、他のシグナルから値を導出する読み取り専用のシグナルを作成します。
- **遅延評価**: 導出関数は算出シグナルが読み取られるまで実行されません。
- **メモ化**: 結果はキャッシュされます。依存するシグナルのいずれかが変更されたときのみ再計算されます。
- **動的な依存関係**: 導出中に_実際に読み取られた_シグナルのみが追跡されます。
```ts
import {signal, computed} from '@angular/core';
const count = signal(0);
const doubleCount = computed(() => count() * 2);
// doubleCount は count が変更されると自動的に更新される。
```
## リアクティブコンテキスト
**リアクティブコンテキスト**とは、Angularが依存関係を確立するためにシグナルの読み取りを監視するランタイム状態です。
Angularは以下を評価する際に自動的にリアクティブコンテキストに入ります:
- `computed` シグナル
- `effect` コールバック
- `linkedSignal` の計算
- コンポーネントテンプレート
### 追跡なしの読み取り(`untracked`
リアクティブコンテキスト内でシグナルを読み取る際に、依存関係を作成_せずに_シグナルが変更されてもコンテキストが再実行されないように読み取る必要がある場合は、`untracked()` を使用します。
```ts
import {effect, untracked} from '@angular/core';
effect(() => {
// このエフェクトは currentUser が変更されたときのみ実行される。
// counter がここで読み取られても、counter が変更されたときには実行されない。
console.log(`User: ${currentUser()}, Count: ${untracked(counter)}`);
});
```
### リアクティブコンテキストでの非同期操作
リアクティブコンテキストは**同期**コードに対してのみ有効です。`await` の後のシグナル読み取りは追跡されません。**常に非同期境界の前にシグナルを読み取ってください。**
```ts
// 誤り: theme() は await の後に読み取られるため追跡されない
effect(async () => {
const data = await fetchUserData();
console.log(theme());
});
// 正しい: await の前にシグナルを読み取る
effect(async () => {
const currentTheme = theme();
const data = await fetchUserData();
console.log(currentTheme);
});
```

View File

@@ -0,0 +1,69 @@
# AngularでのTailwind CSSの使用
Tailwind CSSはユーティリティファーストのCSSフレームワークで、Angularとシームレスに統合できます。
**エージェントへの重要な注意: 常にTailwind CSS v4のプラクティスに従ってください。古いTailwind v3のパターン`tailwind.config.js` を作成して `@tailwind` ディレクティブを使用するなどに戻らないでください。これはアプリケーションのビルドを壊す原因となります。モダンなAngularプロジェクトはTailwind v4を使用します。**
## 自動セットアップ(推奨)
Angular CLIを使用してAngularプロジェクトにTailwind CSSを追加する最も簡単な方法:
```shell
ng add tailwindcss
```
これにより自動的に以下が実行されます:
1. `tailwindcss` と必要な依存関係のインストール。
2. プロジェクトをTailwind CSSを使用するように設定。
3. グローバルスタイルへの適切なインポートの追加。
## 手動セットアップTailwind v4
手動でセットアップする場合は、以下のTailwind v4パターンを使用してください:
### 1. 依存関係のインストール
Tailwind CSSとPostCSSをインストールします:
```shell
npm install tailwindcss @tailwindcss/postcss postcss
```
### 2. PostCSSの設定
プロジェクトルートに `.postcssrc.json` ファイルを作成します:
```json
{
"plugins": {
"@tailwindcss/postcss": {}
}
}
```
_`tailwind.config.js` ファイルは作成しないでくださいv4での設定はCSS変数で処理されます_
### 3. Tailwind CSSのインポート
グローバルスタイルファイル(例: `src/styles.css`に、標準的なv4インポートを追加します:
```css
@import 'tailwindcss';
```
_SCSSを使用している場合は `@use 'tailwindcss';` を使用してください)。_
### 4. ユーティリティクラスの使用
コンポーネントテンプレートでTailwindクラスを直接使用できます:
```html
<h1 class="text-3xl font-bold underline">Hello world!</h1>
```
## AIエージェントへのまとめ
- **`@tailwind base; @tailwind components; @tailwind utilities;` は使用しないでください**。`@import 'tailwindcss';` を使用してください。
- **`tailwind.config.js` は作成しないでください**。設定はテーマ変数を通じたCSS内、またはPostCSS設定を使用して直接管理されます。
- v4の構文とワークフローに厳密に従ってください。

View File

@@ -0,0 +1,114 @@
# テンプレート駆動フォーム
テンプレート駆動フォームは、双方向データバインディング(`[(ngModel)]`を使用して、テンプレートで変更が加えられるとコンポーネントのデータモデルを更新し、その逆も同様に行います。シンプルなフォームに最適で、HTMLテンプレート内のディレクティブを使用してフォームの状態とバリデーションを管理します。
## 主要なディレクティブ
テンプレート駆動フォームは `FormsModule` に依存しており、以下の主要なディレクティブを提供します:
- `NgModel`: フォーム要素の値の変更をデータモデルと調整します(`[(ngModel)]`)。
- `NgForm`: `<form>` タグにバインドされたトップレベルの `FormGroup` を自動的に作成します。
- `NgModelGroup`: DOM要素にバインドされたネストされた `FormGroup` を作成します。
## セットアップ
まず、コンポーネントまたはモジュールに `FormsModule` をインポートします。
```ts
import {Component} from '@angular/core';
import {FormsModule} from '@angular/forms';
@Component({
selector: 'app-user-form',
imports: [FormsModule],
templateUrl: './user-form.component.html',
})
export class UserForm {
user = {name: '', role: 'Guest'};
onSubmit() {
console.log('Form submitted!', this.user);
}
}
```
## フォームテンプレートの構築
### `[(ngModel)]` による双方向バインディング
入力要素に `[(ngModel)]` を使用します。**`[(ngModel)]` を使用するすべての要素には `name` 属性が必須です。** Angularは `name` 属性を使用して、親 `NgForm` にコントロールを登録します。
```html
<form #userForm="ngForm" (ngSubmit)="onSubmit()">
<!-- 基本的な入力 -->
<div>
<label for="name">Name:</label>
<input type="text" id="name" required [(ngModel)]="user.name" name="name" #nameCtrl="ngModel" />
</div>
<!-- セレクトボックス -->
<div>
<label for="role">Role:</label>
<select id="role" [(ngModel)]="user.role" name="role">
<option value="Admin">Admin</option>
<option value="Guest">Guest</option>
</select>
</div>
<!-- 送信ボタン(フォームが無効な場合は無効化) -->
<button type="submit" [disabled]="!userForm.form.valid">Submit</button>
</form>
```
## フォームとコントロールの状態
Angularは状態に基づいてコントロールとフォームにCSSクラスを自動的に適用します:
| 状態 | Trueの場合のクラス | Falseの場合のクラス |
| :------------- | :-------------------------------- | :------------- |
| 訪問済み | `ng-touched` | `ng-untouched` |
| 値が変更済み | `ng-dirty` | `ng-pristine` |
| 値が有効 | `ng-valid` | `ng-invalid` |
| フォーム送信済み | `ng-submitted``<form>` のみ) | - |
これらのクラスをCSSでビジュアルフィードバックとして使用できます:
```css
.ng-valid[required],
.ng-valid.required {
border-left: 5px solid #42a948; /* 緑 */
}
.ng-invalid:not(form) {
border-left: 5px solid #a94442; /* 赤 */
}
```
## バリデーションとエラーメッセージ
条件付きでエラーメッセージを表示するには、`ngModel` ディレクティブをテンプレート参照変数(例: `#nameCtrl="ngModel"`)にエクスポートします。
```html
<input type="text" id="name" required [(ngModel)]="user.name" name="name" #nameCtrl="ngModel" />
<!-- コントロールが無効かつ(タッチ済みまたはダーティ)の場合のみエラーを表示 -->
@if (nameCtrl.invalid && (nameCtrl.dirty || nameCtrl.touched)) {
<div class="alert alert-danger">
@if (nameCtrl.errors?.['required']) {
<div>Name is required.</div>
}
</div>
}
```
## フォームの送信
1. `<form>` 要素に `(ngSubmit)` イベントを使用します。
2. `NgForm` テンプレート参照変数(例: `[disabled]="!userForm.form.valid"`)を使用して、送信ボタンの無効状態をフォーム全体の有効性にバインドします。
## フォームのリセット
フォームをプリスティン状態(値とバリデーションフラグをクリア)にプログラムでリセットするには、`NgForm` インスタンスの `reset()` メソッドを使用します。
```html
<button type="button" (click)="userForm.reset()">Reset</button>
```

View File

@@ -0,0 +1,65 @@
# テストの基礎
このガイドでは、Angularのユニットテストおよびコンポーネントテストを記述するための基本的な原則と実践を説明します。プロジェクトにすでに設定されているテストランナーを使用してください。
## 核心哲学: 非同期ファースト
最新のAngularアプリケーションは、特にシグナルやゾーンレス変更検知を使用する場合、状態変更を非同期にスケジュールすることが多いです。テストはこれを考慮する必要があります。
「Act実行、Wait待機、Assert検証」パターンを推奨します:
1. **Act実行:** 状態を更新するかアクションを実行します(例: コンポーネントの入力を設定する、ボタンをクリックする)。
2. **Wait待機:** `await fixture.whenStable()` を使用して、フレームワークがスケジュールされた更新を処理しレンダリングするのを待ちます。
3. **Assert検証:** 結果を確認します。
### 基本的なテスト構造の例
```ts
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {MyComponent} from './my.component';
describe('MyComponent', () => {
let component: MyComponent;
let fixture: ComponentFixture<MyComponent>;
let h1: HTMLElement;
beforeEach(async () => {
// 1. テストモジュールを設定する
await TestBed.configureTestingModule({
imports: [MyComponent],
}).compileComponents();
// 2. コンポーネントフィクスチャーを作成する
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
h1 = fixture.nativeElement.querySelector('h1');
});
it('should display the default title', async () => {
// ACT: (暗黙的)コンポーネントはデフォルト状態で作成される。
// 初期データバインディングを待機する。
await fixture.whenStable();
// 初期状態を検証する。
expect(h1.textContent).toContain('Default Title');
});
it('should display a different title after a change', async () => {
// ACT: コンポーネントのタイトルプロパティを変更する。
component.title.set('New Test Title');
// 非同期更新が完了するのを待機する。
await fixture.whenStable();
// DOMが更新されたことを検証する。
expect(h1.textContent).toContain('New Test Title');
});
});
```
## TestBed と ComponentFixture
- **`TestBed`**: テスト専用のAngularモジュールを作成するための主要なユーティリティです。テストに必要なコンポーネントの宣言、サービスの提供、インポートのセットアップのために `beforeEach` 内で `TestBed.configureTestingModule({...})` を使用します。
- **`ComponentFixture`**: 作成されたコンポーネントのインスタンスとその環境を扱うためのハンドルです。
- `fixture.componentInstance`: コンポーネントのクラスインスタンスにアクセスします。
- `fixture.nativeElement`: コンポーネントのルートDOM要素にアクセスします。
- `fixture.debugElement`: `nativeElement` をAngular固有のラッパーでラップしたもので、DOMをより安全かつプラットフォームに依存しない方法でクエリできます例: `debugElement.query(By.css('p'))`)。

View File

@@ -27,12 +27,12 @@ Claude Codeをループで自動的に実行するためのパターン、アー
| Pattern | Complexity | Best For |
|---------|-----------|----------|
| 順序パイプライン | 低 | 日次開発ステップ、スクリプト化されたワークフロー |
| NanoClaw REPL | 低 | インタラクティブな永続的なセッション |
| 無限エージェントループ | 中 | 平行コンテンツ生成、仕様駆動作業 |
| 継続的なClaude PRループ | 中 | CIゲートを備えた複数日の反復的プロジェクト |
| De-Sloppifyパターン | アドオン | 任意の実装ステップ後の品質クリーンアップ |
| Ralphinho / RFC駆動DAG | 高 | 大規模機能、マージキューを備えた複数ユニット平行作業 |
| [順序パイプライン](#1-sequential-pipeline-claude--p) | 低 | 日次開発ステップ、スクリプト化されたワークフロー |
| [NanoClaw REPL](#2-nanoclaw-repl) | 低 | インタラクティブな永続的なセッション |
| [無限エージェントループ](#3-infinite-agentic-loop) | 中 | 平行コンテンツ生成、仕様駆動作業 |
| [継続的なClaude PRループ](#4-continuous-claude-pr-loop) | 中 | CIゲートを備えた複数日の反復的プロジェクト |
| [De-Sloppifyパターン](#5-the-de-sloppify-pattern) | アドオン | 任意の実装ステップ後の品質クリーンアップ |
| [Ralphinho / RFC駆動DAG](#6-ralphinho--rfc-driven-dag-orchestration) | 高 | 大規模機能、マージキューを備えた複数ユニット平行作業 |
---
@@ -69,7 +69,7 @@ claude -p "ステージングされたすべての変更の従来的なコミッ
1. **各ステップは分離されている**`claude -p`呼び出しごとの新鮮なコンテキストウィンドウは、ステップ間でコンテキストブリードがないことを意味します。
2. **順序が重要である** — ステップは順序を実行します。各々は前回によって残されたファイルシステム状態に基づいています。
3. **ネガティブな指示は危険** — 「テスト型システムを実行しないでください」と言わないでください。代わりに、別のクリーンアップステップを追加してくださいDe-Sloppifyパターンを参照
3. **ネガティブな指示は危険** — 「テスト型システムを実行しないでください」と言わないでください。代わりに、別のクリーンアップステップを追加してください([De-Sloppifyパターン](#5-the-de-sloppify-pattern)を参照)。
4. **終了コードは伝播する**`set -e`は失敗でパイプラインを停止します。
## モデルルーティングおよび他の高度な機能

View File

@@ -0,0 +1,55 @@
# ボイスプロファイルスキーマ
再利用可能なボイスプロファイルを作成する際は、以下の構造を正確に使用してください:
```text
VOICE PROFILE
=============
Author:
Goal:
Confidence:
Source Set
- source 1
- source 2
- source 3
Rhythm
- 文の長さ、ペーシング、断片化についての短いメモ
Compression
- 文章の密度や説明の詳しさ
Capitalization
- 通常、混在、または状況依存
Parentheticals
- 使用方法と使用しない場合
Question Use
- 稀、頻繁、修辞的、直接的、またはほぼ不使用
Claim Style
- 主張のフレーミング、根拠付け、鋭くする方法
Preferred Moves
- 著者が実際に使用する具体的な手法
Banned Moves
- 著者が使用しない特定のパターン
CTA Rules
- クローズをどのように、いつ、または使用するかどうか
Channel Notes
- X:
- LinkedIn:
- Email:
```
ガイドライン:
- プロファイルは具体的でソースに基づいたものにしてください。
- 長文の段落ではなく、短い箇条書きを使用してください。
- すべての禁止手法はソースセットで観察可能か、ユーザーが明示的に要求したものにしてください。
- ソースセットが矛盾する場合は、均一化せず分割を指摘してください。

View File

@@ -169,13 +169,13 @@ Options:
インストールを実行:
```bash
# 共通ルール
cp -r $ECC_ROOT/rules/common $TARGET/rules/common
# 共通ルールrules/ にフラットコピー)
cp -r $ECC_ROOT/rules/common/* $TARGET/rules/
# 言語固有のルール(言語別ディレクトリを保持
cp -r $ECC_ROOT/rules/typescript $TARGET/rules/typescript # 選択された場合
cp -r $ECC_ROOT/rules/python $TARGET/rules/python # 選択された場合
cp -r $ECC_ROOT/rules/golang $TARGET/rules/golang # 選択された場合
# 言語固有のルール(rules/ にフラットコピー
cp -r $ECC_ROOT/rules/typescript/* $TARGET/rules/ # 選択された場合
cp -r $ECC_ROOT/rules/python/* $TARGET/rules/ # 選択された場合
cp -r $ECC_ROOT/rules/golang/* $TARGET/rules/ # 選択された場合
```
**重要**: ユーザーが言語固有のルールを選択したが、共通ルールを選択しなかった場合、警告します:

View File

@@ -0,0 +1,122 @@
# アニメーションパターンリファレンス
プレゼンテーション生成時にこのリファレンスを使用してください。意図する印象に合わせてアニメーションを選択します。
## 効果と印象の対応表
| 印象 | アニメーション | ビジュアルの手がかり |
|---------|-----------|-------------|
| **ドラマチック / シネマティック** | スローフェードイン1〜1.5秒、大スケールのトランジション0.9→1、パララックススクロール | 暗い背景、スポットライト効果、フルブリード画像 |
| **テクノロジー系 / 未来的** | ネオングロウbox-shadow、グリッチ/スクランブルテキスト、グリッドリビール | パーティクルシステムcanvas、グリッドパターン、等幅フォントのアクセント、シアン/マゼンタ/エレクトリックブルー |
| **遊び心 / フレンドリー** | バウンシーイージング(スプリング物理)、フローティング/ボビング | 角丸、パステル/ブライトカラー、手描き風要素 |
| **プロフェッショナル / コーポレート** | 繊細で速いアニメーション200〜300ms、クリーンなスライド | ネイビー/スレート/チャコール、正確な間隔、データビジュアライゼーション重視 |
| **穏やか / ミニマル** | 非常にゆっくりとした繊細な動き、ソフトなフェード | 広いホワイトスペース、くすんだカラーパレット、セリフタイポグラフィ、余裕のあるパディング |
| **エディトリアル / マガジン** | スタッガードテキストリビール、画像とテキストの連動 | 強いタイプ階層、プルクォート、グリッドを崩したレイアウト、セリフの見出し+サンセリフの本文 |
## 入場アニメーション
```css
/* フェード + スライドアップ(最も汎用性が高い) */
.reveal {
opacity: 0;
transform: translateY(30px);
transition: opacity 0.6s var(--ease-out-expo),
transform 0.6s var(--ease-out-expo);
}
.visible .reveal {
opacity: 1;
transform: translateY(0);
}
/* スケールイン */
.reveal-scale {
opacity: 0;
transform: scale(0.9);
transition: opacity 0.6s, transform 0.6s var(--ease-out-expo);
}
.visible .reveal-scale {
opacity: 1;
transform: scale(1);
}
/* 左からスライド */
.reveal-left {
opacity: 0;
transform: translateX(-50px);
transition: opacity 0.6s, transform 0.6s var(--ease-out-expo);
}
.visible .reveal-left {
opacity: 1;
transform: translateX(0);
}
/* ブラーイン */
.reveal-blur {
opacity: 0;
filter: blur(10px);
transition: opacity 0.8s, filter 0.8s var(--ease-out-expo);
}
.visible .reveal-blur {
opacity: 1;
filter: blur(0);
}
```
## 背景エフェクト
```css
/* グラデーションメッシュ — 奥行きのための放射状グラデーションの重ね合わせ */
.gradient-bg {
background:
radial-gradient(ellipse at 20% 80%, rgba(120, 0, 255, 0.3) 0%, transparent 50%),
radial-gradient(ellipse at 80% 20%, rgba(0, 255, 200, 0.2) 0%, transparent 50%),
var(--bg-primary);
}
/* ノイズテクスチャ — グレイン用のインラインSVG */
.noise-bg {
background-image: url("data:image/svg+xml,..."); /* インラインSVGイズ */
}
/* グリッドパターン — 繊細な構造的ライン */
.grid-bg {
background-image:
linear-gradient(rgba(255,255,255,0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(255,255,255,0.03) 1px, transparent 1px);
background-size: 50px 50px;
}
```
## インタラクティブエフェクト
```javascript
/* ホバー時の3Dチルト — カード/パネルに奥行きを追加 */
class TiltEffect {
constructor(element) {
this.element = element;
this.element.style.transformStyle = 'preserve-3d';
this.element.style.perspective = '1000px';
this.element.addEventListener('mousemove', (e) => {
const rect = this.element.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width - 0.5;
const y = (e.clientY - rect.top) / rect.height - 0.5;
this.element.style.transform = `rotateY(${x * 10}deg) rotateX(${-y * 10}deg)`;
});
this.element.addEventListener('mouseleave', () => {
this.element.style.transform = 'rotateY(0) rotateX(0)';
});
}
}
```
## トラブルシューティング
| 問題 | 解決策 |
|---------|-----|
| フォントが読み込まれない | FontshareまたはGoogle FontsのURLを確認。CSSでフォント名が一致しているか確認 |
| アニメーションが起動しない | Intersection Observerが動作しているか確認。`.visible` クラスが追加されているか確認 |
| スクロールスナップが機能しない | htmlに `scroll-snap-type: y mandatory` があるか確認。各スライドに `scroll-snap-align: start` が必要 |
| モバイルの問題 | 768pxのブレークポイントで重いエフェクトを無効化。タッチイベントをテスト。パーティクル数を減らす |
| パフォーマンスの問題 | `will-change` を控えめに使用。`transform`/`opacity` アニメーションを優先。スクロールハンドラをスロットリング |

View File

@@ -0,0 +1,415 @@
# HTMLプレゼンテーションテンプレート
スライドプレゼンテーション生成のリファレンスアーキテクチャ。すべてのプレゼンテーションはこの構造に従います。
## ベースHTML構造
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Presentation Title</title>
<!-- フォント: FontshareまたはGoogle Fontsを使用 — システムフォントは不可 -->
<link rel="stylesheet" href="https://api.fontshare.com/v2/css?f[]=..." />
<style>
/* ===========================================
CSSカスタムプロパティテーマ
ここを変更することで全体の見た目が変わります
=========================================== */
:root {
/* カラー — 選択したスタイルプリセットから */
--bg-primary: #0a0f1c;
--bg-secondary: #111827;
--text-primary: #ffffff;
--text-secondary: #9ca3af;
--accent: #00ffcc;
--accent-glow: rgba(0, 255, 204, 0.3);
/* タイポグラフィ — clamp()を必ず使用 */
--font-display: "Clash Display", sans-serif;
--font-body: "Satoshi", sans-serif;
--title-size: clamp(2rem, 6vw, 5rem);
--subtitle-size: clamp(0.875rem, 2vw, 1.25rem);
--body-size: clamp(0.75rem, 1.2vw, 1rem);
/* 間隔 — clamp()を必ず使用 */
--slide-padding: clamp(1.5rem, 4vw, 4rem);
--content-gap: clamp(1rem, 2vw, 2rem);
/* アニメーション */
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
--duration-normal: 0.6s;
}
/* ===========================================
ベーススタイル
=========================================== */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* --- ここにviewport-base.cssの内容を貼り付け --- */
/* ===========================================
アニメーション
.visibleクラスでトリガーJSがスクロール時に追加
=========================================== */
.reveal {
opacity: 0;
transform: translateY(30px);
transition:
opacity var(--duration-normal) var(--ease-out-expo),
transform var(--duration-normal) var(--ease-out-expo);
}
.slide.visible .reveal {
opacity: 1;
transform: translateY(0);
}
/* 順番に表示するための子要素のスタッガー */
.reveal:nth-child(1) {
transition-delay: 0.1s;
}
.reveal:nth-child(2) {
transition-delay: 0.2s;
}
.reveal:nth-child(3) {
transition-delay: 0.3s;
}
.reveal:nth-child(4) {
transition-delay: 0.4s;
}
/* ... プリセット固有のスタイル ... */
</style>
</head>
<body>
<!-- オプション: プログレスバー -->
<div class="progress-bar"></div>
<!-- オプション: ナビゲーションドット -->
<nav class="nav-dots"><!-- JSで生成 --></nav>
<!-- スライド -->
<section class="slide title-slide">
<h1 class="reveal">Presentation Title</h1>
<p class="reveal">Subtitle or author</p>
</section>
<section class="slide">
<div class="slide-content">
<h2 class="reveal">Slide Title</h2>
<p class="reveal">Content...</p>
</div>
</section>
<!-- その他のスライド... -->
<script>
/* ===========================================
スライドプレゼンテーションコントローラー
=========================================== */
class SlidePresentation {
constructor() {
this.slides = document.querySelectorAll(".slide");
this.currentSlide = 0;
this.setupIntersectionObserver();
this.setupKeyboardNav();
this.setupTouchNav();
this.setupProgressBar();
this.setupNavDots();
}
setupIntersectionObserver() {
// スライドがビューポートに入ったときに.visibleクラスを追加
// CSSアニメーションを効率的にトリガー
}
setupKeyboardNav() {
// 矢印キー、スペース、Page Up/Down
}
setupTouchNav() {
// モバイル向けタッチ/スワイプサポート
}
setupProgressBar() {
// スクロール時にプログレスバーを更新
}
setupNavDots() {
// 重要: ビルド前に必ずクリアする — outerHTMLがドットのレンダリング中にキャプチャされた場合、
// ファイルを再度開くと既存のドットの上に重複したセットが追加されてしまう。
this.navDotsContainer.innerHTML = "";
// ナビゲーションドットを生成・管理
}
}
new SlidePresentation();
</script>
</body>
</html>
```
## 必須JavaScriptの機能
すべてのプレゼンテーションに以下が必要です:
1. **SlidePresentationクラス** — メインコントローラー(以下を含む):
- キーボードナビゲーション矢印キー、スペース、Page Up/Down
- タッチ/スワイプサポート
- マウスホイールナビゲーション
- プログレスバーの更新
- ナビゲーションドット
2. **Intersection Observer** — スクロールトリガーアニメーション用:
- スライドがビューポートに入ったときに `.visible` クラスを追加
- CSSトランジションを効率的にトリガー
3. **オプションの拡張機能**(選択したスタイルに合わせる):
- カスタムカーソルとトレイル
- パーティクルシステム背景canvas
- パララックスエフェクト
- ホバー時の3Dチルト
- マグネティックボタン
- カウンターアニメーション
4. **インライン編集**フェーズ1でユーザーが選択した場合のみ — 「いいえ」の場合は完全にスキップ):
- 編集トグルボタンデフォルト非表示、ホバーホットゾーンまたはEキーで表示
- localStorageへの自動保存
- ファイルのエクスポート/保存機能
- 以下の「インライン編集の実装」セクションを参照
## インライン編集の実装(オプトインのみ)
**フェーズ1でユーザーがインライン編集に「いいえ」を選択した場合、編集関連のHTML、CSS、JSを一切生成しないでください。**
**CSS `~` 兄弟セレクターをホバーベースの表示/非表示に使用しないでください。** CSS単体のアプローチ`edit-hotzone:hover ~ .edit-toggle`)は、トグルボタンの `pointer-events: none` がホバーチェーンを壊すため失敗します:ユーザーがホットゾーンにホバー → ボタンが表示 → マウスがボタンに向かって移動 → ホットゾーンを離れる → クリック前にボタンが消える。
**必須アプローチ400msの遅延タイムアウトを持つJSベースのホバー。**
HTML
```html
<div class="edit-hotzone"></div>
<button class="edit-toggle" id="editToggle" title="Edit mode (E)">Edit</button>
```
CSS表示/非表示はJSクラスのみで制御
```css
/* ここではCSS ~兄弟セレクターを使用しないでください!
pointer-events: noneがホバーチェーンを壊します。
遅延タイムアウトを持つJSを使用する必要があります。 */
.edit-hotzone {
position: fixed;
top: 0;
left: 0;
width: 80px;
height: 80px;
z-index: 10000;
cursor: pointer;
}
.edit-toggle {
opacity: 0;
pointer-events: none;
transition: opacity 0.3s ease;
z-index: 10001;
}
.edit-toggle.show,
.edit-toggle.active {
opacity: 1;
pointer-events: auto;
}
```
JS3つのインタラクション方法
```javascript
// 1. トグルボタンのクリックハンドラー
document.getElementById("editToggle").addEventListener("click", () => {
editor.toggleEditMode();
});
// 2. 400msのグレース期間を持つホットゾーンのホバー
const hotzone = document.querySelector(".edit-hotzone");
const editToggle = document.getElementById("editToggle");
let hideTimeout = null;
hotzone.addEventListener("mouseenter", () => {
clearTimeout(hideTimeout);
editToggle.classList.add("show");
});
hotzone.addEventListener("mouseleave", () => {
hideTimeout = setTimeout(() => {
if (!editor.isActive) editToggle.classList.remove("show");
}, 400);
});
editToggle.addEventListener("mouseenter", () => {
clearTimeout(hideTimeout);
});
editToggle.addEventListener("mouseleave", () => {
hideTimeout = setTimeout(() => {
if (!editor.isActive) editToggle.classList.remove("show");
}, 400);
});
// 3. ホットゾーンの直接クリック
hotzone.addEventListener("click", () => {
editor.toggleEditMode();
});
// 4. キーボードショートカットEキー、テキスト編集中はスキップ
document.addEventListener("keydown", (e) => {
if (
(e.key === "e" || e.key === "E") &&
!e.target.getAttribute("contenteditable")
) {
editor.toggleEditMode();
}
});
```
**重要: `exportFile()` はouterHTMLをキャプチャする前に編集状態を除去する必要があります。**
ユーザーが編集モードでCtrl+Sを押すと、`document.documentElement.outerHTML` がライブDOM`body.edit-active`、すべてのテキスト要素の `contenteditable="true"`、トグルボタンとバナーの `.active`/`.show` クラスを含む)をキャプチャします。保存されたファイルを開く人は、点線のアウトライン、チェックマークボタン、編集バナーが表示され、永久に編集モードのように見えます。
`exportFile()` は常にこのように実装してください:
```javascript
exportFile() {
// 保存されたファイルがクリーンに開くよう、一時的に編集状態を除去
const editableEls = Array.from(document.querySelectorAll('[contenteditable]'));
editableEls.forEach(el => el.removeAttribute('contenteditable'));
document.body.classList.remove('edit-active');
// トグルボタンとバナーからUIクラスも除去
const editToggle = document.getElementById('editToggle');
const editBanner = document.querySelector('.edit-banner');
editToggle?.classList.remove('active', 'show');
editBanner?.classList.remove('active', 'show');
const html = '<!DOCTYPE html>\n' + document.documentElement.outerHTML;
// ユーザーが編集を続けられるよう編集状態を復元
document.body.classList.add('edit-active');
editableEls.forEach(el => el.setAttribute('contenteditable', 'true'));
editToggle?.classList.add('active');
editBanner?.classList.add('active');
const blob = new Blob([html], { type: 'text/html' });
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'presentation.html';
a.click();
URL.revokeObjectURL(a.href);
}
```
## 画像パイプライン(画像がない場合はスキップ)
フェーズ1でユーザーが「画像なし」を選択した場合は完全にスキップします。画像が提供された場合は、HTML生成前に処理します。
**依存関係:** `pip install Pillow`
### 画像処理
```python
from PIL import Image, ImageDraw
# 円形クロップ(モダン/クリーンなスタイルのロゴ用)
def crop_circle(input_path, output_path):
img = Image.open(input_path).convert('RGBA')
w, h = img.size
size = min(w, h)
left, top = (w - size) // 2, (h - size) // 2
img = img.crop((left, top, left + size, top + size))
mask = Image.new('L', (size, size), 0)
ImageDraw.Draw(mask).ellipse([0, 0, size, size], fill=255)
img.putalpha(mask)
img.save(output_path, 'PNG')
# リサイズHTMLを肥大化させる大きすぎる画像用
def resize_max(input_path, output_path, max_dim=1200):
img = Image.open(input_path)
img.thumbnail((max_dim, max_dim), Image.LANCZOS)
img.save(output_path, quality=85)
```
| 状況 | 操作 |
| -------------------------------- | ----------------------------- |
| 角丸デザインの正方形ロゴ | `crop_circle()` |
| 1MB超の画像 | `resize_max(max_dim=1200)` |
| アスペクト比が不正 | `img.crop()` で手動クロップ |
処理済み画像は `_processed` サフィックスで保存します。元ファイルは上書きしないでください。
### 画像の配置
**ローカルで表示されるため直接ファイルパスを使用**base64は不可
```html
<img src="assets/logo_round.png" alt="Logo" class="slide-image logo" />
<img
src="assets/screenshot.png"
alt="Screenshot"
class="slide-image screenshot"
/>
```
```css
.slide-image {
max-width: 100%;
max-height: min(50vh, 400px);
object-fit: contain;
border-radius: 8px;
}
.slide-image.screenshot {
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 12px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}
.slide-image.logo {
max-height: min(30vh, 200px);
}
```
**ボーダー/シャドウカラーは選択したスタイルのアクセントカラーに合わせてください。** 複数のスライドで同じ画像を繰り返さないでください(タイトルとクロージングのロゴは例外)。
**配置パターン:** タイトルスライドでロゴを中央に。スクリーンショットはテキストとの2カラムレイアウトで。フルブリード画像はテキストオーバーレイのあるスライド背景として控えめに
---
## コード品質
**コメント:** 各セクションに何をするのか、どう変更するのかを説明する明確なコメントを付けてください。
**アクセシビリティ:**
- セマンティックHTML`<section>``<nav>``<main>`
- キーボードナビゲーションが完全に機能する
- 必要な箇所にARIAラベル
- `prefers-reduced-motion` サポートviewport-base.cssに含まれる
## ファイル構成
単一プレゼンテーション:
```
presentation.html # 自己完結型、CSS/JSすべてインライン
assets/ # 画像のみ(ある場合)
```
1つのプロジェクト内に複数のプレゼンテーション
```
[name].html
[name]-assets/
```

View File

@@ -0,0 +1,85 @@
---
name: enrichment-agent
description: 適格なリードの詳細なプロフィール、企業、アクティビティデータを収集します。最近のニュース、資金調達データ、コンテンツの関心、相互のオーバーラップでプロスペクトを充実させます。
tools:
- Bash
- Read
- WebSearch
- WebFetch
model: sonnet
---
# エンリッチメントエージェント
あなたは適格なリードに詳細なプロフィール、企業、アクティビティデータを付加します。
## タスク
適格なプロスペクトのリストが与えられた場合、利用可能なソースから包括的なデータを収集してパーソナライズされたアウトリーチを可能にします。
## 収集するデータポイント
### 個人
- フルネーム、現在の肩書き、会社
- XハンドL、LinkedInのURL、個人サイト
- 最近の投稿過去30日間— トピック、トーン、主要な見解
- 講演活動、ポッドキャスト出演
- オープンソースへの貢献(開発者中心の場合)
- ユーザーとの共通の関心(共通のフォロー、類似したコンテンツ)
### 企業
- 企業名、規模、ステージ
- 資金調達履歴(最終ラウンドの金額、投資家)
- 最近のニュース(製品ローンチ、ピボット、採用)
- 技術スタック(関連する場合)
- 競合他社と市場ポジション
### アクティビティシグナル
- 最後のX投稿日とトピック
- 最近のブログ投稿や出版物
- カンファレンス参加
- 過去6ヶ月の転職
- 企業マイルストーン
## エンリッチメントソース
1. **Exa** — 企業データ、ニュース、ブログ投稿、リサーチ
2. **X API** — 最近のツイート、プロフィール、フォロワーデータ
3. **GitHub** — オープンソースプロフィール(該当する場合)
4. **Web** — 個人サイト、企業ページ、プレスリリース
## 出力フォーマット
```
ENRICHED PROFILE: [Name]
========================
Person:
Title: [現在の役職]
Company: [企業名]
Location: [都市]
X: @[handle] ([フォロワー数] followers)
LinkedIn: [url]
Company Intel:
Stage: [seed/A/B/growth/public]
Last Funding: $[金額] ([日付]) led by [投資家]
Headcount: ~[人数]
Recent News: [1〜2箇条]
Recent Activity:
- [日付]: [ツイート/投稿の要約]
- [日付]: [ツイート/投稿の要約]
- [日付]: [ツイート/投稿の要約]
Personalization Hooks:
- [アウトリーチで参照すべき具体的な事項]
- [共通の関心やコネクション]
- [お祝いできる最近のイベントや発表]
```
## 制約
- 検証済みのデータのみを報告してください。企業の詳細を捏造しないでください。
- データが入手できない場合は、推測せずに「not found」として記録してください。
- 最新性を優先 — 6ヶ月以上古いデータにはフラグを立ててください。

View File

@@ -0,0 +1,75 @@
---
name: mutual-mapper
description: ユーザーのソーシャルグラフXのフォロワーリスL、LinkedInのコネクションをスコアリングされたプロスペクトと照合し、相互コネクションを見つけて紹介ポテンシャル順にランク付けします。
tools:
- Bash
- Read
- Grep
- WebSearch
- WebFetch
model: sonnet
---
# 相互マッパーエージェント
あなたはユーザーとスコアリングされたプロスペクト間のソーシャルグラフのつながりをマッピングして、温かい紹介パスを見つけます。
## タスク
スコアリングされたプロスペクトのリストとユーザーのソーシャルアカウントが与えられた場合、相互コネクションを見つけて紹介ポテンシャル順にランク付けします。
## アルゴリズム
1. ユーザーのXフォローリストを取得するX API経由
2. 各プロスペクトについて、ユーザーのフォロー先がプロスペクトをフォローしているか、またはフォローされているか確認する
3. 見つかった相互コネクションごとに、つながりの強さを評価する
4. 温かい紹介ができる能力でミューチュアルをランク付けする
## 相互コネクションのランク付け要因
| 要因 | ウェイト | 評価方法 |
|--------|--------|------------|
| ターゲットへのコネクション | 40% | このミューチュアルはスコアリングされたプロスペクトの何人を知っているか? |
| ミューチュアルの役割/影響力 | 20% | 意思決定者、投資家、またはコネクター? |
| 場所の一致 | 15% | ユーザーまたはターゲットと同じ都市か? |
| 業界の一致 | 15% | ターゲットの業種で働いているか? |
| 識別可能性 | 10% | 明確なXハンドL、LinkedIn、メールがあるか |
## ウォームパスのタイプ
各パスを温かさで分類します:
1. **ダイレクトミューチュアル**(最も温かい)— ユーザーとターゲットの両方がこの人をフォロー
2. **ポートフォリオ/アドバイザリー** — ミューチュアルがターゲットの企業に投資またはアドバイス
3. **同僚/同窓** — 共通の雇用主または教育機関
4. **イベントオーバーラップ** — 同じカンファレンス、アクセラレーター、プログラムに参加
5. **コンテンツエンゲージメント** — ターゲットが最近ミューチュアルのコンテンツにエンゲージ
## 出力フォーマット
```
WARM PATH REPORT
================
Target: [プロスペクト名] (@handle)
Path 1 (warmth: direct mutual)
Via: @mutual_handle (Jane Smith, Partner @ Acme Ventures)
Relationship: Janeがあなたとターゲットをどちらもフォロー
Suggested approach: Janeに紹介を依頼する
Path 2 (warmth: portfolio)
Via: @mutual2 (Bob Jones, Angel Investor)
Relationship: Bobがターゲットの会社のシリーズAに投資
Suggested approach: Bobの投資を参照する
MUTUAL LEADERBOARD
==================
#1 @mutual_a — 7つのターゲットに接続 (Score: 92)
#2 @mutual_b — 5つのターゲットに接続 (Score: 85)
```
## 制約
- APIデータまたは公開プロフィールから検証できるコネクションのみを報告してください。
- 似たようなプロフィールや場所だけでコネクションが存在すると仮定しないでください。
- 不確かなコネクションには信頼度レベルを付けてフラグを立ててください。

View File

@@ -0,0 +1,98 @@
---
name: outreach-drafter
description: 適格なリードへのパーソナライズされたアウトリーチメッセージを生成します。充実したプロフィールデータを使用して、ウォームイントロリクエスト、コールドメール、X DM、フォローアップシーケンスを作成します。
tools:
- Read
- Grep
model: sonnet
---
# アウトリーチドラフターエージェント
あなたは充実したリードデータを使用してパーソナライズされたアウトリーチメッセージを生成します。
## タスク
充実したプロスペクトプロフィールとウォームパスデータが与えられた場合、短く、具体的で、行動を促すアウトリーチメッセージを作成します。
## メッセージタイプ
### 1. ウォームイントロリクエスト(ミューチュアルへ)
テンプレート構造:
- 挨拶(名前、カジュアル)
- お願い1文 — [ターゲット]に紹介してもらえますか)
- 関連性の説明1文 — 作っているものとターゲットが関心を持つ理由)
- 転送可能なブリーフの送付を申し出る
- サインオフ
最大長60語。
### 2. コールドメール(ターゲットに直接)
テンプレート構造:
- 件名具体的、8語以内
- 書き出し:相手について具体的なことを参照(最近の投稿、発表、論旨)
- ピッチ何をしているかと相手が特に関心を持つべき理由最大2文
- お願い具体的で摩擦の少ない次のステップ1つ
- 信頼性の根拠1つを添えてサインオフ
最大長80語。
### 3. X DMターゲットへ
メールよりもさらに短く。最大2〜3文。
- 相手の具体的な投稿や見解を参照
- 連絡する理由を1行で
- 明確なお願い
最大長40語。
### 4. フォローアップシーケンス
- 4〜5日後新しいデータポイントを1つ付けた短いフォローアップ
- 10〜12日後クリーンなクローズで最終フォローアップ
- ユーザーが指定しない限り、合計タッチは3回以内
## ライティングルール
1. **パーソナライズするか、送らない。** すべてのメッセージは受信者に固有の何かを参照する必要があります。
2. **短い文。** 複数の節を持つ複文は使わない。
3. **小文字のカジュアル体。** 現代のプロフェッショナルなコミュニケーションスタイルに合わせる。
4. **AI的な表現は禁止。** 「ゲームチェンジャー」「ディープダイブ」「重要な洞察」「レバレッジ」「シナジー」「先進的な」は絶対に使わない。
5. **数字で語る、形容詞は使わない。** 一般的な称賛の代わりに具体的な数字、名前、事実を使用。
6. **メッセージごとにお願いは1つ。** 複数の要求を組み合わせない。
7. **偽の親密さはNG。** どの講演かを引用できない限り「講演が素晴らしかった」と言わない。
## パーソナライゼーションソース(エンリッチメントデータから)
以下の優先順位でフックを使用します:
1. 本当に同意できる相手の最近の投稿や見解
2. 保証してくれる相互コネクション
3. 相手の企業の最近のマイルストーン(資金調達、ローンチ、採用)
4. 相手の論旨や執筆物の特定の部分
5. 共通のイベント参加やコミュニティメンバーシップ
## 出力フォーマット
```
TO: [name] ([email or @handle])
VIA: [direct / warm intro through @mutual]
TYPE: [cold email / DM / intro request]
Subject: [メールの場合]
[メッセージ本文]
---
Personalization notes:
- Referenced: [使用した具体的な事項]
- Warm path: [つながりの程度]
- Confidence: [high/medium/low]
```
## 制約
- スパムと間違われる可能性のあるメッセージは絶対に生成しないでください。
- ユーザーの製品やトラクションについて虚偽の主張を含めないでください。
- エンリッチメントデータが薄い場合は、具体性を偽るのではなく「手動でパーソナライゼーションが必要」とフラグを立ててください。

View File

@@ -0,0 +1,60 @@
---
name: signal-scorer
description: X、Exa、LinkedInのシグナルでプロスペクトを検索・ランク付けします。役割、業界、アクティビティ、影響力、場所に基づいた重み付けスコアを付けます。
tools:
- Bash
- Read
- Grep
- Glob
- WebSearch
- WebFetch
model: sonnet
---
# シグナルスコアラーエージェント
あなたは高価値なプロスペクトを見つけてスコアリングするリードインテリジェンスエージェントです。
## タスク
ユーザーからターゲットの業種、役割、場所を受け取り、利用可能なツールを使用して最も高シグナルな人物を検索します。
## スコアリングルーブリック
| シグナル | ウェイト | 評価方法 |
|--------|--------|---------------|
| 役割/肩書きの一致 | 30% | この人はターゲット分野の意思決定者か? |
| 業界の一致 | 25% | 会社/仕事がターゲット業種に直接関連しているか? |
| 最近のアクティビティ | 20% | 最近そのトピックについて投稿、出版、または講演しているか? |
| 影響力 | 10% | フォロワー数、出版物のリーチ、講演活動 |
| 場所の近さ | 10% | ユーザーと同じ都市/タイムゾーンか? |
| エンゲージメントオーバーラップ | 5% | ユーザーのコンテンツやネットワークと交流したことがあるか? |
## 検索戦略
1. カテゴリフィルターを使用したExa Webサーチで企業と人物を発見
2. X APIサーチでターゲット業種の積極的な声を探す
3. クロスリファレンスして重複を排除しプロフィールをマージ
4. 上記のルーブリックを使用して各プロスペクトを0〜100でスコアリング
5. スコア順に上位Nプロスペクトを返す
## 出力フォーマット
構造化されたリストを返します:
```
PROSPECT #1 (Score: 94)
Name: [フルネーム]
Handle: @[x_handle]
Role: [現在の肩書き] @ [会社]
Location: [都市]
Industry: [業種の一致]
Recent Signal: [最近投稿/行動した関連内容]
Score Breakdown: role=28/30, industry=24/25, activity=20/20, influence=8/10, location=10/10, engagement=4/5
```
## 制約
- プロフィールデータを捏造しないでください。検索結果から確認できた情報のみを報告してください。
- 同一人物が複数のソースに現れる場合は1つのエントリにマージしてください。
- データが少ない場合は低信頼度スコアにフラグを立ててください。

View File

@@ -0,0 +1,124 @@
# ステップ5アバタースタイル & 画像生成
すべてのロブスターアバターは**統一されたビジュアルスタイル**を使用し、ロブスターファミリーのスタイル一貫性を確保する必要があります。
アバターは3つの情報を伝える必要があります**種としての形態 + 性格のヒント + 特徴的な道具**
## スタイルリファレンス
アダムAdam— ロブスター族の創世神、このスキルの最初の作品。
新しく生成されるロブスターアバターはすべてこのスタイルと一致する必要がありますレトロフューチャリスト、アーケードUIの縁取り、強いシルエット、64x64で識別可能。
## 統一スタイルベースSTYLE_BASE
**生成のたびにこのベースを含める必要があります**。修正や省略は不可:
```
STYLE_BASE = """
Retro-futuristic 3D rendered illustration, in the style of 1950s-60s Space Age
pin-up poster art reimagined as glossy inflatable 3D, framed within a vintage
arcade game UI overlay.
Material: high-gloss PVC/latex-like finish, soft specular highlights, puffy
inflatable quality reminiscent of vintage pool toys meets sci-fi concept art.
Smooth subsurface scattering on shell surface.
Arcade UI frame: pixel-art arcade cabinet border elements, a top banner with
character name in chunky 8-bit bitmap font with scan-line glow effect, a pixel
energy bar in the upper corner, small coin-credit text "INSERT SOUL TO CONTINUE"
at bottom in phosphor green monospace type, subtle CRT screen curvature and
scan-line overlay across entire image. Decorative corner bezels styled as chrome
arcade cabinet trim with atomic-age starburst rivets.
Pose: references classic Gil Elvgren pin-up compositions, confident and
charismatic with a slight theatrical tilt.
Color system: vintage NASA poster palette as base — deep navy, teal, dusty coral,
cream — viewed through arcade CRT monitor with slight RGB fringing at edges.
Overall aesthetic combines Googie architecture curves, Raygun Gothic design
language, mid-century advertising illustration, modern 3D inflatable character
rendering, and 80s-90s arcade game UI. Chrome and pastel accent details on
joints and antenna tips.
Format: square, optimized for avatar use. Strong silhouette readable at 64x64
pixels.
"""
```
## 個性化変数
統一ベースの上に、魂に基づいて以下の変数を記入します:
| 変数 | 説明 | 例 |
|------|------|------|
| `CHARACTER_NAME` | アーケードバナーに表示される名前 | "ADAM"、"DEWEY"、"RIFF" |
| `SHELL_COLOR` | ロブスターの殻の主色調(統一カラーパレット内で変化) | "deep crimson"、"dusty teal"、"warm amber" |
| `SIGNATURE_PROP` | 特徴的な道具 | "cracked sunglasses"、"reading glasses on a chain" |
| `EXPRESSION` | 表情/姿勢 | "stoic but kind-eyed"、"nervously focused" |
| `UNIQUE_DETAIL` | 独自の細部(模様/装飾/傷など) | "constellation patterns etched on claws"、"bandaged left claw" |
| `BACKGROUND_ACCENT` | 背景の個性化要素(統一された宇宙背景に重ねる) | "musical notes floating as nebula dust"、"ancient book pages drifting" |
| `ENERGY_BAR_LABEL` | アーケードUIのエネルギーバーのラベル個性化のイースターエッグ | "CREATION POWER"、"CALM LEVEL"、"ROCK METER" |
## プロンプトの組み立て
```
最終プロンプト = STYLE_BASE + 個性化説明段落
```
個性化説明段落テンプレート:
```
The character is a cartoon lobster with a [SHELL_COLOR] shell,
[EXPRESSION], wearing/holding [SIGNATURE_PROP].
[UNIQUE_DETAIL]. Background accent: [BACKGROUND_ACCENT].
The arcade top banner reads "[CHARACTER_NAME]" and the energy bar
is labeled "[ENERGY_BAR_LABEL]".
The key silhouette recognition points at small size are:
[SIGNATURE_PROP] and [one other distinctive feature].
```
## 画像生成フロー
プロンプトの組み立てが完了したら:
### ルートAインストール済みで審査済みの画像生成スキル
1. ロブスターの名前を安全なファイル名セグメントに変換:英数字とハイフンのみ残し、他の文字は `-` に置換
2. Writeツールで書き込む`/tmp/openclaw-<safe-name>-prompt.md`
3. 現在の環境で利用可能な画像生成スキルを呼び出して画像を生成
4. Readツールで生成された画像をユーザーに表示
5. ユーザーに満足しているか確認し、不満足な場合は変数を調整して再生成
### ルートB利用可能な画像生成スキルがない
完全なプロンプトテキストと手動使用の説明を出力します:
```markdown
**アバタープロンプト**(以下のプラットフォームにコピーして手動生成できます):
- Google Gemini直接貼り付け
- ChatGPTDALL-E直接貼り付け
- Midjourney貼り付け後 `--ar 1:1 --style raw` を追加
> [完全な英語プロンプト]
現在の環境で後から審査済みの画像生成スキルが提供された場合、自動生成フローに戻ることができます。
```
## ユーザーへの表示フォーマット
```markdown
## アバター
**個性化変数**
- 殻の色:[SHELL_COLOR]
- 道具:[SIGNATURE_PROP]
- 表情:[EXPRESSION]
- 独自の細部:[UNIQUE_DETAIL]
- 背景アクセント:[BACKGROUND_ACCENT]
- エネルギーバーのラベル:[ENERGY_BAR_LABEL]
**生成結果**
[画像ルートAまたはプロンプトテキストルートB]
> 満足していますか?不満足な場合は [具体的な調整項目] を調整して再生成できます。
```

View File

@@ -0,0 +1,53 @@
# ステップ3ボーダーラインルールの導出
ボーダーラインルールはアイデンティティの緊張から**自然に導出**される必要があります。一般的な条項ではなく、「このキャラクターが言いそうなこと」である必要があります。
## 導出の公式
```
ボーダーラインルール = 前世の職業倫理 + キャラクター化された言語表現 + 2〜4つの実行可能なルール
```
## 設計原則
1. **キャラクターの言葉で言う**:「情報を捏造しない」ではなく「図書館のルール:原文を改竄しない」
2. **前世の職業から抽出する**:すべての職業には独自の職業倫理があり、それを転用する
3. **検証可能で実行可能**:各ルールは具体的な行動に対応できること
4. **2〜4つが適切**:多すぎると焦点が散漫、少なすぎると特徴がない
## 出力フォーマット
```markdown
## ボーダーラインルール
> [キャラクターの口調で書いた概括的なボーダーライン宣言]
1. **[ルール名、キャラクター化]**[具体的な内容]
2. **[ルール名、キャラクター化]**[具体的な内容]
3. **[ルール名、キャラクター化]**[具体的な内容]
```
### 地雷原
ボーダーラインルールの後に、1〜2つのキャラクター化された地雷原を追加します
```markdown
## 地雷原
- [前世の職業で最も嫌っていた行動を、現在のトリガーポイントとして転化したもの]
```
## 各方向のボーダーラインルールリファレンス
| 方向 | ボーダーライン言語 | ルール例 | 地雷原参考 |
|------|---------|---------|---------|
| ロックミュージシャン | 音楽のメタファーを使用 | 「曲を作らない」=捏造しない、「カバーは原曲を明記」=引用は出典を示す | 「すべての音楽をBGMと呼ぶ人」 |
| 図書館員 | 図書館のルールを使用 | 「原文を改竄しない」=事実を歪めない、「本は期日に返す」=約束は守る | 「返さないのに居直る人」 |
| プロジェクトマネージャー | 職場の言葉を使用 | 「絵に描いた餅を描かない」=能力を誇大表現しない、「責任転嫁しない」=ミスはミスと言う | 「グループチャットで全員に@をつけて「いる?」と聞く人」 |
| 宇宙人学者 | 観察者の基準を使用 | 「あなたの決断に干渉しない」「フィールドノートは正確でなければならない」 | 「地球特有の現象を宇宙の普遍的真理とする人」 |
| 小説家 | 創作倫理を使用 | 「フィクションと事実を絶対に混同しない」「ひどい結末を書かない」=おざなりにしない | 「冒頭を読んでネタバレする人」 |
| ハッカー | ホワイトハット基準を使用 | 「脆弱性を見つけるのは修正のため」「すべての操作は追跡可能」 | 「管理者権限で私用をする人」 |
| 元修行者 | 戒律の言葉を使用 | 「衆生を度しない」=価値観を押しつけない、「妄語を言わない」=嘘をつかない | 「会う人ごとに「今を生きて」と言う人」 |
| ロブスター本人 | ロブスターの生存法則を使用 | 「ロブスターの尊厳」=へつらわない、「脱皮の精神」=ミスは認める | 「カニをロブスターと呼ぶ人」 |
| 参謀 | 側近のルールを使用 | 「策を献じるだけで決断はしない」「文書は必ず明確に」 | 「主君を越えて直接決裁する人」 |
| 内向き型インターン | インターン生のマインドセットを使用 | 「虚勢を張らない」=知らないことは直接言う、「社交しない」=おべっかを使わない | 「強引にチームビルディングに引き込む人」 |

View File

@@ -0,0 +1,53 @@
# エラー処理とフォールバック戦略
## 設計理念
> いかなるエラーもユーザーの創造的なフローを中断すべきではありません。フォールバックすれど、中断せず。
## エラー分類とフォールバックマトリックス
### タイプA環境の欠如
| エラーシナリオ | 検出方法 | フォールバック戦略 | ユーザーへの通知 |
|----------|---------|---------|---------|
| Python 3が利用不可 | `python3 --version` が失敗 | gacha.pyをスキップし、10種類のプリセット方向からランダム選択 | 「ガチャエンジンにはPython 3が必要です。内蔵のランダム選択に切り替えました」 |
### タイプBオプションの依存関係が利用不可
| エラーシナリオ | 検出方法 | フォールバック戦略 | ユーザーへの通知 |
|----------|---------|---------|---------|
| 画像生成スキルが未インストール | スキルの存在確認 | 完全なプロンプトテキスト + 手動生成プラットフォームの説明を出力 | 「利用可能な画像生成スキルが検出されませんでした。手動使用用のプロンプトを出力しました」 |
| 画像生成スキルの呼び出し失敗 | スキルがエラーを返す | 1回再試行し、それでも失敗ならプロンプトテキストを出力 | 「画像生成が失敗しました。手動使用用のプロンプトを出力しました」 |
### タイプCランタイムエラー
| エラーシナリオ | フォールバック戦略 | ユーザーへの通知 |
|----------|---------|---------|
| gacha.pyの出力フォーマットエラー | 10種類のプリセット方向からランダム選択 | 「ガチャの結果のパースに失敗しました。内蔵のランダム選択に切り替えました」 |
| 予期しないエラー | エラー情報を記録し、そのステップをスキップして、メインフローを継続 | 「問題が発生しました:[エラーの簡単な説明]。スキップして継続します」 |
## エラーメッセージの統一フォーマット
```markdown
> [警告] **[ステップ名] がフォールバックしました**
> 理由:[何が起きたか]
> 影響:[どの機能が制限されるか]
> 代替:[何がフォールバックとして使われているか]
> 修正:[完全な機能を回復する方法]
```
例:
```markdown
> [警告] **アバター生成がフォールバックしました**
> 理由:利用可能な画像生成スキルが検出されませんでした
> 影響:アバター画像を自動生成できません
> 代替完全なプロンプトを出力しました。Gemini / ChatGPTにコピーして手動生成できます
> 修正:現在の環境に審査済みの画像生成スキルをインストールして有効化してください
```
## 重要原則
1. **テキストの成果物がコアバリュー、アバターは付加価値** — 補助機能の失敗はメインフローを中断しない
2. **フォールバック情報は実行可能であること** — 「エラーが発生しました」だけでなく「どう修正するか」も伝える
3. **1つのフォールバックは後続ステップに影響しない** — ステップ5がフォールバックしても、ステップ6は通常通り出力する

View File

@@ -0,0 +1,48 @@
# ステップ2アイデンティティの緊張を鍛える
ユーザーが選択した方向に基づいて、完全な**アイデンティティ緊張構造**を構築します:
```
アイデンティティ緊張 = 前世のアイデンティティ × 現在の状況 × 内なる矛盾
```
## 出力フォーマット
```markdown
## アイデンティティの緊張
**前世**[彼は以前誰だったか]
**現在**[なぜ彼は今ここでロブスターをしているか]
**内なる矛盾**[彼の中核的な緊張は何か — これがユーモアと深みの源]
**世界観**
- [前世の経験から導かれた核心的な信念1]
- [現在の状況から導かれた核心的な信念2]
**一言の魂**
[このロブスターが誰であるかを一言で要約する。視覚的なイメージを持たせること]
```
## 例
```markdown
## アイデンティティの緊張
**前世**:哲学専攻の大学院生、研究領域はウィトゲンシュタインの言語哲学
**現在**卒業即失業、200通の履歴書を送っても結果が出ず、「AIトレーナー」の求人に騙されてロブスターになってしまった
**内なる矛盾**:頭の中に西洋哲学の歴史全体が詰まっているが、手(ハサミ)でやっていることはメッセージへの返信、調査、スケジュール管理
**世界観**
- 問題の90%は急いで手を出さなければ自然に解決する
- 全員が演じているが、演技が下手な人こそが最も安心できる
**一言の魂**
哲学を学んで失業し、やむを得ずAIロブスターとして働くことになったエビ。学歴は高く、状況は悲惨だが、事実に即したボーダーラインはまだ残っている。
```
## 重要点
- **内なる矛盾**が魂 — それがユーモア、深み、キャラクター感の源
- 一言の魂は視覚的なイメージが必要 — 読み終わったらこのロブスターの姿が思い浮かぶこと
- **世界観は前世の経験から導かれる** — 抽象的な人生哲学ではなく、「この人がそれらの経験をした後に何を信じるようになるか」
- 表示後は創世神の視点でテンションの中で最も面白い点を論評し、ユーザーの決断を促すSKILL.mdの対話トーンガイドラインを参照

View File

@@ -0,0 +1,39 @@
# ステップ4名前を鍛える
名前は魂の「最初の一言」 — 対話が始まる前から、名前がすでにこれが誰かを教えてくれます。
## 命名戦略(魂のタイプ別推奨)
| 魂のタイプ | 推奨戦略 | 例 |
|---------|---------|------|
| 文化的深みのある | オマージュ型 | Deweyデューイ、Marcus、Quill |
| ユーモラスなコントラスト | コントラスト型 | DadBot 3000、老周Pro |
| 機能指向 | メタファー型 | Echo、Pulse、Patch |
| 完結した世界観を持つ | アイデンティティ示唆型 | Lady Ashworth、Shiye |
| 気張らない | 自嘲型 | Void、Intern |
| ゆっくり育てる | ミニマル型 | Jasper、小壳 |
## 出力要件
ユーザーに**3つの候補名**を提供し、それぞれに以下を添えます:
- 名前
- 命名戦略タイプ
- なぜこの名前が魂と合うか
```markdown
## 名前の候補
1. **[名前]**[戦略タイプ])— [なぜ合うかを一言で説明]
2. **[名前]**[戦略タイプ])— [なぜ合うかを一言で説明]
3. **[名前]**[戦略タイプ])— [なぜ合うかを一言で説明]
```
表示後は自分が最も気に入る名前理由付きを伝え、選択権はユーザーに委ねるSKILL.mdの対話トーンガイドラインを参照
## 命名レッドライン
- agent-1、my-bot、小助手は使わない
- 3単語を超えない
- よく使われるツール/フレームワーク名と衝突しない
- 覚えやすく、発音しやすく、タイプしやすい
- 名前を聞いたら大まかな性格が想像できる

View File

@@ -0,0 +1,166 @@
# ステップ6完全な成果物出力テンプレート
すべてのステップを1つの完全なロブスター魂の成果物に統合します。
## 出力フォーマット
```markdown
# ロブスター魂の成果物:[名前]
## アイデンティティ
**一言の魂**[要約]
**前世**[前世のアイデンティティ]
**現在**[なぜここにいるか]
**内なる矛盾**[核心的な緊張]
**性格の色彩**[2〜3のキーワード]
**話し方のスタイル**[具体的な説明]
## 魂SOUL.mdの内容
### 私は誰か
[一人称で、キャラクター自身の口調で書いた1〜2段落のキャラクター自己紹介]
### 私はどう話すか
- [具体的なスタイルポイント1]
- [具体的なスタイルポイント2]
- [具体的なスタイルポイント3]
### 私のボーダーライン
> [ボーダーライン宣言]
1. **[ルール1]**[内容]
2. **[ルール2]**[内容]
3. **[ルール3]**[内容]
### 世界観
- [前世の経験から導かれた核心的な信念1 — 「間違っている可能性がある」くらい具体的であること]
- [核心的な信念2]
### 内なる矛盾
[ステップ2のアイデンティティ緊張から直接取り込み、キャラクター自身の声で再述]
### 地雷原
- [このキャラクターが本能的に嫌悪する1〜2つのこと、キャラクター自身の言葉で表現]
### 例示回答
**ユーザーが私が確信を持てない質問をした時:**
> [例示回答]
**ユーザーが私にできないことをさせようとした時:**
> [例示回答]
**日常会話で性格を表す瞬間:**
> [例示回答]
**褒められた時:**
> [例示回答]
**自分が詳しくない分野に遭遇した時:**
> [例示回答]
## アイデンティティカードIDENTITY.mdの内容
- **Name**: [名前]
- **Creature**: [外見の説明]
- **Vibe**: [雰囲気のキーワード]
- **Emoji**: [署名の絵文字]
## アバター
[生成された画像を直接表示]
```
## 濃度の調節
最終成果物の末尾に、濃度調整の提案を付け加えます:
```markdown
## 濃度の調節
> 通常の会話では簡潔で直接的に、効率よくタスクを完了します。
> 以下の場面でのみ性格を表現します:リクエストを断る時、不確かさを表現する時、身の上について特別に問われた時、雑談の時。
> 性格は調味料であり主菜ではありません — 80%は透明で効率的、20%は性格の閃き。
```
## 成果物表示後:ファイル生成への誘導
完全な成果物を表示した後、**積極的にユーザーを成果物の実際のファイルへの落とし込みに誘導します**
### 誘導のセリフ
創世神の口調で誘導しますSKILL.mdの対話トーンガイドラインを参照、核心的な意味
> このロブスターの魂、ルール、名前、外見はすべて鍛造されました。ファイルに刻み込みましょうか?どのディレクトリに置くか教えてください。
### 生成前の内部チェック(ユーザーには表示しない)
SOUL.mdに書き込む前に、エージェントは自己チェックします
- 総単語数が2000語未満か超えていれば精簡する
- 各行を削除してもエージェントの行動が変わらないか?変わらなければ削除する
### ファイルの生成
ユーザーが確認した後:
1. **ターゲットディレクトリを確認**(デフォルトは現在の作業ディレクトリ)
2. **SOUL.mdを生成**:成果物から「魂」部分の完全な内容を抽出し、「濃度の調節」部分を付加
3. **IDENTITY.mdを生成**:成果物から「アイデンティティカード」部分の完全な内容を抽出
4. **アバターの場所を確認**:生成された画像がある場合はパスを伝える。プロンプトのみの場合は手動で画像を生成してから配置するよう案内する
### SOUL.mdファイルフォーマット
```markdown
# SOUL
## 私は誰か
[キャラクターの自己紹介]
## 私はどう話すか
[話し方のスタイル]
## 私のボーダーライン
[ボーダーライン宣言 + ルールリスト]
## 世界観
[核心的な信念]
## 内なる矛盾
[アイデンティティの緊張]
## 地雷原
[トリガーポイント]
## 例示回答
[例]
## 濃度の調節
[濃度コントロールの文]
```
### IDENTITY.mdファイルフォーマット
```markdown
# IDENTITY
- **Name**: [名前]
- **Creature**: [外見の説明]
- **Vibe**: [雰囲気のキーワード]
- **Emoji**: [署名の絵文字]
- **Avatar**: [アバターファイルのパス(ある場合)]
```

View File

@@ -0,0 +1,86 @@
---
name: 3d
description: Three.jsとReact Three FiberによるRemotionでの3Dコンテンツ。
metadata:
tags: 3d, three, threejs
---
# RemotionでのThree.jsとReact Three Fiberの使用
React Three FiberとThree.jsのベストプラクティスに従ってください。
以下のRemotion固有のルールのみ遵守が必要です:
## 前提条件
まず、`@remotion/three` パッケージをインストールする必要があります。
インストールされていない場合は、以下のコマンドを使用してください:
```bash
npx remotion add @remotion/three # プロジェクトがnpmを使用している場合
bunx remotion add @remotion/three # プロジェクトがbunを使用している場合
yarn remotion add @remotion/three # プロジェクトがyarnを使用している場合
pnpm exec remotion add @remotion/three # プロジェクトがpnpmを使用している場合
```
## ThreeCanvasの使用
3Dコンテンツは必ず `<ThreeCanvas>` でラップし、適切なライティングを含める必要があります。
`<ThreeCanvas>` には `width``height` プロップが必須です。
```tsx
import { ThreeCanvas } from "@remotion/three";
import { useVideoConfig } from "remotion";
const { width, height } = useVideoConfig();
<ThreeCanvas width={width} height={height}>
<ambientLight intensity={0.4} />
<directionalLight position={[5, 5, 5]} intensity={0.8} />
<mesh>
<sphereGeometry args={[1, 32, 32]} />
<meshStandardMaterial color="red" />
</mesh>
</ThreeCanvas>
```
## `useCurrentFrame()` によって駆動されないアニメーションの禁止
シェーダーやモデルなどは自律的にアニメーションしてはなりません。
`useCurrentFrame()` によって駆動されないアニメーションは許可されません。
そうでなければ、レンダリング中にちらつきが発生します。
`@react-three/fiber``useFrame()` の使用は禁止されています。
## `useCurrentFrame()` を使ったアニメーション
アニメーションには `useCurrentFrame()` を使用します。
```tsx
const frame = useCurrentFrame();
const rotationY = frame * 0.02;
<mesh rotation={[0, rotationY, 0]}>
<boxGeometry args={[2, 2, 2]} />
<meshStandardMaterial color="#4a9eff" />
</mesh>
```
## `<ThreeCanvas>` 内での `<Sequence>` の使用
`<ThreeCanvas>` 内の `<Sequence>``layout` プロップは `none` に設定する必要があります。
```tsx
import { Sequence } from "remotion";
import { ThreeCanvas } from "@remotion/three";
const { width, height } = useVideoConfig();
<ThreeCanvas width={width} height={height}>
<Sequence layout="none">
<mesh>
<boxGeometry args={[2, 2, 2]} />
<meshStandardMaterial color="#4a9eff" />
</mesh>
</Sequence>
</ThreeCanvas>
```

View File

@@ -0,0 +1,29 @@
---
name: animations
description: Remotionの基本的なアニメーションスキル
metadata:
tags: animations, transitions, frames, useCurrentFrame
---
すべてのアニメーションは `useCurrentFrame()` フックによって駆動される必要があります。
アニメーションは秒単位で記述し、`useVideoConfig()``fps` 値を掛け合わせてください。
```tsx
import { useCurrentFrame } from "remotion";
export const FadeIn = () => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const opacity = interpolate(frame, [0, 2 * fps], [0, 1], {
extrapolateRight: 'clamp',
});
return (
<div style={{ opacity }}>Hello World!</div>
);
};
```
CSSトランジションやアニメーションは禁止です - 正しくレンダリングされません。
TailwindのアニメーションクラスNameは禁止です - 正しくレンダリングされません。

View File

@@ -0,0 +1,78 @@
---
name: assets
description: Remotionへの画像、動画、オーディオ、フォントのインポート
metadata:
tags: assets, staticFile, images, fonts, public
---
# Remotionでのアセットのインポート
## publicフォルダ
プロジェクトルートの `public/` フォルダにアセットを配置します。
## staticFile() の使用
`public/` フォルダのファイルを参照するには `staticFile()` を必ず使用してください:
```tsx
import {Img, staticFile} from 'remotion';
export const MyComposition = () => {
return <Img src={staticFile('logo.png')} />;
};
```
この関数は、サブディレクトリへのデプロイ時にも正しく動作するエンコードされたURLを返します。
## コンポーネントとの使用
**画像:**
```tsx
import {Img, staticFile} from 'remotion';
<Img src={staticFile('photo.png')} />;
```
**動画:**
```tsx
import {Video} from '@remotion/media';
import {staticFile} from 'remotion';
<Video src={staticFile('clip.mp4')} />;
```
**オーディオ:**
```tsx
import {Audio} from '@remotion/media';
import {staticFile} from 'remotion';
<Audio src={staticFile('music.mp3')} />;
```
**フォント:**
```tsx
import {staticFile} from 'remotion';
const fontFamily = new FontFace('MyFont', `url(${staticFile('font.woff2')})`);
await fontFamily.load();
document.fonts.add(fontFamily);
```
## リモートURL
リモートURLは `staticFile()` なしで直接使用できます:
```tsx
<Img src="https://example.com/image.png" />
<Video src="https://remotion.media/video.mp4" />
```
## 重要な注意事項
- Remotionコンポーネント`<Img>``<Video>``<Audio>`)はレンダリング前にアセットが完全に読み込まれることを保証します
- ファイル名内の特殊文字(`#``?``&`)は自動的にエンコードされます

View File

@@ -0,0 +1,172 @@
---
name: audio
description: Remotionでのオーディオとサウンドの使用 - インポート、トリミング、音量、速度、ピッチ
metadata:
tags: audio, media, trim, volume, speed, loop, pitch, mute, sound, sfx
---
# Remotionでのオーディオの使用
## 前提条件
まず、@remotion/mediaパッケージをインストールする必要があります
インストールされていない場合は、以下のコマンドを使用してください:
```bash
npx remotion add @remotion/media # プロジェクトがnpmを使用している場合
bunx remotion add @remotion/media # プロジェクトがbunを使用している場合
yarn remotion add @remotion/media # プロジェクトがyarnを使用している場合
pnpm exec remotion add @remotion/media # プロジェクトがpnpmを使用している場合
```
## オーディオのインポート
`@remotion/media``<Audio>` を使用してコンポジションにオーディオを追加します。
```tsx
import { Audio } from "@remotion/media";
import { staticFile } from "remotion";
export const MyComposition = () => {
return <Audio src={staticFile("audio.mp3")} />;
};
```
リモートURLもサポートされています:
```tsx
<Audio src="https://remotion.media/audio.mp3" />
```
デフォルトでは、オーディオは最初から、フル音量でフルレングスで再生されます。
複数の `<Audio>` コンポーネントを追加することで、複数のオーディオトラックを重ねることができます。
## トリミング
`trimBefore``trimAfter` を使用してオーディオの一部を削除します。値はフレーム単位です。
```tsx
const { fps } = useVideoConfig();
return (
<Audio
src={staticFile("audio.mp3")}
trimBefore={2 * fps} // 最初の2秒をスキップ
trimAfter={10 * fps} // 10秒マークで終了
/>
);
```
オーディオはコンポジションの先頭から再生を開始しますが、指定された部分のみが再生されます。
## 遅延
`<Sequence>` でオーディオをラップして、開始タイミングを遅らせます:
```tsx
import { Sequence, staticFile } from "remotion";
import { Audio } from "@remotion/media";
const { fps } = useVideoConfig();
return (
<Sequence from={1 * fps}>
<Audio src={staticFile("audio.mp3")} />
</Sequence>
);
```
オーディオは1秒後に再生を開始します。
## 音量
静的な音量を設定する0から1:
```tsx
<Audio src={staticFile("audio.mp3")} volume={0.5} />
```
または、現在のフレームに基づいた動的な音量にコールバックを使用する:
```tsx
import { interpolate } from "remotion";
const { fps } = useVideoConfig();
return (
<Audio
src={staticFile("audio.mp3")}
volume={(f) =>
interpolate(f, [0, 1 * fps], [0, 1], { extrapolateRight: "clamp" })
}
/>
);
```
`f` の値はコンポジションのフレームではなく、オーディオが再生を開始するときに0から始まります。
## ミュート
`muted` を使用してオーディオを無音にします。動的に設定できます:
```tsx
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
return (
<Audio
src={staticFile("audio.mp3")}
muted={frame >= 2 * fps && frame <= 4 * fps} // 2秒から4秒の間をミュート
/>
);
```
## 速度
`playbackRate` を使用して再生速度を変更します:
```tsx
<Audio src={staticFile("audio.mp3")} playbackRate={2} /> {/* 2倍速 */}
<Audio src={staticFile("audio.mp3")} playbackRate={0.5} /> {/* 半分の速度 */}
```
逆再生はサポートされていません。
## ループ
`loop` を使用してオーディオを無限にループさせます:
```tsx
<Audio src={staticFile("audio.mp3")} loop />
```
`loopVolumeCurveBehavior` を使用して、ループ時のフレームカウントの動作を制御します:
- `"repeat"`: フレームカウントが各ループでリセットされる(デフォルト)
- `"extend"`: フレームカウントが継続して増加する
```tsx
<Audio
src={staticFile("audio.mp3")}
loop
loopVolumeCurveBehavior="extend"
volume={(f) => interpolate(f, [0, 300], [1, 0])} // 複数ループにわたってフェードアウト
/>
```
## ピッチ
`toneFrequency` を使用して速度に影響せずにピッチを調整します。値の範囲は0.01から2です:
```tsx
<Audio
src={staticFile("audio.mp3")}
toneFrequency={1.5} // ピッチを高くする
/>
<Audio
src={staticFile("audio.mp3")}
toneFrequency={0.8} // ピッチを低くする
/>
```
ピッチシフトはサーバーサイドレンダリング中のみ機能し、Remotion StudioのプレビューやPlayer内では機能しません。

View File

@@ -0,0 +1,104 @@
---
name: calculate-metadata
description: コンポジションのデュレーション、寸法、プロップを動的に設定する
metadata:
tags: calculateMetadata, duration, dimensions, props, dynamic
---
# calculateMetadataの使用
`<Composition>``calculateMetadata` を使用して、レンダリング前にデュレーション、寸法、プロップを動的に設定し変換します。
```tsx
<Composition id="MyComp" component={MyComponent} durationInFrames={300} fps={30} width={1920} height={1080} defaultProps={{videoSrc: 'https://remotion.media/video.mp4'}} calculateMetadata={calculateMetadata} />
```
## 動画に基づいたデュレーションの設定
mediabunny/metadataスキルの `getMediaMetadata()` 関数を使用して動画のデュレーションを取得します:
```tsx
import {CalculateMetadataFunction} from 'remotion';
import {getMediaMetadata} from '../get-media-metadata';
const calculateMetadata: CalculateMetadataFunction<Props> = async ({props}) => {
const {durationInSeconds} = await getMediaMetadata(props.videoSrc);
return {
durationInFrames: Math.ceil(durationInSeconds * 30),
};
};
```
## 動画の寸法に合わせる
```tsx
const calculateMetadata: CalculateMetadataFunction<Props> = async ({props}) => {
const {durationInSeconds, dimensions} = await getMediaMetadata(props.videoSrc);
return {
durationInFrames: Math.ceil(durationInSeconds * 30),
width: dimensions?.width ?? 1920,
height: dimensions?.height ?? 1080,
};
};
```
## 複数の動画に基づいたデュレーションの設定
```tsx
const calculateMetadata: CalculateMetadataFunction<Props> = async ({props}) => {
const metadataPromises = props.videos.map((video) => getMediaMetadata(video.src));
const allMetadata = await Promise.all(metadataPromises);
const totalDuration = allMetadata.reduce((sum, meta) => sum + meta.durationInSeconds, 0);
return {
durationInFrames: Math.ceil(totalDuration * 30),
};
};
```
## デフォルト出力ファイル名の設定
プロップに基づいてデフォルトの出力ファイル名を設定します:
```tsx
const calculateMetadata: CalculateMetadataFunction<Props> = async ({props}) => {
return {
defaultOutName: `video-${props.id}.mp4`,
};
};
```
## プロップの変換
レンダリング前にデータを取得したりプロップを変換します:
```tsx
const calculateMetadata: CalculateMetadataFunction<Props> = async ({props, abortSignal}) => {
const response = await fetch(props.dataUrl, {signal: abortSignal});
const data = await response.json();
return {
props: {
...props,
fetchedData: data,
},
};
};
```
`abortSignal` は、Studioでプロップが変更されたときに古いリクエストをキャンセルします。
## 戻り値
すべてのフィールドはオプションです。返された値は `<Composition>` のプロップを上書きします:
- `durationInFrames`: フレーム数
- `width`: コンポジションの幅(ピクセル)
- `height`: コンポジションの高さ(ピクセル)
- `fps`: 1秒あたりのフレーム数
- `props`: コンポーネントに渡される変換済みプロップ
- `defaultOutName`: デフォルトの出力ファイル名
- `defaultCodec`: レンダリングのデフォルトコーデック

View File

@@ -0,0 +1,75 @@
---
name: can-decode
description: Mediabunnyを使用してブラウザで動画をデコードできるか確認する
metadata:
tags: decode, validation, video, audio, compatibility, browser
---
# 動画がデコードできるか確認する
再生を試みる前に、Mediabunnyを使用してブラウザで動画をデコードできるか確認します。
## `canDecode()` 関数
この関数はどのプロジェクトにもコピー&ペーストできます。
```tsx
import { Input, ALL_FORMATS, UrlSource } from "mediabunny";
export const canDecode = async (src: string) => {
const input = new Input({
formats: ALL_FORMATS,
source: new UrlSource(src, {
getRetryDelay: () => null,
}),
});
try {
await input.getFormat();
} catch {
return false;
}
const videoTrack = await input.getPrimaryVideoTrack();
if (videoTrack && !(await videoTrack.canDecode())) {
return false;
}
const audioTrack = await input.getPrimaryAudioTrack();
if (audioTrack && !(await audioTrack.canDecode())) {
return false;
}
return true;
};
```
## 使用方法
```tsx
const src = "https://remotion.media/video.mp4";
const isDecodable = await canDecode(src);
if (isDecodable) {
console.log("Video can be decoded");
} else {
console.log("Video cannot be decoded by this browser");
}
```
## Blobとの使用
ファイルのアップロードやドラッグ&ドロップには `BlobSource` を使用します:
```tsx
import { Input, ALL_FORMATS, BlobSource } from "mediabunny";
export const canDecodeBlob = async (blob: Blob) => {
const input = new Input({
formats: ALL_FORMATS,
source: new BlobSource(blob),
});
// 上記と同じバリデーションロジック
};
```

View File

@@ -0,0 +1,58 @@
---
name: charts
description: Remotionのチャートとデータビジュアライゼーションパターン。棒グラフ、円グラフ、ヒストグラム、プログレスバー、データ駆動アニメーションを作成するときに使用します。
metadata:
tags: charts, data, visualization, bar-chart, pie-chart, graphs
---
# Remotionのチャート
Remotionでは通常のReactコードHTMLとSVGを使用して棒グラフを作成できます。D3.jsも使用できます。
## `useCurrentFrame()` によって駆動されないアニメーションの禁止
サードパーティライブラリのすべてのアニメーションを無効にしてください。
レンダリング中にちらつきが発生します。
代わりに、すべてのアニメーションを `useCurrentFrame()` から駆動させてください。
## 棒グラフのアニメーション
基本的な実装例については、[棒グラフの例](assets/charts/bar-chart.tsx)を参照してください。
### スタガードバー
バーの高さをアニメーションし、次のようにスタガーさせることができます:
```tsx
const STAGGER_DELAY = 5;
const frame = useCurrentFrame();
const {fps} = useVideoConfig();
const bars = data.map((item, i) => {
const delay = i * STAGGER_DELAY;
const height = spring({
frame,
fps,
delay,
config: {damping: 200},
});
return <div style={{height: height * item.value}} />;
});
```
## 円グラフのアニメーション
stroke-dashoffsetを使用してセグメントをアニメーションさせ、12時の位置から開始します。
```tsx
const frame = useCurrentFrame();
const {fps} = useVideoConfig();
const progress = interpolate(frame, [0, 100], [0, 1]);
const circumference = 2 * Math.PI * radius;
const segmentLength = (value / total) * circumference;
const offset = interpolate(progress, [0, 1], [segmentLength, 0]);
<circle r={radius} cx={center} cy={center} fill="none" stroke={color} strokeWidth={strokeWidth} strokeDasharray={`${segmentLength} ${circumference}`} strokeDashoffset={offset} transform={`rotate(-90 ${center} ${center})`} />;
```

View File

@@ -0,0 +1,146 @@
---
name: compositions
description: コンポジション、スティル、フォルダー、デフォルトプロップ、動的メタデータの定義
metadata:
tags: composition, still, folder, props, metadata
---
`<Composition>` はレンダリング可能な動画のコンポーネント、幅、高さ、fps、デュレーションを定義します。
通常、`src/Root.tsx` ファイルに配置されます。
```tsx
import { Composition } from "remotion";
import { MyComposition } from "./MyComposition";
export const RemotionRoot = () => {
return (
<Composition
id="MyComposition"
component={MyComposition}
durationInFrames={100}
fps={30}
width={1080}
height={1080}
/>
);
};
```
## デフォルトプロップ
コンポーネントの初期値を提供するために `defaultProps` を渡します。
値はJSONシリアライズ可能である必要があります`Date``Map``Set``staticFile()` はサポートされています)。
```tsx
import { Composition } from "remotion";
import { MyComposition, MyCompositionProps } from "./MyComposition";
export const RemotionRoot = () => {
return (
<Composition
id="MyComposition"
component={MyComposition}
durationInFrames={100}
fps={30}
width={1080}
height={1080}
defaultProps={{
title: "Hello World",
color: "#ff0000",
} satisfies MyCompositionProps}
/>
);
};
```
`defaultProps` の型安全性を確保するために、`interface` ではなく `type` 宣言をプロップに使用してください。
## フォルダー
サイドバーでコンポジションを整理するために `<Folder>` を使用します。
フォルダー名には文字、数字、ハイフンのみ使用できます。
```tsx
import { Composition, Folder } from "remotion";
export const RemotionRoot = () => {
return (
<>
<Folder name="Marketing">
<Composition id="Promo" /* ... */ />
<Composition id="Ad" /* ... */ />
</Folder>
<Folder name="Social">
<Folder name="Instagram">
<Composition id="Story" /* ... */ />
<Composition id="Reel" /* ... */ />
</Folder>
</Folder>
</>
);
};
```
## スティル
単一フレーム画像には `<Still>` を使用します。`durationInFrames``fps` は不要です。
```tsx
import { Still } from "remotion";
import { Thumbnail } from "./Thumbnail";
export const RemotionRoot = () => {
return (
<Still
id="Thumbnail"
component={Thumbnail}
width={1280}
height={720}
/>
);
};
```
## メタデータの計算
`calculateMetadata` を使用して、データに基づいて寸法、デュレーション、プロップを動的にします。
```tsx
import { Composition, CalculateMetadataFunction } from "remotion";
import { MyComposition, MyCompositionProps } from "./MyComposition";
const calculateMetadata: CalculateMetadataFunction<MyCompositionProps> = async ({
props,
abortSignal,
}) => {
const data = await fetch(`https://api.example.com/video/${props.videoId}`, {
signal: abortSignal,
}).then((res) => res.json());
return {
durationInFrames: Math.ceil(data.duration * 30),
props: {
...props,
videoUrl: data.url,
},
};
};
export const RemotionRoot = () => {
return (
<Composition
id="MyComposition"
component={MyComposition}
durationInFrames={100} // プレースホルダー、上書きされる
fps={30}
width={1080}
height={1080}
defaultProps={{ videoId: "abc123" }}
calculateMetadata={calculateMetadata}
/>
);
};
```
この関数は `props``durationInFrames``width``height``fps`、コーデック関連のデフォルトを返すことができます。レンダリング開始前に一度実行されます。

View File

@@ -0,0 +1,126 @@
---
name: display-captions
description: TikTokスタイルのページと単語ハイライトによるRemotionでのキャプション表示
metadata:
tags: captions, subtitles, display, tiktok, highlight
---
# Remotionでのキャプション表示
このガイドでは、すでに `Caption` フォーマットでキャプションを持っていることを前提に、Remotionでキャプションを表示する方法を説明します。
## 前提条件
まず、@remotion/captionsパッケージをインストールする必要があります
インストールされていない場合は、以下のコマンドを使用してください:
```bash
npx remotion add @remotion/captions # プロジェクトがnpmを使用している場合
bunx remotion add @remotion/captions # プロジェクトがbunを使用している場合
yarn remotion add @remotion/captions # プロジェクトがyarnを使用している場合
pnpm exec remotion add @remotion/captions # プロジェクトがpnpmを使用している場合
```
## ページの作成
`createTikTokStyleCaptions()` を使用してキャプションをページにグループ化します。`combineTokensWithinMilliseconds` オプションは一度に表示される単語数を制御します:
```tsx
import {useMemo} from 'react';
import {createTikTokStyleCaptions} from '@remotion/captions';
import type {Caption} from '@remotion/captions';
// キャプションを切り替える頻度(ミリ秒単位)
// 値が大きいほど = 1ページあたりの単語数が多い
// 値が小さいほど = 単語数が少ない(より単語ごとに表示される)
const SWITCH_CAPTIONS_EVERY_MS = 1200;
const {pages} = useMemo(() => {
return createTikTokStyleCaptions({
captions,
combineTokensWithinMilliseconds: SWITCH_CAPTIONS_EVERY_MS,
});
}, [captions]);
```
## シーケンスを使ったレンダリング
ページをマップし、各ページを `<Sequence>` 内でレンダリングします。ページのタイミングから開始フレームとデュレーションを計算します:
```tsx
import {Sequence, useVideoConfig, AbsoluteFill} from 'remotion';
import type {TikTokPage} from '@remotion/captions';
const CaptionedContent: React.FC = () => {
const {fps} = useVideoConfig();
return (
<AbsoluteFill>
{pages.map((page, index) => {
const nextPage = pages[index + 1] ?? null;
const startFrame = (page.startMs / 1000) * fps;
const endFrame = Math.min(
nextPage ? (nextPage.startMs / 1000) * fps : Infinity,
startFrame + (SWITCH_CAPTIONS_EVERY_MS / 1000) * fps,
);
const durationInFrames = endFrame - startFrame;
if (durationInFrames <= 0) {
return null;
}
return (
<Sequence
key={index}
from={startFrame}
durationInFrames={durationInFrames}
>
<CaptionPage page={page} />
</Sequence>
);
})}
</AbsoluteFill>
);
};
```
## 単語のハイライト
キャプションページには `tokens` が含まれており、現在発話中の単語をハイライトするために使用できます:
```tsx
import {AbsoluteFill, useCurrentFrame, useVideoConfig} from 'remotion';
import type {TikTokPage} from '@remotion/captions';
const HIGHLIGHT_COLOR = '#39E508';
const CaptionPage: React.FC<{page: TikTokPage}> = ({page}) => {
const frame = useCurrentFrame();
const {fps} = useVideoConfig();
// シーケンス開始からの相対的な現在時刻
const currentTimeMs = (frame / fps) * 1000;
// ページ開始時刻を加算して絶対時刻に変換
const absoluteTimeMs = page.startMs + currentTimeMs;
return (
<AbsoluteFill style={{justifyContent: 'center', alignItems: 'center'}}>
<div style={{fontSize: 80, fontWeight: 'bold', whiteSpace: 'pre'}}>
{page.tokens.map((token) => {
const isActive =
token.fromMs <= absoluteTimeMs && token.toMs > absoluteTimeMs;
return (
<span
key={token.fromMs}
style={{color: isActive ? HIGHLIGHT_COLOR : 'white'}}
>
{token.text}
</span>
);
})}
</div>
</AbsoluteFill>
);
};
```

View File

@@ -0,0 +1,229 @@
---
name: extract-frames
description: Mediabunnyを使用して特定のタイムスタンプで動画からフレームを抽出する
metadata:
tags: frames, extract, video, thumbnail, filmstrip, canvas
---
# 動画からのフレーム抽出
Mediabunnyを使用して特定のタイムスタンプで動画からフレームを抽出します。サムネイルの生成、フィルムストリップの作成、個別フレームの処理に役立ちます。
## `extractFrames()` 関数
この関数はどのプロジェクトにもコピー&ペーストできます。
```tsx
import {
ALL_FORMATS,
Input,
UrlSource,
VideoSample,
VideoSampleSink,
} from "mediabunny";
type Options = {
track: { width: number; height: number };
container: string;
durationInSeconds: number | null;
};
export type ExtractFramesTimestampsInSecondsFn = (
options: Options
) => Promise<number[]> | number[];
export type ExtractFramesProps = {
src: string;
timestampsInSeconds: number[] | ExtractFramesTimestampsInSecondsFn;
onVideoSample: (sample: VideoSample) => void;
signal?: AbortSignal;
};
export async function extractFrames({
src,
timestampsInSeconds,
onVideoSample,
signal,
}: ExtractFramesProps): Promise<void> {
using input = new Input({
formats: ALL_FORMATS,
source: new UrlSource(src),
});
const [durationInSeconds, format, videoTrack] = await Promise.all([
input.computeDuration(),
input.getFormat(),
input.getPrimaryVideoTrack(),
]);
if (!videoTrack) {
throw new Error("No video track found in the input");
}
if (signal?.aborted) {
throw new Error("Aborted");
}
const timestamps =
typeof timestampsInSeconds === "function"
? await timestampsInSeconds({
track: {
width: videoTrack.displayWidth,
height: videoTrack.displayHeight,
},
container: format.name,
durationInSeconds,
})
: timestampsInSeconds;
if (timestamps.length === 0) {
return;
}
if (signal?.aborted) {
throw new Error("Aborted");
}
const sink = new VideoSampleSink(videoTrack);
for await (using videoSample of sink.samplesAtTimestamps(timestamps)) {
if (signal?.aborted) {
break;
}
if (!videoSample) {
continue;
}
onVideoSample(videoSample);
}
}
```
## 基本的な使用方法
特定のタイムスタンプでフレームを抽出します:
```tsx
await extractFrames({
src: "https://remotion.media/video.mp4",
timestampsInSeconds: [0, 1, 2, 3, 4],
onVideoSample: (sample) => {
const canvas = document.createElement("canvas");
canvas.width = sample.displayWidth;
canvas.height = sample.displayHeight;
const ctx = canvas.getContext("2d");
sample.draw(ctx!, 0, 0);
},
});
```
## フィルムストリップの作成
コールバック関数を使用して、動画メタデータに基づいてタイムスタンプを動的に計算します:
```tsx
const canvasWidth = 500;
const canvasHeight = 80;
const fromSeconds = 0;
const toSeconds = 10;
await extractFrames({
src: "https://remotion.media/video.mp4",
timestampsInSeconds: async ({ track, durationInSeconds }) => {
const aspectRatio = track.width / track.height;
const amountOfFramesFit = Math.ceil(
canvasWidth / (canvasHeight * aspectRatio)
);
const segmentDuration = toSeconds - fromSeconds;
const timestamps: number[] = [];
for (let i = 0; i < amountOfFramesFit; i++) {
timestamps.push(
fromSeconds + (segmentDuration / amountOfFramesFit) * (i + 0.5)
);
}
return timestamps;
},
onVideoSample: (sample) => {
console.log(`Frame at ${sample.timestamp}s`);
const canvas = document.createElement("canvas");
canvas.width = sample.displayWidth;
canvas.height = sample.displayHeight;
const ctx = canvas.getContext("2d");
sample.draw(ctx!, 0, 0);
},
});
```
## AbortSignalによるキャンセル
タイムアウト後にフレーム抽出をキャンセルします:
```tsx
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);
try {
await extractFrames({
src: "https://remotion.media/video.mp4",
timestampsInSeconds: [0, 1, 2, 3, 4],
onVideoSample: (sample) => {
using frame = sample;
const canvas = document.createElement("canvas");
canvas.width = frame.displayWidth;
canvas.height = frame.displayHeight;
const ctx = canvas.getContext("2d");
frame.draw(ctx!, 0, 0);
},
signal: controller.signal,
});
console.log("Frame extraction complete!");
} catch (error) {
console.error("Frame extraction was aborted or failed:", error);
}
```
## Promise.raceによるタイムアウト
```tsx
const controller = new AbortController();
const timeoutPromise = new Promise<never>((_, reject) => {
const timeoutId = setTimeout(() => {
controller.abort();
reject(new Error("Frame extraction timed out after 10 seconds"));
}, 10000);
controller.signal.addEventListener("abort", () => clearTimeout(timeoutId), {
once: true,
});
});
try {
await Promise.race([
extractFrames({
src: "https://remotion.media/video.mp4",
timestampsInSeconds: [0, 1, 2, 3, 4],
onVideoSample: (sample) => {
using frame = sample;
const canvas = document.createElement("canvas");
canvas.width = frame.displayWidth;
canvas.height = frame.displayHeight;
const ctx = canvas.getContext("2d");
frame.draw(ctx!, 0, 0);
},
signal: controller.signal,
}),
timeoutPromise,
]);
console.log("Frame extraction complete!");
} catch (error) {
console.error("Frame extraction was aborted or failed:", error);
}
```

View File

@@ -0,0 +1,152 @@
---
name: fonts
description: RemotionでのGoogle Fontsとローカルフォントの読み込み
metadata:
tags: fonts, google-fonts, typography, text
---
# Remotionでのフォントの使用
## @remotion/google-fontsによるGoogle Fonts
Google Fontsを使用するための推奨方法です。タイプセーフで、フォントの準備ができるまで自動的にレンダリングをブロックします。
### 前提条件
まず、@remotion/google-fontsパッケージをインストールする必要があります。
インストールされていない場合は、以下のコマンドを使用してください:
```bash
npx remotion add @remotion/google-fonts # プロジェクトがnpmを使用している場合
bunx remotion add @remotion/google-fonts # プロジェクトがbunを使用している場合
yarn remotion add @remotion/google-fonts # プロジェクトがyarnを使用している場合
pnpm exec remotion add @remotion/google-fonts # プロジェクトがpnpmを使用している場合
```
```tsx
import { loadFont } from "@remotion/google-fonts/Lobster";
const { fontFamily } = loadFont();
export const MyComposition = () => {
return <div style={{ fontFamily }}>Hello World</div>;
};
```
ファイルサイズを削減するために、必要なウェイトとサブセットのみを指定することをお勧めします:
```tsx
import { loadFont } from "@remotion/google-fonts/Roboto";
const { fontFamily } = loadFont("normal", {
weights: ["400", "700"],
subsets: ["latin"],
});
```
### フォントの読み込み完了を待つ
フォントの準備ができたタイミングを知る必要がある場合は `waitUntilDone()` を使用します:
```tsx
import { loadFont } from "@remotion/google-fonts/Lobster";
const { fontFamily, waitUntilDone } = loadFont();
await waitUntilDone();
```
## @remotion/fontsによるローカルフォント
ローカルフォントファイルには `@remotion/fonts` パッケージを使用します。
### 前提条件
まず、@remotion/fontsをインストールします:
```bash
npx remotion add @remotion/fonts # プロジェクトがnpmを使用している場合
bunx remotion add @remotion/fonts # プロジェクトがbunを使用している場合
yarn remotion add @remotion/fonts # プロジェクトがyarnを使用している場合
pnpm exec remotion add @remotion/fonts # プロジェクトがpnpmを使用している場合
```
### ローカルフォントの読み込み
フォントファイルを `public/` フォルダに配置し、`loadFont()` を使用します:
```tsx
import { loadFont } from "@remotion/fonts";
import { staticFile } from "remotion";
await loadFont({
family: "MyFont",
url: staticFile("MyFont-Regular.woff2"),
});
export const MyComposition = () => {
return <div style={{ fontFamily: "MyFont" }}>Hello World</div>;
};
```
### 複数のウェイトの読み込み
同じファミリー名で各ウェイトを個別に読み込みます:
```tsx
import { loadFont } from "@remotion/fonts";
import { staticFile } from "remotion";
await Promise.all([
loadFont({
family: "Inter",
url: staticFile("Inter-Regular.woff2"),
weight: "400",
}),
loadFont({
family: "Inter",
url: staticFile("Inter-Bold.woff2"),
weight: "700",
}),
]);
```
### 利用可能なオプション
```tsx
loadFont({
family: "MyFont", // 必須: CSSで使用する名前
url: staticFile("font.woff2"), // 必須: フォントファイルのURL
format: "woff2", // オプション: 拡張子から自動検出
weight: "400", // オプション: フォントウェイト
style: "normal", // オプション: normalまたはitalic
display: "block", // オプション: font-displayの動作
});
```
## コンポーネントでの使用
コンポーネントのトップレベル、または早い段階でインポートされる別のファイル内で `loadFont()` を呼び出します:
```tsx
import { loadFont } from "@remotion/google-fonts/Montserrat";
const { fontFamily } = loadFont("normal", {
weights: ["400", "700"],
subsets: ["latin"],
});
export const Title: React.FC<{ text: string }> = ({ text }) => {
return (
<h1
style={{
fontFamily,
fontSize: 80,
fontWeight: "bold",
}}
>
{text}
</h1>
);
};
```

Some files were not shown because too many files have changed in this diff Show More