phasegate 0.160.5 → 0.160.6
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 +6 -0
- package/docs/templates/ci/agent-context-refresh.yml +12 -8
- package/docs/templates/ci/consistency-check.yml +11 -7
- package/package.json +1 -1
- package/scripts/delegate-sonnet.sh +21 -7
- package/scripts/harness/ci-governance/application/usecases/refresh-claude-md-usecase.ts +6 -6
- package/scripts/harness/ci-governance/domain/services/claude-md-composer.ts +1 -1
- package/scripts/harness/ci-governance/infrastructure/adapters/yaml-template-renderer-adapter.ts +1 -0
- package/scripts/harness/config-foundation/domain/harness-config.ts +1 -1
- package/scripts/harness/config-foundation/domain/value-objects/planning-mode-config.ts +2 -2
- package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json +4 -2
- package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json +4 -2
- package/scripts/harness/installation/application/checks/wi-workflow-drift-check.ts +2 -0
- package/scripts/harness/main.ts +41 -6
- package/scripts/harness/phase-dependency-model/application/services/phase-info-resolver.ts +1 -1
- package/scripts/harness/phase-dependency-model/domain/models/phase-structure.ts +1 -1
- package/scripts/harness/phase-dependency-model/domain/values/planning-mode.ts +2 -2
- package/scripts/harness/skill-quality/application/usecases/apply-cascade-update-usecase.ts +2 -1
- package/scripts/harness/skill-quality/presentation/handlers/apply-cascade-update-handler.ts +10 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.160.6] - 2026-05-14
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **WI-190..WI-196 — post-0.160.5 dogfood regressions** — aligns agent context refresh with reconcile rendering, adds retrofit planning-mode config plans, makes cascade update dry-runs non-mutating and explicit, fixes doctor `_shared` drift counts, removes pnpm-only scheduled CI templates, exposes `migrate work-items` help, and accepts positional `delegate-sonnet` prompts.
|
|
15
|
+
|
|
10
16
|
## [0.160.5] - 2026-05-14
|
|
11
17
|
|
|
12
18
|
### Fixed
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# Phasegate — Agent context refresh workflow
|
|
2
|
+
# @work-item-id WI-194
|
|
2
3
|
#
|
|
3
4
|
# 使い方:
|
|
4
5
|
# このファイルを .github/workflows/agent-context-refresh.yml にコピーして使用する。
|
|
@@ -32,18 +33,21 @@ jobs:
|
|
|
32
33
|
uses: actions/setup-node@v4
|
|
33
34
|
with:
|
|
34
35
|
node-version: '20'
|
|
35
|
-
cache: 'pnpm'
|
|
36
|
-
|
|
37
|
-
- name: Install pnpm
|
|
38
|
-
uses: pnpm/action-setup@v4
|
|
39
|
-
with:
|
|
40
|
-
version: 9
|
|
41
36
|
|
|
42
37
|
- name: Install dependencies
|
|
43
|
-
run:
|
|
38
|
+
run: |
|
|
39
|
+
if [ -f pnpm-lock.yaml ]; then
|
|
40
|
+
pnpm install --frozen-lockfile
|
|
41
|
+
elif [ -f yarn.lock ]; then
|
|
42
|
+
yarn install --immutable || yarn install --frozen-lockfile
|
|
43
|
+
elif [ -f package-lock.json ] || [ -f npm-shrinkwrap.json ]; then
|
|
44
|
+
npm ci
|
|
45
|
+
else
|
|
46
|
+
npm install
|
|
47
|
+
fi
|
|
44
48
|
|
|
45
49
|
- name: Refresh agent context
|
|
46
|
-
run:
|
|
50
|
+
run: npx phasegate ci:auto-refresh-agent-context --apply
|
|
47
51
|
|
|
48
52
|
- name: Create pull request
|
|
49
53
|
uses: peter-evans/create-pull-request@v6
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# Phasegate — 週次整合性チェックワークフロー
|
|
2
|
+
# @work-item-id WI-194
|
|
2
3
|
#
|
|
3
4
|
# 使い方:
|
|
4
5
|
# このファイルを .github/workflows/consistency-check.yml にコピーして使用する。
|
|
@@ -31,15 +32,18 @@ jobs:
|
|
|
31
32
|
uses: actions/setup-node@v4
|
|
32
33
|
with:
|
|
33
34
|
node-version: '20'
|
|
34
|
-
cache: 'pnpm'
|
|
35
|
-
|
|
36
|
-
- name: Install pnpm
|
|
37
|
-
uses: pnpm/action-setup@v4
|
|
38
|
-
with:
|
|
39
|
-
version: 9
|
|
40
35
|
|
|
41
36
|
- name: Install dependencies
|
|
42
|
-
run:
|
|
37
|
+
run: |
|
|
38
|
+
if [ -f pnpm-lock.yaml ]; then
|
|
39
|
+
pnpm install --frozen-lockfile
|
|
40
|
+
elif [ -f yarn.lock ]; then
|
|
41
|
+
yarn install --immutable || yarn install --frozen-lockfile
|
|
42
|
+
elif [ -f package-lock.json ] || [ -f npm-shrinkwrap.json ]; then
|
|
43
|
+
npm ci
|
|
44
|
+
else
|
|
45
|
+
npm install
|
|
46
|
+
fi
|
|
43
47
|
|
|
44
48
|
# L4-001: Drift Detection(設計⇔コード双方向乖離)
|
|
45
49
|
- name: L4 Drift Detection
|
package/package.json
CHANGED
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
# Usage:
|
|
5
5
|
# bash scripts/delegate-sonnet.sh --prompt "プロンプト" --output "出力パス"
|
|
6
6
|
# bash scripts/delegate-sonnet.sh --prompt-file /tmp/prompt.md --output "出力パス"
|
|
7
|
+
# bash scripts/delegate-sonnet.sh "プロンプト" --output "出力パス"
|
|
7
8
|
#
|
|
8
9
|
# Options:
|
|
9
10
|
# --prompt 委任プロンプト(直接指定、2000文字以下推奨)
|
|
10
11
|
# --prompt-file 委任プロンプトファイル(長文の場合)
|
|
11
|
-
# --output
|
|
12
|
+
# --output 出力ファイルパス(省略時: .phasegate/delegate-sonnet-output.md)
|
|
12
13
|
# --max-turns 最大ターン数(デフォルト: 30)
|
|
13
14
|
# --dry-run プロンプトを表示するだけで実行しない
|
|
14
15
|
|
|
@@ -20,6 +21,7 @@ PROMPT_FILE=""
|
|
|
20
21
|
OUTPUT_PATH=""
|
|
21
22
|
MAX_TURNS=30
|
|
22
23
|
DRY_RUN=false
|
|
24
|
+
POSITIONAL_ARGS=()
|
|
23
25
|
|
|
24
26
|
while [[ $# -gt 0 ]]; do
|
|
25
27
|
case $1 in
|
|
@@ -43,23 +45,35 @@ while [[ $# -gt 0 ]]; do
|
|
|
43
45
|
DRY_RUN=true
|
|
44
46
|
shift
|
|
45
47
|
;;
|
|
48
|
+
--)
|
|
49
|
+
shift
|
|
50
|
+
if [[ $# -gt 0 ]]; then
|
|
51
|
+
POSITIONAL_ARGS+=("$@")
|
|
52
|
+
fi
|
|
53
|
+
break
|
|
54
|
+
;;
|
|
46
55
|
*)
|
|
47
|
-
|
|
48
|
-
|
|
56
|
+
if [[ "$1" == --* ]]; then
|
|
57
|
+
echo "Unknown option: $1" >&2
|
|
58
|
+
exit 1
|
|
59
|
+
fi
|
|
60
|
+
POSITIONAL_ARGS+=("$1")
|
|
61
|
+
shift
|
|
49
62
|
;;
|
|
50
63
|
esac
|
|
51
64
|
done
|
|
52
65
|
|
|
66
|
+
if [[ -z "$PROMPT" && ${#POSITIONAL_ARGS[@]} -gt 0 ]]; then
|
|
67
|
+
PROMPT="${POSITIONAL_ARGS[*]}"
|
|
68
|
+
fi
|
|
69
|
+
|
|
53
70
|
# --- バリデーション ---
|
|
54
71
|
if [[ -z "$PROMPT" && -z "$PROMPT_FILE" ]]; then
|
|
55
72
|
echo "Error: --prompt or --prompt-file is required" >&2
|
|
56
73
|
exit 1
|
|
57
74
|
fi
|
|
58
75
|
|
|
59
|
-
|
|
60
|
-
echo "Error: --output is required" >&2
|
|
61
|
-
exit 1
|
|
62
|
-
fi
|
|
76
|
+
OUTPUT_PATH="${OUTPUT_PATH:-.phasegate/delegate-sonnet-output.md}"
|
|
63
77
|
|
|
64
78
|
if [[ -n "$PROMPT_FILE" && ! -f "$PROMPT_FILE" ]]; then
|
|
65
79
|
echo "Error: Prompt file not found: $PROMPT_FILE" >&2
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @layer application
|
|
3
3
|
* @unit ci-governance
|
|
4
|
+
* @work-item-id WI-190
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
7
|
import type { AgentContextDocumentPort } from '../../domain/ports/agent-context-document-port.js';
|
|
@@ -12,12 +13,11 @@ const CLAUDE_MD_PATH = 'CLAUDE.md';
|
|
|
12
13
|
const CLAUDE_MD_TEMPLATE_PATH = 'docs/templates/agent-context/CLAUDE.md.template.md';
|
|
13
14
|
|
|
14
15
|
const PHASEGATE_COMMANDS = [
|
|
15
|
-
'phasegate
|
|
16
|
-
'phasegate ci:auto-refresh-agent-context --dry-run',
|
|
17
|
-
'phasegate ci:auto-refresh-agent-context --apply',
|
|
18
|
-
'phasegate refresh-claude-md --apply',
|
|
19
|
-
'phasegate p2:check-agent-context',
|
|
16
|
+
'phasegate doctor',
|
|
20
17
|
'phasegate phasegate:check-ready',
|
|
18
|
+
'phasegate validate --layer L2 --format human',
|
|
19
|
+
'phasegate setup:agent --dry-run',
|
|
20
|
+
'phasegate config:plan --intent l4-strict --dry-run',
|
|
21
21
|
];
|
|
22
22
|
|
|
23
23
|
const PHASE_PRESETS = ['minimal', 'standard', 'full', 'custom'];
|
|
@@ -37,7 +37,7 @@ export class RefreshClaudeMdUseCase {
|
|
|
37
37
|
]);
|
|
38
38
|
const nextContent = this.composer.compose(template, existing, {
|
|
39
39
|
commands: PHASEGATE_COMMANDS,
|
|
40
|
-
skills,
|
|
40
|
+
skills: ['all bundled skills'],
|
|
41
41
|
presets: PHASE_PRESETS,
|
|
42
42
|
});
|
|
43
43
|
const changed = existing !== nextContent;
|
|
@@ -11,7 +11,7 @@ export interface ClaudeMdTemplateValues {
|
|
|
11
11
|
|
|
12
12
|
const USER_SECTION_START = '<!-- phasegate:user-section:start -->';
|
|
13
13
|
const USER_SECTION_END = '<!-- phasegate:user-section:end -->';
|
|
14
|
-
const DEFAULT_USER_SECTION = '
|
|
14
|
+
const DEFAULT_USER_SECTION = 'Project-specific agent instructions go here.';
|
|
15
15
|
|
|
16
16
|
export class ClaudeMdComposer {
|
|
17
17
|
compose(template: string, existing: string | null, values: ClaudeMdTemplateValues): string {
|
|
@@ -29,7 +29,7 @@ import type {
|
|
|
29
29
|
|
|
30
30
|
export type LayerId = 'L1' | 'L2' | 'L3' | 'L4';
|
|
31
31
|
export type PresetId = 'minimal' | 'standard' | 'strict';
|
|
32
|
-
export type PlanningModeValue = 'interactive' | 'embedded-qa';
|
|
32
|
+
export type PlanningModeValue = 'interactive' | 'embedded-qa' | 'manual';
|
|
33
33
|
export type { PhaseDependenciesPresetId };
|
|
34
34
|
type DeepPartial<T> = {
|
|
35
35
|
[K in keyof T]?: T[K] extends Array<infer TItem>
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
* @unit config-foundation
|
|
4
4
|
*
|
|
5
5
|
* Planning Mode設定を表す値オブジェクト
|
|
6
|
-
* defaultMode と perPhase の値は列挙値 "interactive" | "embedded-qa" のみ許容
|
|
6
|
+
* defaultMode と perPhase の値は列挙値 "interactive" | "embedded-qa" | "manual" のみ許容
|
|
7
7
|
*/
|
|
8
8
|
import { ConfigValidationError } from '../errors/config-validation-error.js';
|
|
9
9
|
|
|
10
|
-
const VALID_MODES = ['interactive', 'embedded-qa'] as const;
|
|
10
|
+
const VALID_MODES = ['interactive', 'embedded-qa', 'manual'] as const;
|
|
11
11
|
type PlanningMode = (typeof VALID_MODES)[number];
|
|
12
12
|
|
|
13
13
|
export interface PlanningModeConfigProps {
|
package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json
CHANGED
|
@@ -384,7 +384,8 @@
|
|
|
384
384
|
"type": "string",
|
|
385
385
|
"enum": [
|
|
386
386
|
"interactive",
|
|
387
|
-
"embedded-qa"
|
|
387
|
+
"embedded-qa",
|
|
388
|
+
"manual"
|
|
388
389
|
]
|
|
389
390
|
},
|
|
390
391
|
"perPhase": {
|
|
@@ -393,7 +394,8 @@
|
|
|
393
394
|
"type": "string",
|
|
394
395
|
"enum": [
|
|
395
396
|
"interactive",
|
|
396
|
-
"embedded-qa"
|
|
397
|
+
"embedded-qa",
|
|
398
|
+
"manual"
|
|
397
399
|
]
|
|
398
400
|
}
|
|
399
401
|
}
|
package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json
CHANGED
|
@@ -394,7 +394,8 @@
|
|
|
394
394
|
"type": "string",
|
|
395
395
|
"enum": [
|
|
396
396
|
"interactive",
|
|
397
|
-
"embedded-qa"
|
|
397
|
+
"embedded-qa",
|
|
398
|
+
"manual"
|
|
398
399
|
]
|
|
399
400
|
},
|
|
400
401
|
"perPhase": {
|
|
@@ -403,7 +404,8 @@
|
|
|
403
404
|
"type": "string",
|
|
404
405
|
"enum": [
|
|
405
406
|
"interactive",
|
|
406
|
-
"embedded-qa"
|
|
407
|
+
"embedded-qa",
|
|
408
|
+
"manual"
|
|
407
409
|
]
|
|
408
410
|
}
|
|
409
411
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// @layer application
|
|
3
3
|
// @work-item-id WI-143
|
|
4
4
|
// @work-item-id WI-187
|
|
5
|
+
// @work-item-id WI-193
|
|
5
6
|
|
|
6
7
|
import { join, relative, sep } from "node:path";
|
|
7
8
|
import { DiagnosticFinding } from "../../domain/diagnostic-finding.js";
|
|
@@ -61,5 +62,6 @@ function isWorkItemDescription(path: string): boolean {
|
|
|
61
62
|
function isAdHocPlan(path: string): boolean {
|
|
62
63
|
if (!path.startsWith("docs/inception/")) return false;
|
|
63
64
|
if (/\/WI-\d{3}\//.test(path)) return false;
|
|
65
|
+
if (path.startsWith("docs/inception/_shared/") && path.endsWith(".md")) return true;
|
|
64
66
|
return path.includes("/codding_plan/") || path.endsWith("_plan.md");
|
|
65
67
|
}
|
package/scripts/harness/main.ts
CHANGED
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
* @work-item-id WI-176
|
|
9
9
|
* @work-item-id WI-184
|
|
10
10
|
* @work-item-id WI-189
|
|
11
|
+
* @work-item-id WI-191
|
|
12
|
+
* @work-item-id WI-195
|
|
13
|
+
* @work-item-id WI-196
|
|
11
14
|
*
|
|
12
15
|
* Phasegate CLI エントリポイント。
|
|
13
16
|
* 各Unitの Composition Root からハンドラーを取得し、コマンドに応じてディスパッチする。
|
|
@@ -171,6 +174,7 @@ Commands:
|
|
|
171
174
|
disable-feature <name> Disable a harness feature
|
|
172
175
|
list-features List available features
|
|
173
176
|
migrate Migrate phasegate.config.json (--schema v3, --config <path>)
|
|
177
|
+
migrate work-items Migrate legacy inception work item directories (--dry-run|--apply)
|
|
174
178
|
work-items:status Report or apply derived WI frontmatter status (--dry-run|--apply, --id, --fail-on-stale, --json)
|
|
175
179
|
|
|
176
180
|
render-errors Render harness errors (--format human|agent|ci)
|
|
@@ -211,7 +215,7 @@ Gate semantics:
|
|
|
211
215
|
refresh-claude-md Refresh CLAUDE.md standard sections (--dry-run, --apply, --json)
|
|
212
216
|
p2:check-agent-context Check AGENTS.md / CLAUDE.md freshness (--threshold-days <n>, --json)
|
|
213
217
|
setup:agent Plan agent-driven setup (--intent <minimal|recommended|strict|ci-only|agent-hooks|retrofit>, --agent <claude|codex|both>, --dry-run|--apply, --json)
|
|
214
|
-
config:plan Plan safe config changes (--intent <l4-strict|codex-hooks|ci-fail-on-warning|baseline-reset|quick-mode-strict>, --dry-run, --json)
|
|
218
|
+
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)
|
|
215
219
|
ci:check-repetition Check error repetition (--code <errorCode>, --reset, --json)
|
|
216
220
|
baseline Create retrofit baseline snapshot (--dry-run, --force, --paths <glob,glob,...>, --json)
|
|
217
221
|
scaffold-design Scaffold a design doc (--unit <id>, --phase <logical|domain|uiux|unit-test|it-test>, --dry-run|--apply, --force, --json)
|
|
@@ -528,7 +532,7 @@ Options:
|
|
|
528
532
|
Produce an agent-readable configuration change plan.
|
|
529
533
|
|
|
530
534
|
Intents:
|
|
531
|
-
l4-strict, codex-hooks, ci-fail-on-warning, baseline-reset, quick-mode-strict
|
|
535
|
+
l4-strict, codex-hooks, ci-fail-on-warning, baseline-reset, quick-mode-strict, retrofit-bootstrap, planning-mode-relax
|
|
532
536
|
|
|
533
537
|
Options:
|
|
534
538
|
--dry-run
|
|
@@ -562,10 +566,11 @@ Options:
|
|
|
562
566
|
--help, -h Show this help`,
|
|
563
567
|
migrate: `Usage: phasegate migrate [options]
|
|
564
568
|
|
|
565
|
-
Migrate phasegate.config.json from older schema versions
|
|
569
|
+
Migrate phasegate.config.json from older schema versions, or migrate legacy inception work item directories.
|
|
566
570
|
|
|
567
571
|
Options:
|
|
568
572
|
--dry-run Preview changes without writing
|
|
573
|
+
--apply Apply migration when supported
|
|
569
574
|
--help, -h Show this help`,
|
|
570
575
|
"list-errors": `Usage: phasegate list-errors [options]
|
|
571
576
|
|
|
@@ -769,7 +774,7 @@ function parseCoverageThreshold(raw: string | undefined): number {
|
|
|
769
774
|
type InitPhasePreset = "full" | "standard" | "minimal" | "custom";
|
|
770
775
|
type AgentTarget = "claude" | "codex" | "both";
|
|
771
776
|
type SetupIntent = "minimal" | "recommended" | "strict" | "ci-only" | "agent-hooks" | "retrofit";
|
|
772
|
-
type ConfigChangeIntent = "l4-strict" | "codex-hooks" | "ci-fail-on-warning" | "baseline-reset" | "quick-mode-strict";
|
|
777
|
+
type ConfigChangeIntent = "l4-strict" | "codex-hooks" | "ci-fail-on-warning" | "baseline-reset" | "quick-mode-strict" | "retrofit-bootstrap" | "planning-mode-relax";
|
|
773
778
|
type SetupCompletenessStatus = "configured" | "planned" | "manual" | "not-applicable" | "unknown";
|
|
774
779
|
|
|
775
780
|
interface SetupCompletenessEntry {
|
|
@@ -847,7 +852,9 @@ function parseConfigChangeIntent(value: string | undefined): ConfigChangeIntent
|
|
|
847
852
|
value === "codex-hooks" ||
|
|
848
853
|
value === "ci-fail-on-warning" ||
|
|
849
854
|
value === "baseline-reset" ||
|
|
850
|
-
value === "quick-mode-strict"
|
|
855
|
+
value === "quick-mode-strict" ||
|
|
856
|
+
value === "retrofit-bootstrap" ||
|
|
857
|
+
value === "planning-mode-relax"
|
|
851
858
|
) {
|
|
852
859
|
return value;
|
|
853
860
|
}
|
|
@@ -1216,6 +1223,14 @@ function buildConfigPatchPreview(intent: ConfigChangeIntent, before: unknown | n
|
|
|
1216
1223
|
],
|
|
1217
1224
|
"codex-hooks": [],
|
|
1218
1225
|
"baseline-reset": [],
|
|
1226
|
+
"retrofit-bootstrap": [
|
|
1227
|
+
{ pointer: "/planningMode/default", path: ["planningMode", "default"], value: "manual" },
|
|
1228
|
+
{ pointer: "/phaseDependencies/override", path: ["phaseDependencies", "override"], value: true },
|
|
1229
|
+
{ pointer: "/quickMode/relaxedGates", path: ["quickMode", "relaxedGates"], value: ["phase-gate"] },
|
|
1230
|
+
],
|
|
1231
|
+
"planning-mode-relax": [
|
|
1232
|
+
{ pointer: "/planningMode/default", path: ["planningMode", "default"], value: "manual" },
|
|
1233
|
+
],
|
|
1219
1234
|
};
|
|
1220
1235
|
const changes = configIntents[intent];
|
|
1221
1236
|
if (changes.length === 0) {
|
|
@@ -1303,6 +1318,22 @@ async function buildConfigChangePlan(rootDir: string, intent: ConfigChangeIntent
|
|
|
1303
1318
|
validations: ["phasegate ci-check --quick --dry-run", "phasegate phasegate:check-ready"],
|
|
1304
1319
|
risks: ["More changes will require Full Mode validation before commit."],
|
|
1305
1320
|
},
|
|
1321
|
+
"retrofit-bootstrap": {
|
|
1322
|
+
targets: ["phasegate.config.json: planningMode.default", "phasegate.config.json: phaseDependencies.override", "phasegate.config.json: quickMode.relaxedGates"],
|
|
1323
|
+
managedTargets: ["phasegate.config.json"],
|
|
1324
|
+
externalActions: [],
|
|
1325
|
+
commands: ["phasegate baseline --dry-run", "phasegate config:plan --intent retrofit-bootstrap --json"],
|
|
1326
|
+
validations: ["phasegate validate-metadata docs/inception/_shared/*.md", "phasegate check-phase-gate --level 2"],
|
|
1327
|
+
risks: ["Manual planning mode accepts existing retrofit planning evidence; review the patch before applying it to avoid weakening greenfield projects."],
|
|
1328
|
+
},
|
|
1329
|
+
"planning-mode-relax": {
|
|
1330
|
+
targets: ["phasegate.config.json: planningMode.default"],
|
|
1331
|
+
managedTargets: ["phasegate.config.json"],
|
|
1332
|
+
externalActions: [],
|
|
1333
|
+
commands: ["phasegate config:plan --intent planning-mode-relax --json"],
|
|
1334
|
+
validations: ["phasegate check-phase-gate --level 2", "phasegate phasegate:check-ready"],
|
|
1335
|
+
risks: ["Manual planning mode reduces PhaseGate's QA enforcement for plan documents until strict planning is restored."],
|
|
1336
|
+
},
|
|
1306
1337
|
};
|
|
1307
1338
|
const before = await readProjectJson(rootDir, "phasegate.config.json");
|
|
1308
1339
|
return {
|
|
@@ -2587,7 +2618,7 @@ Examples:
|
|
|
2587
2618
|
const mod = createSkillQualityHandlers();
|
|
2588
2619
|
const storyId = parseFlag(args, "--story") ?? "";
|
|
2589
2620
|
const dryRun = hasFlag(args, "--dry-run");
|
|
2590
|
-
const result = await mod.applyCascadeUpdateHandler.handle({ storyId, dryRun });
|
|
2621
|
+
const result = await mod.applyCascadeUpdateHandler.handle({ storyId, dryRun, format: json ? "json" : "human" });
|
|
2591
2622
|
console.log(result.message);
|
|
2592
2623
|
process.exit(result.exitCode);
|
|
2593
2624
|
break;
|
|
@@ -2780,6 +2811,10 @@ Examples:
|
|
|
2780
2811
|
}
|
|
2781
2812
|
|
|
2782
2813
|
case "delegate-sonnet": {
|
|
2814
|
+
if (hasFlag(args, "--help") || hasFlag(args, "-h")) {
|
|
2815
|
+
printSubcommandHelp("delegate-sonnet");
|
|
2816
|
+
process.exit(0);
|
|
2817
|
+
}
|
|
2783
2818
|
const { spawn } = await import("node:child_process");
|
|
2784
2819
|
const scriptPath = join(harnessRoot, "scripts/delegate-sonnet.sh");
|
|
2785
2820
|
const forwardArgs = args.slice(1);
|
|
@@ -125,7 +125,7 @@ export class PhaseInfoResolver {
|
|
|
125
125
|
blockers.push(`QAが未完了です: ${node.nodeKey()}`);
|
|
126
126
|
}
|
|
127
127
|
if (!actual.planningModeMatch) {
|
|
128
|
-
blockers.push(`Planning Mode
|
|
128
|
+
blockers.push(`Planning Mode evidence requirement is not satisfied: ${node.nodeKey()}`);
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
}
|
|
@@ -270,7 +270,7 @@ export class PhaseStructure {
|
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
if (!planEvidence.planningModeMatch) {
|
|
273
|
-
blockers.push(`Planning Mode
|
|
273
|
+
blockers.push(`Planning Mode evidence requirement is not satisfied: ${node.nodeKey()}`);
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
276
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @unit phase-dependency-model
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
export type PlanningModeValue = 'interactive' | 'embedded-qa';
|
|
6
|
+
export type PlanningModeValue = 'interactive' | 'embedded-qa' | 'manual';
|
|
7
7
|
|
|
8
8
|
export class InvalidPlanningModeError extends Error {
|
|
9
9
|
constructor(value: string) {
|
|
@@ -21,7 +21,7 @@ export class PlanningMode {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
static create(value: string): PlanningMode {
|
|
24
|
-
if (value !== 'interactive' && value !== 'embedded-qa') {
|
|
24
|
+
if (value !== 'interactive' && value !== 'embedded-qa' && value !== 'manual') {
|
|
25
25
|
throw new InvalidPlanningModeError(value);
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @layer application
|
|
3
3
|
* @unit skill-quality
|
|
4
|
+
* @work-item-id WI-192
|
|
4
5
|
*/
|
|
5
6
|
import { CascadeUpdateResult } from '../../domain/value-objects/cascade-update-result.js';
|
|
6
7
|
import type { CascadeUpdateService } from '../../domain/services/cascade-update-service.js';
|
|
@@ -35,7 +36,7 @@ export class ApplyCascadeUpdateUseCase {
|
|
|
35
36
|
const updatedContent = content.includes(target.storyIdTag)
|
|
36
37
|
? content
|
|
37
38
|
: `${content}\n${target.storyIdTag}`;
|
|
38
|
-
if (!input.dryRun) {
|
|
39
|
+
if (!input.dryRun && updatedContent !== content) {
|
|
39
40
|
await this.fileSystemPort.write(filePath, updatedContent);
|
|
40
41
|
}
|
|
41
42
|
updatedCount++;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @layer presentation
|
|
3
3
|
* @unit skill-quality
|
|
4
|
+
* @work-item-id WI-192
|
|
4
5
|
*/
|
|
5
6
|
import type { ApplyCascadeUpdateUseCase } from '../../application/usecases/apply-cascade-update-usecase.js';
|
|
6
7
|
|
|
7
8
|
export interface ApplyCascadeUpdateArgs {
|
|
8
9
|
storyId: string;
|
|
9
10
|
dryRun?: boolean;
|
|
11
|
+
format?: 'human' | 'json';
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
export class ApplyCascadeUpdateHandler {
|
|
@@ -15,8 +17,15 @@ export class ApplyCascadeUpdateHandler {
|
|
|
15
17
|
async handle(args: ApplyCascadeUpdateArgs): Promise<{ exitCode: number; message: string }> {
|
|
16
18
|
try {
|
|
17
19
|
const output = await this.useCase.execute({ storyId: args.storyId, dryRun: args.dryRun });
|
|
20
|
+
if (args.format === 'json') {
|
|
21
|
+
return {
|
|
22
|
+
exitCode: output.errors.length > 0 ? 1 : 0,
|
|
23
|
+
message: JSON.stringify({ dryRun: args.dryRun === true, ...output }, null, 2),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
18
26
|
const tagsLine = output.appliedStoryIds.join(', ');
|
|
19
|
-
|
|
27
|
+
const verb = args.dryRun ? 'Would update' : 'Updated';
|
|
28
|
+
let msg = `${verb} ${output.updatedCount} files with tags: ${tagsLine}`;
|
|
20
29
|
|
|
21
30
|
if (output.errors.length > 0) {
|
|
22
31
|
const errLines = output.errors.map((e) => ` - ${e}`).join('\n');
|