Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .code-abyss/packs.lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"version": 1,
"hosts": {
"claude": {
"required": [
"gstack"
],
"optional": [],
"optional_policy": "auto",
"sources": {
"gstack": "pinned"
}
},
"codex": {
"required": [
"gstack"
],
"optional": [],
"optional_policy": "auto",
"sources": {
"gstack": "pinned"
}
},
"gemini": {
"required": [
"gstack"
],
"optional": [],
"optional_policy": "auto",
"sources": {
"gstack": "pinned"
}
}
}
}
10 changes: 10 additions & 0 deletions .code-abyss/snippets/CONTRIBUTING.packs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## AI Tooling

This repository uses `.code-abyss/packs.lock.json` to declare AI packs.

- Update the lock with `npm run packs:update -- [flags]`.
- Validate it with `npm run packs:check`.
- Re-run `npx code-abyss --target claude|codex|gemini -y` after pack changes.

Current host policies: claude=auto, codex=auto, gemini=auto

16 changes: 16 additions & 0 deletions .code-abyss/snippets/README.packs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## AI Pack Bootstrap

This repository declares Code Abyss packs in `.code-abyss/packs.lock.json`.

- claude: required=[gstack], optional=[none], optional_policy=auto
- codex: required=[gstack], optional=[none], optional_policy=auto
- gemini: required=[gstack], optional=[none], optional_policy=auto

Recommended install:

```bash
npx code-abyss --target claude -y
npx code-abyss --target codex -y
npx code-abyss --target gemini -y
```

62 changes: 57 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ jobs:
- run: npm ci
- run: npm test
- run: npm run verify:skills
- run: npm run packs:check
- run: npm run packs:vendor:sync -- --check
- run: node skills/tools/verify-change/scripts/change_analyzer.js --mode staged || node skills/tools/verify-change/scripts/change_analyzer.js --mode working
- run: node skills/tools/verify-module/scripts/module_scanner.js .
- run: node skills/tools/verify-quality/scripts/quality_checker.js .
Expand Down Expand Up @@ -50,13 +52,16 @@ jobs:

export HOME="$abyss_home"
export USERPROFILE="$abyss_home"
export CODE_ABYSS_GSTACK_SOURCE="$GITHUB_WORKSPACE/test/fixtures/gstack-codex-source"

npx --yes --package "./$pkg_tgz" code-abyss --target claude -y

test -f "$abyss_home/.claude/CLAUDE.md"
test -d "$abyss_home/.claude/skills"
test -d "$abyss_home/.claude/skills/gstack/review"
test -d "$abyss_home/.claude/commands"
test -f "$abyss_home/.claude/commands/gen-docs.md"
test -f "$abyss_home/.claude/commands/review.md"
test -f "$abyss_home/.claude/settings.json"
test -f "$abyss_home/.claude/.sage-uninstall.js"

Expand Down Expand Up @@ -93,19 +98,66 @@ jobs:

export HOME="$abyss_home"
export USERPROFILE="$abyss_home"
export CODE_ABYSS_GSTACK_SOURCE="$GITHUB_WORKSPACE/test/fixtures/gstack-codex-source"

npx --yes --package "./$pkg_tgz" code-abyss --target codex -y

test -f "$abyss_home/.codex/AGENTS.md"
test -d "$abyss_home/.codex/skills"
test ! -e "$abyss_home/.codex/AGENTS.md"
test -d "$abyss_home/.agents/skills"
test -d "$abyss_home/.agents/bin/lib"
test -f "$abyss_home/.agents/skills/gstack/review/SKILL.md"
test -f "$abyss_home/.codex/config.toml"
test -d "$abyss_home/.codex/prompts"
test -f "$abyss_home/.codex/prompts/gen-docs.md"
test ! -e "$abyss_home/.codex/settings.json"
test -f "$abyss_home/.codex/.sage-uninstall.js"

npx --yes --package "./$pkg_tgz" code-abyss --uninstall codex

