协作头脑风暴
brainstorming
在实现前澄清需求、探索设计选择,并形成清晰的开发方向。
wiring-extract-static【开发与工程】Emit run-scoped static wiring edges from a target project via SCIP (scip-python, scip-typescript) plus framework plug-ins (FastAPI, Express) or a generic fallback (Python ast + JS regex). Writes `.wiring/runs/<run_id>/static.jsonl` and `manifest.json` conforming to `wiring-source-edge.v1` and `wiring-source-manifest.v1`. Single-writer of `static.json…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
.wiring/runs/<run_id>/static.jsonl and manifest.json conforming to wiring-source-edge.v1 and wiring-source-manifest.v1. Single-writer of static.jsonl. Deterministic Python, no LLM calls. Invoked by bob with a claim UUID; heartbeats every 60s via ~/.claude/skills/_meta/claims.py.
family: wiring
disambiguation: EMITS per-run static edges from source via SCIP and framework plug-ins. Merging run artefacts into the promoted snapshot is wiring-reconcile.Status: PRODUCTION. WP-1 (schemas) + WP-2 (runtime + plug-in API + generic fallback) + WP-3 (FastAPI + Express plug-ins) complete. Driven by bob via S023 wiring-ledger pipeline.
Design document: /path/to/project/docs/plans/2026-04-14-wiring-skills-design.md §5.1
Given a target project directory and a run UUID issued by bob, emit per-run static wiring edges. Edges describe how components in the target project call, route to, import from, or persist into each other. Output:
.wiring/runs/<run_id>/manifest.json — conforms to wiring-source-manifest.v1; lists every extractor source that ran, its status, and gaps.wiring/runs/<run_id>/static.jsonl — one JSON line per edge, each conforms to wiring-source-edge.v1.ledger/requests/<uuid>.request.yaml that bob (sole ledger writer, CB4) consumesThe skill itself NEVER writes to the ledger, NEVER invokes LLMs, NEVER touches .wiring/ root (that is bob's single-creator domain), and NEVER writes outside its run-scoped subdirectory.
python3 ~/.claude/skills/wiring-extract-static/scripts/run.py \
--project-dir "$PROJECT_DIR" \
--run-id "<uuid>" \
--claim-uuid "<claim_uuid>" \
[--config .ledger/config.yaml]
Exit codes:
0 — full or partial success. Gaps and per-source skipped/failed statuses are recorded in the manifest; downstream reconcile proceeds.1 — unrecoverable. Disk full, claim revoked, git write-tree fails, target .wiring/ missing.claim_uuid (first heartbeat immediate; background thread every 60s).git write-tree → workspace_tree_hash..wiring/runs/<run_id>/ and write initial manifest.json with status: in_progress.scripts/plugin_loader.py.target_framework in detected frameworks), run it against the language's source files.generic-treesitter fallback for that language.wiring-source-edge.v1 before it is appended; malformed edges are dropped and reported as a gap.src_component / dst_component comes from progress/contract-map.yaml via ComponentResolver. Files that do not match any component's source_paths are recorded as unmapped_path:<path> gaps.static.jsonl and the terminal manifest.json atomically (tmp + rename).target_stage (SCAFFOLDED at first call, later UNIT_TESTED/INTEGRATED per bob's orchestration).~/.claude/skills/wiring-extract-static/
├── SKILL.md
├── schemas/
│ ├── wiring-source-edge.v1.json # frozen (WP-1)
│ └── wiring-source-manifest.v1.json # frozen (WP-1)
├── scripts/
│ ├── run.py # CLI entry
│ ├── plugin_loader.py # discovers & validates plug-ins
│ ├── component_resolver.py # contract-map-driven component id lookup
│ ├── heartbeat.py # claim heartbeat thread (invokes claims.py)
│ └── scip_invoke.sh # SCIP subprocess wrapper w/ 120s timeout
├── extractors/
│ ├── generic-treesitter/ # fallback: Python ast + JS/TS regex
│ ├── fastapi/ # WP-3 plug-in
│ └── express/ # WP-3 plug-in
├── references/
│ ├── plugin-author-guide.md # frozen plug-in contract
│ ├── edge-schema.md # (future) human-readable schema notes
│ └── scip-notes.md # (future) SCIP gotchas
├── fixtures/
│ ├── fastapi-minimal/ # WP-3 smoke fixture
│ └── express-minimal/ # WP-3 smoke fixture
└── tests/
├── test_schemas.py # 6/6 (WP-1)
├── test_component_resolver.py
├── test_plugin_loader.py
├── test_generic_treesitter.py
├── test_heartbeat.py
├── test_plugin_fastapi.py # WP-3
└── test_plugin_express.py # WP-3
See references/plugin-author-guide.md. Summary:
plugin.json declares id, semver version, target_framework, languages, edge_kinds, is_fallback, description.extractor.py exposes extract_edges(project_dir, symbols, source_files, workspace_tree_hash, extractor_version, config, resolve_component) -> Iterator[edge dict].edge_id MUST come from ~/.claude/skills/wiring-reconcile/scripts/edge_identity.compute_edge_id(...).external:<package> for external deps.edge_id is five-tuple sha256 truncated to 16 hex — one source of truth in wiring-reconcile/scripts/edge_identity.py. No re-implementation.static.jsonl — only this skill writes it. Agent-asserted edges go in the sibling asserted/<agent_id>.jsonl, owned by the agent.Run everything under tests/ with Python 3.12+. Current pass count:
test_schemas.py — 6/6test_component_resolver.py — 3/3test_plugin_loader.py — 6/6test_generic_treesitter.py — 4/4test_heartbeat.py — 3/3test_plugin_fastapi.py — fixture-driven smoketest_plugin_express.py — fixture-driven smokescip-python, scip-typescript) are optional; when absent the corresponding source is marked skipped and generic-treesitter covers the language with reduced precision (imports + intra-component calls only).ast + JS regex. Real tree-sitter Python bindings are optional and deferred to v2 when the dependency lands in env-adoption.