Skip to content
Merged
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
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@

## [Unreleased]

## [0.2.0] - 2026-06-21
### Added
- ゲートの実機化: `bin/dango-state.mjs` に `check --<name> pass|fail` を追加し、
ビルド/起動/スモークの合否を `check.json` に記録。`gate` は「レビュー『高』が残る」
**または**「実機チェックに `fail` がある」を阻害要因として `continue|loop-back|escalate`
を判定する(文書だけでなく動作で関門を閉じる)。`check` 未記録時は従来どおりレビューのみで判定。
- `dango-run` に **autoplan(計画一気通し)モード**。計画フェーズ(`dango-plan`→`dango-spec`
→自己レビュー)を無確認で連鎖し、実装(`Edit`)の手前で人間に渡す。
### Changed
- `gate --reset` が往復カウンタに加えて前回の `check.json` も初期化(feature 跨ぎの誤ブロック防止)。
- `decisions.log` のゲート行に `checks_failed=` を追記。

## [0.1.3] - 2026-06-17
### Added
- OSS 運用の環境整備: `CODE_OF_CONDUCT.md`、`SECURITY.md`、Issue/PR テンプレート、
Expand All @@ -32,7 +44,8 @@
- 核となる日本語レビュー役(全角半角・和暦・禁則・郵便番号/住所・IME/組版)。
- インストール/アンインストール、状態・決定ログ helper(Node・ビルド不要)。

[Unreleased]: https://github.com/fla9ua/dango-pack/compare/v0.1.3...HEAD
[Unreleased]: https://github.com/fla9ua/dango-pack/compare/v0.2.0...HEAD
[0.2.0]: https://github.com/fla9ua/dango-pack/compare/v0.1.3...v0.2.0
[0.1.3]: https://github.com/fla9ua/dango-pack/compare/v0.1.2...v0.1.3
[0.1.2]: https://github.com/fla9ua/dango-pack/compare/v0.1.1...v0.1.2
[0.1.1]: https://github.com/fla9ua/dango-pack/compare/v0.1.0...v0.1.1
Expand Down
63 changes: 54 additions & 9 deletions bin/dango-state.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
// node bin/dango-state.mjs log 決定ログを表示
// node bin/dango-state.mjs verdict --high N [--mid N --low N] [--target T --branch B]
// レビュー結果を構造化して保存(verdict.json)
// node bin/dango-state.mjs gate [--reset] verdict.json と往復回数から
// node bin/dango-state.mjs check --<name> pass|fail [...]
// 実機チェック(ビルド/起動/スモーク等)の
// 合否を記録(check.json)。gate がこれも見る
// node bin/dango-state.mjs gate [--reset] verdict.json + check.json + 往復回数から
// continue|loop-back|escalate をコード判定