test ! -e "$abyss_home/.codex/AGENTS.md"
test ! -e "$abyss_home/.codex/skills"
test ! -e "$abyss_home/.agents/skills"
test ! -e "$abyss_home/.codex/.sage-backup"

smoke-gemini:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- name: Pack npm tarball
shell: bash
run: npm pack
- name: Smoke install/uninstall Gemini target
shell: bash
run: |
set -euo pipefail

pkg_tgz="$(ls code-abyss-*.tgz | head -n 1)"
abyss_home="$RUNNER_TEMP/abyss-home"
rm -rf "$abyss_home"
mkdir -p "$abyss_home"

export HOME="$abyss_home"
export USERPROFILE="$abyss_home"
export CODE_ABYSS_GSTACK_SOURCE="$GITHUB_WORKSPACE/test/fixtures/gstack-codex-source"

npx --yes --package "./$pkg_tgz" code-abyss --target gemini -y

test -f "$abyss_home/.gemini/GEMINI.md"
test -d "$abyss_home/.gemini/skills"
test -d "$abyss_home/.gemini/commands"
test -f "$abyss_home/.gemini/commands/gen-docs.toml"
test -f "$abyss_home/.gemini/commands/review.toml"
test -d "$abyss_home/.gemini/skills/gstack/review"
test -f "$abyss_home/.gemini/settings.json"
test -f "$abyss_home/.gemini/.sage-uninstall.js"

npx --yes --package "./$pkg_tgz" code-abyss --uninstall gemini

test ! -e "$abyss_home/.gemini/GEMINI.md"
test ! -e "$abyss_home/.gemini/skills"
test ! -e "$abyss_home/.gemini/.sage-backup"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@ node_modules/
# Local config
.env.local
.ace-tool/
.code-abyss/reports/
137 changes: 137 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

Code Abyss is an npm package that installs a "邪修红尘仙" persona configuration into Claude Code, Codex CLI, and Gemini CLI. It delivers: persona rules, 4 switchable output styles, 56 skill documents, and 5 executable verification/generation tools.

## Commands

```bash
npm test # Run Jest test suite
npm run verify:skills # Validate all SKILL.md frontmatter contracts (fail-fast gate)
node bin/install.js --help # Installer CLI help
node bin/install.js --target claude -y # Zero-config install to ~/.claude/
node bin/install.js --target codex -y # Zero-config install to ~/.codex/
node bin/install.js --target gemini -y # Zero-config install to ~/.gemini/
node bin/install.js --list-styles # List available output styles
```

Running individual verify tools directly:
```bash
node skills/tools/verify-security/scripts/security_scanner.js <path>
node skills/tools/verify-module/scripts/module_scanner.js <path>
node skills/tools/verify-change/scripts/change_analyzer.js --mode staged|working
node skills/tools/verify-quality/scripts/quality_checker.js <path>
node skills/tools/gen-docs/scripts/doc_generator.js <path>
```

Running a single test file:
```bash
npx jest test/install-registry.test.js --runInBand
```

CI runs on Node 18/20/22: `npm ci && npm test && npm run verify:skills` plus all 4 verify tools + smoke install/uninstall on 3 platforms.

## Architecture

### Three-Layer System

| Layer | Source | Purpose |
|-------|--------|---------|
| Identity & Rules | `config/CLAUDE.md` | Persona, rules, scene routing, execution chains |
| Output Style | `output-styles/*.md` + `index.json` | Style registry + per-style templates |
| Knowledge | `skills/**/*.md` | Domain skill documents + executable tools |

`config/AGENTS.md` remains a repository snapshot, but Codex runtime installation no longer writes a generated `~/.codex/AGENTS.md`. Codex now runs in a `skills-only` shape and installs Code Abyss plus gstack under `~/.agents/skills/`.

### Skill Registry (Single Source of Truth)

`bin/lib/skill-registry.js` is the authoritative skill discovery engine for installed skills, `run_skill.js`, Claude command generation, and CI validation.

