phasegate 0.160.8 → 0.160.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/docs/guide/cli-reference.md +1 -1
- package/docs/guide/configuration.md +3 -1
- package/docs/guide/hooks-integration.md +2 -1
- package/package.json +1 -1
- package/scripts/harness/agent-integration/infrastructure/adapters/child-process-cli-executor-adapter.ts +16 -2
- package/scripts/harness/agent-integration/presentation/stop-hook.ts +17 -2
- package/scripts/harness/main.ts +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.160.10] - 2026-05-16
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **WI-203 — Stop hook Complete Check execution** — resolves built-in `phasegate:*` hook commands through the packaged CLI entrypoint instead of unmanaged downstream wrapper files, distinguishes Complete Check validation failures from command wiring failures in strict Stop hook output, and documents that `scripts/harness/cli/complete-check.ts` is not required by standard install/reconcile.
|
|
15
|
+
|
|
16
|
+
## [0.160.9] - 2026-05-15
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **WI-201 — config plan apply discoverability** — documents `config:plan --apply` in subcommand help, top-level help, and CLI reference so agents can discover the managed config apply path from `--help`.
|
|
21
|
+
|
|
10
22
|
## [0.160.8] - 2026-05-15
|
|
11
23
|
|
|
12
24
|
### Fixed
|
|
@@ -28,7 +28,7 @@ Command names in this document are split into three surfaces:
|
|
|
28
28
|
| `uninstall --dry-run` / `--apply` | Remove PhaseGate-managed files and managed blocks using `.phasegate/manifest.json`; `--force` handles managed conflict cases. |
|
|
29
29
|
| `reconcile --dry-run` / `--apply` | Update PhaseGate-managed files to current package templates and refresh manifest hashes; `--force` allows managed-file replacement with backup. |
|
|
30
30
|
| `setup:agent` | Agent-readable setup planner and optional apply path. Options: `--intent <minimal\|recommended\|strict\|ci-only\|agent-hooks\|retrofit>`, `--agent <claude\|codex\|both>`, `--workflow <standard\|strict>`, `--with-husky`, `--with-ci`, `--dry-run`, `--apply`, `--json`. <!-- @work-item-id WI-172 --> |
|
|
31
|
-
| `config:plan` | Agent-readable configuration change planner. Options: `--intent <l4-strict\|codex-hooks\|ci-fail-on-warning\|baseline-reset\|quick-mode-strict>`, `--dry-run`, `--json`. <!-- @work-item-id WI-173 --> |
|
|
31
|
+
| `config:plan` | Agent-readable configuration change planner. Options: `--intent <l4-strict\|codex-hooks\|ci-fail-on-warning\|baseline-reset\|quick-mode-strict\|retrofit-bootstrap\|planning-mode-relax>`, `--dry-run`, `--apply`, `--json`. <!-- @work-item-id WI-173 --> <!-- @work-item-id WI-201 --> |
|
|
32
32
|
| `update-skills` | Compatibility alias for `reconcile`; use `reconcile` for new automation. |
|
|
33
33
|
| `scaffold-wi <unit> <type>` | Create `docs/inception/{unit}/WI-XXX/description.md` using the next free WI number. |
|
|
34
34
|
| `emit-agent-rules` | Print the AGENTS.md / CLAUDE.md WI workflow rules block. |
|
|
@@ -548,12 +548,14 @@ Controls how phasegate's agent-side hooks integrate with Claude Code. Currently
|
|
|
548
548
|
|
|
549
549
|
| Sub-field | Type | Default | Description |
|
|
550
550
|
|--------------------|-----------|---------|----------------------------------------------------------------------------------------------------------------------|
|
|
551
|
-
| `stopHook.enforce` | `boolean` | `false` | When `true`, a non-zero exit from `phasegate:complete-check` causes the Stop hook to emit `{"decision":"block","reason":"Complete Check failed (exitCode=N)"}` on stdout and exit with code 2, blocking Claude Code's turn. When `false` (default), the hook exits with the inner CLI's exit code, which Claude Code surfaces only as a transcript warning. |
|
|
551
|
+
| `stopHook.enforce` | `boolean` | `false` | When `true`, a non-zero exit from `phasegate:complete-check` causes the Stop hook to emit `{"decision":"block","reason":"Complete Check failed (exitCode=N)"}` on stdout and exit with code 2, blocking Claude Code's turn. If command invocation itself fails, the reason is `Complete Check execution failed (exitCode=N)`. When `false` (default), the hook exits with the inner CLI's exit code, which Claude Code surfaces only as a transcript warning. |
|
|
552
552
|
|
|
553
553
|
Use `enforce: true` when your team treats Complete Check failures as hard gates (e.g., disallow ending a session with failing tests or lint). Leave it as default `false` for an opt-in / advisory experience.
|
|
554
554
|
|
|
555
555
|
Reentry-detection cases (`REENTRY_DETECTED`) always exit with code 0 regardless of this setting; strict mode applies only to actual Complete Check failures.
|
|
556
556
|
|
|
557
|
+
The built-in Stop hook invokes the packaged PhaseGate CLI command directly; projects initialized or reconciled by PhaseGate do not need a local `scripts/harness/cli/complete-check.ts` wrapper for this setting. <!-- @work-item-id WI-203 -->
|
|
558
|
+
|
|
557
559
|
---
|
|
558
560
|
|
|
559
561
|
### Quick Mode
|
|
@@ -93,8 +93,9 @@ Use /quick-implementor skill for version changes in package.json.
|
|
|
93
93
|
|
|
94
94
|
### Stop (before session end)
|
|
95
95
|
- Runs `phasegate:complete-check` (L2-L4 full validation)
|
|
96
|
+
- The built-in Stop hook runs the packaged PhaseGate CLI command; downstream projects do not need to provide `scripts/harness/cli/complete-check.ts`.
|
|
96
97
|
- By default, the hook exits with the inner CLI's exit code, which Claude Code shows as a transcript warning but does not turn-block on.
|
|
97
|
-
- Set `agentIntegration.stopHook.enforce: true` in `phasegate.config.json` to enable **strict mode**: on Complete Check failure, the hook emits `{"decision":"block","reason":"Complete Check failed (exitCode=N)"}` on stdout and exits with code 2, hard-blocking Claude Code's turn end. Reentry-detection still exits 0 regardless of this setting. See `docs/guide/configuration.md` `agentIntegration` section for details.
|
|
98
|
+
- Set `agentIntegration.stopHook.enforce: true` in `phasegate.config.json` to enable **strict mode**: on Complete Check failure, the hook emits `{"decision":"block","reason":"Complete Check failed (exitCode=N)"}` on stdout and exits with code 2, hard-blocking Claude Code's turn end. If the command cannot be invoked at all, strict mode reports `Complete Check execution failed (exitCode=N)` instead. Reentry-detection still exits 0 regardless of this setting. See `docs/guide/configuration.md` `agentIntegration` section for details. <!-- @work-item-id WI-203 -->
|
|
98
99
|
|
|
99
100
|
## Git hook metadata validation
|
|
100
101
|
|
package/package.json
CHANGED
|
@@ -1,22 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @layer infrastructure
|
|
3
3
|
* @unit agent-integration
|
|
4
|
+
* @work-item-id WI-203
|
|
4
5
|
*
|
|
5
6
|
* ChildProcessCliExecutorAdapter
|
|
6
7
|
* CliExecutorPort の実装。子プロセスで CLI コマンドを実行する
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
10
|
import { spawn } from 'node:child_process';
|
|
11
|
+
import { dirname, resolve } from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
10
13
|
import type { CliExecutorPort, CliExecutionResult } from '../../application/ports/cli-executor-port.js';
|
|
11
14
|
import { TimeoutError } from '../../application/ports/cli-executor-port.js';
|
|
12
15
|
|
|
16
|
+
function getHarnessMainPath(): string {
|
|
17
|
+
return resolve(dirname(fileURLToPath(import.meta.url)), '../../../main.ts');
|
|
18
|
+
}
|
|
19
|
+
|
|
13
20
|
/**
|
|
14
21
|
* CommandName を実行可能なコマンドに変換する
|
|
15
|
-
* 例: 'phasegate:lint' → ['npx', 'tsx', 'scripts/harness/
|
|
22
|
+
* 例: 'phasegate:lint' → ['npx', 'tsx', '<package>/scripts/harness/main.ts', 'phasegate:lint']
|
|
16
23
|
* テスト時は直接スクリプトパスで execute を呼ぶことも可能
|
|
17
24
|
*/
|
|
18
25
|
function resolveCommand(commandName: string): { cmd: string; args: string[] } {
|
|
19
|
-
|
|
26
|
+
if (commandName.startsWith('phasegate:')) {
|
|
27
|
+
return {
|
|
28
|
+
cmd: 'npx',
|
|
29
|
+
args: ['tsx', getHarnessMainPath(), commandName],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Legacy extension commands may still be provided as project-local wrappers.
|
|
20
34
|
const slug = commandName.replace('phasegate:', '');
|
|
21
35
|
return {
|
|
22
36
|
cmd: 'npx',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @layer presentation
|
|
3
3
|
* @unit agent-integration
|
|
4
|
+
* @work-item-id WI-203
|
|
4
5
|
*
|
|
5
6
|
* Stop Hook Adapter
|
|
6
7
|
* Claude Code の Stop Hook エントリポイント
|
|
@@ -19,6 +20,20 @@ interface StopHookInput {
|
|
|
19
20
|
session_id?: string;
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
function isCompleteCheckExecutionWiringFailure(stderr: string): boolean {
|
|
24
|
+
return (
|
|
25
|
+
/scripts\/harness\/cli\/complete-check\.ts/.test(stderr) ||
|
|
26
|
+
/ERR_MODULE_NOT_FOUND|Cannot find module/i.test(stderr)
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function formatCompleteCheckFailureReason(exitCode: number, stderr: string): string {
|
|
31
|
+
if (isCompleteCheckExecutionWiringFailure(stderr)) {
|
|
32
|
+
return `Complete Check execution failed (exitCode=${exitCode})`;
|
|
33
|
+
}
|
|
34
|
+
return `Complete Check failed (exitCode=${exitCode})`;
|
|
35
|
+
}
|
|
36
|
+
|
|
22
37
|
async function readStdin(): Promise<string> {
|
|
23
38
|
const chunks: Buffer[] = [];
|
|
24
39
|
for await (const chunk of process.stdin) {
|
|
@@ -97,10 +112,10 @@ async function main(): Promise<void> {
|
|
|
97
112
|
if (output.cliResult.exitCode !== 0) {
|
|
98
113
|
// WI-087 finding #4: enforce=true なら exit 2 + decision JSON で turn block
|
|
99
114
|
if (output.shouldEnforceFailure === true) {
|
|
100
|
-
const reason =
|
|
115
|
+
const reason = formatCompleteCheckFailureReason(output.cliResult.exitCode, output.cliResult.stderr);
|
|
101
116
|
process.stdout.write(`${JSON.stringify({ decision: 'block', reason })}\n`);
|
|
102
117
|
process.stderr.write(
|
|
103
|
-
|
|
118
|
+
`${reason} — strict mode により turn を block します\n`,
|
|
104
119
|
);
|
|
105
120
|
process.exit(2);
|
|
106
121
|
}
|
package/scripts/harness/main.ts
CHANGED
|
@@ -219,7 +219,7 @@ Gate semantics:
|
|
|
219
219
|
refresh-claude-md Refresh CLAUDE.md standard sections (--dry-run, --apply, --json)
|
|
220
220
|
p2:check-agent-context Check AGENTS.md / CLAUDE.md freshness (--threshold-days <n>, --json)
|
|
221
221
|
setup:agent Plan agent-driven setup (--intent <minimal|recommended|strict|ci-only|agent-hooks|retrofit>, --agent <claude|codex|both>, --dry-run|--apply, --json)
|
|
222
|
-
config:plan Plan safe config changes (--intent <l4-strict|codex-hooks|ci-fail-on-warning|baseline-reset|quick-mode-strict|retrofit-bootstrap|planning-mode-relax>, --dry-run, --json)
|
|
222
|
+
config:plan Plan safe config changes (--intent <l4-strict|codex-hooks|ci-fail-on-warning|baseline-reset|quick-mode-strict|retrofit-bootstrap|planning-mode-relax>, --dry-run|--apply, --json)
|
|
223
223
|
ci:check-repetition Check error repetition (--code <errorCode>, --reset, --json)
|
|
224
224
|
baseline Create retrofit baseline snapshot (--dry-run, --force, --paths <glob,glob,...>, --json)
|
|
225
225
|
scaffold-design Scaffold a design doc (--unit <id>, --phase <logical|domain|uiux|unit-test|it-test>, --dry-run|--apply, --force, --json)
|
|
@@ -540,6 +540,7 @@ Intents:
|
|
|
540
540
|
|
|
541
541
|
Options:
|
|
542
542
|
--dry-run
|
|
543
|
+
--apply
|
|
543
544
|
--json
|
|
544
545
|
--help, -h Show this help`,
|
|
545
546
|
reconcile: `Usage: phasegate reconcile [options]
|