import { execSync } from 'node:child_process';
Expand Down Expand Up @@ -113,16 +116,44 @@ switch (cmd) {
process.stdout.write(`verdict saved: high=${high} mid=${mid} low=${low}\n`);
break;
}
case 'check': {
// 実機チェック(ビルド通過/起動/主要導線スモーク等)の合否を記録する。
// gate はこれも阻害要因として見る → 「文書」だけでなく「動作」で関門を閉じる。
const f = parseFlags(rest);
const checks = {};
for (const [k, v] of Object.entries(f)) {
if (k === '_' || k === 'reset') continue;
const val = String(v).toLowerCase();
if (val !== 'pass' && val !== 'fail') {
console.error(`check: --${k} には pass か fail を渡してください(受領: ${v})`);
process.exit(1);
}
checks[k] = val;
}
mkdirSync(base, { recursive: true });
const checkPath = join(base, 'check.json');
if (f.reset || Object.keys(checks).length === 0) {
writeFileSync(checkPath, JSON.stringify({ checks: {}, at: new Date().toISOString() }, null, 2) + '\n');
process.stdout.write('check reset: (記録なし)\n');
break;
}
writeFileSync(checkPath, JSON.stringify({ checks, at: new Date().toISOString() }, null, 2) + '\n');
const summary = Object.entries(checks).map(([k, v]) => `${k}=${v}`).join(' ');
process.stdout.write(`check saved: ${summary}\n`);
break;
}
case 'gate': {
// 状態(verdict + 往復回数)を読んで、continue|loop-back|escalate をコードで決める。
// 状態(verdict + check + 往復回数)を読んで、continue|loop-back|escalate をコードで決める。
// モデルはこの結果に従うだけ。3回上限の判定もここで強制する。
mkdirSync(base, { recursive: true });
const f = parseFlags(rest);
const gatePath = join(base, 'gate.json');

if (f.reset) {
// 新しい feature の頭で往復カウンタも前回の実機チェックも初期化する。
writeFileSync(gatePath, JSON.stringify({ roundtrips: 0 }, null, 2) + '\n');
process.stdout.write('gate reset: roundtrips=0\n');
writeFileSync(join(base, 'check.json'), JSON.stringify({ checks: {}, at: new Date().toISOString() }, null, 2) + '\n');
process.stdout.write('gate reset: roundtrips=0, checks cleared\n');
break;
}

Expand All @@ -134,8 +165,16 @@ switch (cmd) {
const gateState = readJson(gatePath, { roundtrips: 0 });
const high = Number(verdict.high ?? 0);

// 実機チェック: check.json があれば fail を阻害要因として扱う(無ければ従来どおり無視)。
const check = readJson(join(base, 'check.json'), null);
const failedChecks = check && check.checks
? Object.entries(check.checks).filter(([, v]) => v === 'fail').map(([k]) => k)
: [];

const blocked = high > 0 || failedChecks.length > 0;

let action;
if (high === 0) {
if (!blocked) {
action = 'continue';
} else if (gateState.roundtrips < MAX_ROUNDTRIPS) {
gateState.roundtrips += 1;
Expand All @@ -146,18 +185,24 @@ switch (cmd) {
writeFileSync(gatePath, JSON.stringify(gateState, null, 2) + '\n');

const iter = gateState.roundtrips;
const line = `${new Date().toISOString()}\tgate\tstep=review\titer=${iter}\thigh=${high}\tmid=${verdict.mid ?? 0}\tlow=${verdict.low ?? 0}\taction=${action}\n`;
const checksField = failedChecks.length ? failedChecks.join(',') : '-';
const line = `${new Date().toISOString()}\tgate\tstep=review\titer=${iter}\thigh=${high}\tmid=${verdict.mid ?? 0}\tlow=${verdict.low ?? 0}\tchecks_failed=${checksField}\taction=${action}\n`;
appendFileSync(join(base, 'decisions.log'), line);

// 阻害要因を人間語でまとめる(レビュー指摘・実機 fail の両方を明示)。
const reasons = [];
if (high > 0) reasons.push(`重大度「高」${high}件`);
if (failedChecks.length) reasons.push(`実機チェック fail: ${failedChecks.join(', ')}`);
const reasonText = reasons.join(' / ');
const human = {
continue: `重大度「高」なし → 次の工程へ進む (continue)`,
'loop-back': `重大度「高」${high}件 → 実装へ戻す (loop-back ${iter}/${MAX_ROUNDTRIPS})`,
escalate: `往復上限 ${MAX_ROUNDTRIPS} 回に達し「高」${high}件が残存 → 人間にエスカレート (escalate)`,
continue: `阻害要因なし(レビュー「高」0・実機チェック fail なし) → 次の工程へ進む (continue)`,
'loop-back': `${reasonText} → 実装へ戻す (loop-back ${iter}/${MAX_ROUNDTRIPS})`,
escalate: `往復上限 ${MAX_ROUNDTRIPS} 回に達し ${reasonText} が残存 → 人間にエスカレート (escalate)`,
}[action];
process.stdout.write(`${human}\naction=${action}\n`);
break;
}
default:
console.error('usage: dango-state.mjs <init|path|decide|log|verdict|gate> [args]');
console.error('usage: dango-state.mjs <init|path|decide|log|verdict|check|gate> [args]');
process.exit(1);
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dango-pack",
"version": "0.1.3",
"version": "0.2.0",
"description": "日本のチーム開発に最適化した、Claude Code / Codex 用の仮想開発組織",
"type": "module",
"bin": {
Expand Down
48 changes: 41 additions & 7 deletions skills/dango-run/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: dango-run
version: 0.1.3
version: 0.2.0
description: "dango-packのオーケストレータ — 計画→実装→日本語レビュー→出荷を順に回し、足りない役割をAIが演じる。(dango-pack)"
allowed-tools:
- Read
Expand All @@ -15,6 +15,9 @@ triggers:
- dango-packで進めて
- dango-pack run
- チームで開発して
- dango-pack autoplan
- 計画を一気に
- 計画だけ先に
---

## この役割は何者か
Expand Down Expand Up @@ -53,19 +56,48 @@ triggers:
全角半角・和暦・禁則・郵便番号/住所・IME/組版を点検。`reviews/{日付}.md` と
`verdict.json`(重大度の件数)を出力させる。

3.5. **実機チェック(動作で関門を閉じる)** — レビュー(文書)だけでなく、
**実際に動かした結果**をゲートに渡す。最低限「ビルド通過 / 起動 / 主要導線の
スモーク」を試し、合否を記録する:
```bash
node bin/dango-state.mjs check --build pass --start pass --smoke fail
```
- 名前(`--build` 等)は対象に合わせて自由に付けてよい。値は `pass`/`fail` のみ。
- 実行手段は対象次第(`npm test` / `npm run build` / 起動しての手動確認 / ブラウザ
確認など)。**合否は自分の感覚で決めず、走らせた事実をそのまま記録する**。
- 試せる手段が無いときは記録を省いてよい(その場合ゲートは従来どおりレビューだけで
判定する)。これは非破壊なので**確認なしで自動実行**してよい。

4. **ゲート判定** — 次の工程に進むかどうかは **自分で判断せず、コードに決めさせる**:
```bash
node bin/dango-state.mjs gate # verdict.json と往復回数から判定
node bin/dango-state.mjs gate # verdict.json + check.json + 往復回数から判定
```
出力末尾の `action=` に従う:
ゲートは「レビュー重大度『高』が残る」**または**「実機チェックに `fail` がある」を
阻害要因として扱う。出力末尾の `action=` に従う:
- `continue` → 5(出荷)へ進む
- `loop-back` → 2(実装)へ戻り、レビュー指摘を直してから再度 3→4
- `loop-back` → 2(実装)へ戻り、レビュー指摘と実機 fail を直してから再度 3→3.5→4
- `escalate` → 自動で回さず、残課題を要約して人間に渡す
往復上限(実装⇄レビュー 3 回)はコード側で強制されるので、自分で数えない。

5. **出荷 (`dango-ship`)**
日本語のコミット規約・PR本文で締める。

## 計画一気通し(autoplan モード)

「計画を一気に」「dango-pack autoplan」「計画だけ先に」等のとき、または feature の
頭で計画を素早く固めたいとき、**計画フェーズだけを無確認で連鎖**させる:

- 対象は **非破壊の文書生成のみ**:`dango-plan`(要件・受け入れ条件・作業分解)→
`dango-spec`(要件定義書/基本設計書/詳細設計書)→ 生成物の自己レビュー、を
**途中で止めずに**一気に通し、`plan.md` 一式を仕上げる。
- ここで止まるのは **本物の方針分岐だけ**(後で覆すと手戻りが大きい選択)。それは
`AskUserQuestion` で確認する。文書の体裁・粒度など覆しやすい判断では止まらない。
- **実装(`Edit`)には踏み込まない。** autoplan のゴールは「実装着手の一歩手前まで
計画を仕上げる」こと。計画が揃ったら要点を要約し、「このまま実装(2.)へ進めますか?」
と人間に渡す。
- 通常モード(feature 丸ごと)との違いは**計画工程で逐一確認しない**点だけ。実装以降の
線引き(Edit/ship の手前で止める・ゲートはコード判定)は通常モードと同じ。

## ゲート(関門)

- 進む/戻る/エスカレートの判断は **`dango-state.mjs gate` の `action=` が一次情報**。
Expand All @@ -80,9 +112,11 @@ triggers:
ユーザーに毎回コマンドを叩かせない。一度この流れに入ったら、**確認なしで自分で
回す工程**と、**必ず人間に確認する工程**を分ける:

- **確認なしで自動実行(非破壊):** `gate --reset` / `verdict` / `gate` / `decide` /
`log`、および `dango-review` の点検そのもの。これらは `~/.dango-pack` 配下を
読み書きするだけなので、いちいち聞かずに走らせてよい。
- **確認なしで自動実行(非破壊):** `gate --reset` / `verdict` / `check` / `gate` /
`decide` / `log`、および `dango-review` の点検・実機チェックの実行そのもの。これらは
`~/.dango-pack` 配下の読み書きと読み取り専用の動作確認なので、いちいち聞かずに
走らせてよい(ただし実機チェックの手段が `git push` 等の外向き操作を伴う場合は、
その操作だけ「必ず人間に確認」側に従う)。
- **必ず人間に確認(外向き・破壊的):** `Edit` でのコード修正、`dango-ship`(コミット/
PR)、外部公開を伴う操作。loop-back でレビュー指摘を直すときも、修正の適用前に
一言告げる。
Expand Down
Loading