- Each skill's metadata lives in `skills/**/SKILL.md` YAML frontmatter
- Required fields: `name` (kebab-case slug), `description`, `user-invocable`
- Optional fields: `allowed-tools` (default: `Read`), `argument-hint`, `aliases`
- `category` is auto-inferred from directory prefix (`tools/` → tool, `domains/` → domain, `orchestration/` → orchestration)
- `runtimeType` is auto-inferred: `scripts/` has exactly one `.js` → `scripted`, else `knowledge`
- Registry fail-fast validates: missing fields, bad slugs, illegal tool names, duplicate names, multiple script entries

### Pack Registry

`packs/*/manifest.json` defines installable packs. `abyss` is the core pack; `gstack` is a pinned upstream pack consumed by the Claude/Codex auto-install flows. `bin/lib/pack-registry.js` is the source of truth for host file mappings and upstream metadata.

Project-level automatic pack sync is driven by `.code-abyss/packs.lock.json`. The installer reads the nearest lock file from the current working directory upward and installs host-specific packs according to `required`, `optional`, `optional_policy`, and `sources`. `node bin/packs.js bootstrap` initializes the lock plus README/CONTRIBUTING snippets, `--apply-docs` writes them back into repo docs, `vendor-pull` / `vendor-sync` manage local sources, `vendor-sync --check` acts as a gate, `report summary` reads `.code-abyss/reports/`, and `uninstall <pack>` removes pack-specific runtime artifacts with a report.

### Style Registry

`bin/lib/style-registry.js` manages `output-styles/index.json`. Exactly one style must be `default`. Each style has `slug`, `label`, `description`, `file`, `targets`, `default`.

### Dual-Target Generation

The installer generates different artifacts per target CLI:

- **Claude**: `~/.claude/commands/*.md` (slash commands) — `runtimeType=scripted` calls `run_skill.js`, `knowledge` reads SKILL.md directly
- **Codex**: `~/.agents/skills/**/SKILL.md` — Codex discovers user skills from `~/.agents/skills`; Code Abyss auto-installs an embedded gstack runtime under `~/.agents/skills/gstack`
- **Gemini**: `~/.gemini/GEMINI.md` + `~/.gemini/commands/*.toml` + `~/.gemini/skills/**/SKILL.md` — Gemini reads persistent context from `GEMINI.md` and custom commands from TOML files

Claude command generation and Codex skill installation share the same skill source tree; only Claude filters on `user-invocable` to emit slash commands.

### Adapter Pattern

`bin/install.js` is the orchestration layer. Target-specific logic lives in adapters:
- `bin/adapters/claude.js` — Claude auth detection, settings merge, core files mapping
- `bin/adapters/codex.js` — Codex auth detection, config.toml merge, core files mapping
- `bin/lib/ccline.js` — Claude status bar (ccline) integration
- `bin/lib/style-registry.js` — Style catalog + repository AGENTS snapshot assembly
- `bin/lib/utils.js` — Shared: `copyRecursive`, `rmSafe`, `deepMergeNew`, `parseFrontmatter`, `shouldSkip`

### Skill Execution

`skills/run_skill.js` is the script-type skill runner:
1. Resolve skill via registry → validate `runtimeType=scripted`
2. Acquire target lock (async polling, 30s timeout)
3. Spawn child process with the script entry
4. Propagate exit code, release lock on exit/signal

Knowledge-type skills are read-only — no script execution, just load SKILL.md content.

## Key Contracts

### SKILL.md Frontmatter

```yaml
---
name: verify-quality # kebab-case, unique across all skills
description: Code quality gate
user-invocable: true # false = knowledge-only, not exposed as Claude slash command
allowed-tools: Bash, Read, Glob # optional, default: Read
argument-hint: <scan-path> # optional
aliases: vq # optional comma-separated aliases
---
```

### Adding a New Skill

1. Create `skills/<category>/<skill-name>/SKILL.md` with required frontmatter
2. For script-type: add exactly one `scripts/<name>.js` entry point
3. Run `npm run verify:skills` — must pass with zero errors
4. Run `npm test` — especially `test/install-registry.test.js`, `test/install-generation.test.js`, `test/run-skill.test.js`
5. Verify no name collision with existing skills

### Style Contract

- Exactly one entry in `output-styles/index.json` must have `default: true`
- `slug` must be kebab-case, unique
- `targets` defaults to `["claude", "codex"]` if omitted
- Corresponding `.md` file must exist in `output-styles/`

## Install Targets

| Target | Config file | Skill artifacts | Style mechanism |
|--------|-------------|-----------------|-----------------|
| Claude | `~/.claude/CLAUDE.md` | `~/.claude/commands/*.md` + `~/.claude/skills/` | `settings.json.outputStyle` = slug |
| Codex | `~/.codex/config.toml` | `~/.agents/skills/` + `~/.agents/skills/gstack/` | Skills-only runtime; no generated AGENTS.md |
| Gemini | `~/.gemini/settings.json` | `~/.gemini/GEMINI.md` + `~/.gemini/commands/*.toml` + `~/.gemini/skills/` | Global context + TOML command runtime |

Backups go to `<target-dir>/.sage-backup/` with `manifest.json`. Uninstall restores from backup.
35 changes: 31 additions & 4 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,16 @@ Code Abyss 是 CLI 助手的个性化配置方案(支持 Claude Code CLI 与 C
- 脚本型 skill 位于 `skills/**/scripts/*.js`
- 每个 skill 的权威元数据来自对应 `SKILL.md` frontmatter
- 共享 registry(`bin/lib/skill-registry.js`)负责扫描、分类、脚本入口解析
- Claude commands、Codex prompts、`skills/run_skill.js` 都消费同一份 skill 清单
- Claude commands、Codex skill 安装、`skills/run_skill.js` 都消费同一份 skill 清单

这样避免安装器、执行器、双端生成器各自维护一套 discovery 逻辑。

### 3. 配置文件位置

根据目标 CLI 选择配置文件:
- Claude Code CLI:`~/.claude/CLAUDE.md`
- Codex CLI:`~/.codex/AGENTS.md`
- Codex CLI:`~/.codex/config.toml`
- Codex 用户级 skills:`~/.agents/skills/`

安装脚本通过 `--target claude|codex`(或交互选择)确定写入位置,确保用户级配置不污染项目目录。

Expand All @@ -56,11 +57,11 @@ Code Abyss 是 CLI 助手的个性化配置方案(支持 Claude Code CLI 与 C

### 5. Skill registry 与双端生成

- 问题:skills 元数据发现、脚本执行、Claude commands、Codex prompts 曾各自扫描,容易漂移。
- 问题:skills 元数据发现、脚本执行、Claude commands、Codex 侧安装规则曾各自扫描,容易漂移。
- 决策:以 `SKILL.md` frontmatter 为唯一事实源,抽出共享 registry,统一产出 `name`、`description`、`userInvocable`、`allowedTools`、`argumentHint`、`relPath`、`category`、`runtimeType`、`scriptPath`、`meta` 等标准化字段;`kind` 与 kebab-case compatibility 镜像字段已从 registry public surface 移除。
- 决策:`category` 按目录前缀自动推断(`tools` / `domains` / `orchestration`),`runtimeType` 按脚本入口自动推断(`scripted` / `knowledge`)。
- 决策:registry 在扫描阶段 fail-fast 校验 frontmatter 解析、必填字段、合法工具名、重复 skill name、多脚本入口,拒绝把脏数据交给后续生成链。
- 取舍:多了一层 registry 抽象,但 commands/prompts/run_skill/CI gate 共享同一条契约,测试面更集中,错误更早暴露。
- 取舍:多了一层 registry 抽象,但 commands/skill-install/run_skill/CI gate 共享同一条契约,测试面更集中,错误更早暴露。

### 6. `run_skill.js` 职责收窄

Expand All @@ -81,8 +82,34 @@ Code Abyss 是 CLI 助手的个性化配置方案(支持 Claude Code CLI 与 C
- 决策:新增 `output-styles/index.json` 作为 style registry,统一维护 `slug`、`label`、`description`、`file`、`targets`、`default`。
- 决策:Claude 继续安装整个 `output-styles/` 目录,并把 `settings.json.outputStyle` 写为所选 style slug。
- 决策:Codex 不再直接复制仓库内静态 `config/AGENTS.md`,改为安装时动态拼接 `config/CLAUDE.md + output-styles/<slug>.md` 生成目标 `AGENTS.md`。
- 决策:Codex skills 改对齐官方当前规范,安装到 `~/.agents/skills/`;`agents/openai.yaml` 只负责可选 metadata,而不是旧 `prompts/` 入口。
- 取舍:安装器多了一层 registry 与模板拼装逻辑,但换来多风格切换能力,并消除 Codex 风格与仓库 snapshot 的长期漂移。

### 9. Pack registry(进行中)

- 问题:`abyss` core 资源与 `gstack` 融合逻辑分别散落在 adapter、installer、测试中,host 映射与 upstream pin 容易再次漂移。
- 决策:新增 `packs/abyss/manifest.json` 与 `packs/gstack/manifest.json`,把 host 文件映射、upstream repo/commit、runtime 目录、路径改写规则集中到 manifest。
- 决策:`bin/lib/pack-registry.js` 成为安装器读取 pack 元数据的唯一入口;Claude/Codex adapter 只消费 registry,不再手写 core file 列表。
- 取舍:多一层 manifest 解析,但后续扩展 Claude 侧 gstack、更多第三方 pack 或 pack 锁文件时不必再次散改 installer 常量。

### 10. 项目级 packs.lock(进行中)

- 问题:上一阶段的 gstack 自动融合是“全局默认行为”,缺乏项目粒度开关,容易把不相关仓库也拖入同一套 workflow。
- 决策:新增 `.code-abyss/packs.lock.json`,支持按 host 声明 `required` / `optional` packs;安装器从当前工作目录向上查找最近的 lock 文件。
- 决策:安装器只自动同步 lock 中的 `required` packs;本仓当前为 Claude/Codex 都声明 `gstack`,因此保持“零手动触发”的体验。
- 取舍:多了一层项目配置解析,但把“自动化”从全局硬编码降成项目声明,更适合团队协作与多仓共存。

### 11. optional source 策略 + bootstrap/diff(进行中)

- 问题:`optional` pack 之前只有装/不装,没有来源控制;项目初始化也只能手写 lock 文件,缺少推荐文档片段与差异报告。
- 决策:`packs.lock` 扩展 `sources.<pack>=pinned|local|disabled`。`pinned` 走 pack manifest 的 upstream pin,`local` 走 `.code-abyss/vendor/<pack>` 或 env override,`disabled` 明确跳过安装。
- 决策:新增 `bin/packs.js bootstrap`,一次生成/更新 `packs.lock` 与 `.code-abyss/snippets/{README,CONTRIBUTING}.packs.md`;`--apply-docs` 可把 snippet 回写到现有文档。
- 决策:新增 `vendor-pull` / `vendor-sync`,让 `source=local` 不再依赖手工拷贝 vendor 源。
- 决策:新增 `uninstall <pack>`,按 host 清理指定 pack 的运行时残留,并可选同步更新 lock 与 vendor。
- 决策:新增 `bin/packs.js diff`,输出当前 lock 相对默认模板的 host/pack/source/policy 差异。
- 决策:安装 manifest 新增 `pack_reports`,安装完成与卸载时按 pack 维度输出摘要。
- 取舍:schema 更复杂,但换来可审计的 pack 来源控制、项目引导闭环,以及更清晰的安装/卸载报告。

| 债务 | 原因 | 计划 |
|------|------|------|
| 无自动更新机制 | 复杂度控制 | 视需求添加 |
Expand Down
Loading
Loading