phasegate 0.340.0 → 0.341.0
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/folder_management_rules.md +10 -1
- package/docs/guide/cli-reference.md +23 -3
- package/docs/guide/configuration.md +28 -2
- package/docs/guide/hooks-integration.md +7 -1
- package/docs/guide/skills-overview.md +3 -0
- package/package.json +2 -1
- package/scripts/harness/agent-integration/application/usecases/handle-post-tool-use-usecase.ts +4 -0
- package/scripts/harness/agent-integration/application/usecases/handle-pre-tool-use-usecase.ts +36 -1
- package/scripts/harness/agent-integration/application/usecases/handle-stop-usecase.ts +3 -9
- package/scripts/harness/agent-integration/domain/ports/story-reflection-query-port.ts +2 -0
- package/scripts/harness/agent-integration/domain/services/hook-to-cli-translator.ts +8 -5
- package/scripts/harness/agent-integration/domain/value-objects/hook-translation-result.ts +1 -1
- package/scripts/harness/agent-integration/domain/value-objects/story-reflection-query-result.ts +10 -2
- package/scripts/harness/agent-integration/domain/value-objects/write-target-scope.ts +12 -0
- package/scripts/harness/agent-integration/infrastructure/adapters/child-process-cli-executor-adapter.ts +64 -13
- package/scripts/harness/agent-integration/infrastructure/adapters/file-system-story-reflection-query-adapter.ts +108 -2
- package/scripts/harness/agent-integration/infrastructure/adapters/harness-config-config-query-adapter.ts +8 -6
- package/scripts/harness/agent-integration/presentation/hook-skip-event-recorder.ts +3 -0
- package/scripts/harness/agent-integration/presentation/post-tool-use-feedback.ts +39 -0
- package/scripts/harness/agent-integration/presentation/post-tool-use-hook.ts +20 -27
- package/scripts/harness/agent-integration/presentation/pre-tool-use-hook.ts +3 -0
- package/scripts/harness/agent-integration/presentation/stop-hook.ts +1 -3
- package/scripts/harness/biome-ast-engine/infrastructure/adapters/biome-cli-executor-adapter.ts +21 -1
- package/scripts/harness/biome-ast-engine/infrastructure/adapters/typescript-source-module-analyzer-adapter.ts +5 -0
- package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json +15 -0
- package/scripts/harness/config-foundation/infrastructure/validators/ajv-config-schema-validator.ts +6 -3
- package/scripts/harness/harness-api/domain/ports/biome-lint-port.ts +2 -1
- package/scripts/harness/harness-api/domain/services/command-dispatch-service.ts +12 -1
- package/scripts/harness/harness-api/infrastructure/adapters/biome-ast-engine-lint-adapter.ts +10 -2
- package/scripts/harness/installation/application/bundled-skill-selection.ts +28 -2
- package/scripts/harness/installation/application/checks/check-utils.ts +2 -2
- package/scripts/harness/installation/application/usecases/run-install.ts +5 -5
- package/scripts/harness/installation/application/usecases/run-reconcile.ts +62 -21
- package/scripts/harness/installation/presentation/cli/install-handler.ts +2 -1
- package/scripts/harness/main.ts +128 -90
- package/scripts/harness/phase-dependency-model/domain/services/story-reflection-checker.ts +48 -5
- package/scripts/harness/phase-dependency-model/domain/services/work-item-reflection-scope-resolver.ts +64 -0
- package/scripts/harness/phase-dependency-model/domain/values/story-reflection-mapping.ts +8 -2
- package/scripts/harness/phase-dependency-model/infrastructure/filesystem/file-system-story-reflection-adapter.ts +6 -1
- package/scripts/harness/phase-dependency-model/infrastructure/filesystem/file-system-work-item-dependency-catalog.ts +73 -0
- package/scripts/harness/quick-mode/application/dto/change-category-classification-contract.ts +4 -0
- package/scripts/harness/quick-mode/application/ports/change-risk-advisory-port.ts +16 -0
- package/scripts/harness/quick-mode/composition-root.ts +5 -1
- package/scripts/harness/quick-mode/infrastructure/adapters/snapshot-risk-advisory-adapter.ts +118 -0
- package/scripts/harness/quick-mode/presentation/formatters/change-category-formatter.ts +7 -0
- package/scripts/harness/quick-mode/presentation/handlers/check-change-category-handler.ts +12 -1
- package/scripts/harness/setup/skill-deployer.ts +3 -45
- package/scripts/harness/skill-quality/application/dto/run-plan-checker-loop-output.ts +1 -0
- package/scripts/harness/skill-quality/application/usecases/apply-cascade-update-usecase.ts +9 -4
- package/scripts/harness/skill-quality/application/usecases/execute-tdd-cycle-usecase.ts +2 -1
- package/scripts/harness/skill-quality/application/usecases/run-plan-checker-loop-usecase.ts +8 -0
- package/scripts/harness/skill-quality/composition-root.ts +14 -7
- package/scripts/harness/skill-quality/domain/ports/plan-check-executor-port.ts +2 -0
- package/scripts/harness/skill-quality/domain/value-objects/cascade-update-target.ts +15 -1
- package/scripts/harness/skill-quality/infrastructure/adapters/l1-biome-validator-adapter.ts +9 -1
- package/scripts/harness/skill-quality/infrastructure/adapters/l2-validator-system-adapter.ts +18 -2
- package/scripts/harness/skill-quality/presentation/handlers/apply-cascade-update-handler.ts +8 -2
- package/scripts/harness/skill-quality/presentation/handlers/execute-tdd-cycle-handler.ts +4 -3
- package/scripts/harness/skill-quality/presentation/handlers/run-plan-checker-loop-handler.ts +11 -4
- package/scripts/harness/traceability-model/infrastructure/parsers/work-item-frontmatter-parser.ts +41 -0
- package/skills/README.md +7 -0
- package/skills/cascade-updater/SKILL.md +37 -109
- package/skills/cascade-updater/references//345/261/244/345/210/245/345/210/244/345/256/232/343/202/254/343/202/244/343/203/211.md +5 -3
- package/skills/release-publisher/SKILL.md +3 -1
- package/skills/skill-creator/SKILL.md +8 -9
|
@@ -13,7 +13,8 @@ export class ExecuteTddCycleUseCase {
|
|
|
13
13
|
|
|
14
14
|
async execute(input: ExecuteTddCycleInput): Promise<ExecuteTddCycleOutput> {
|
|
15
15
|
const tddCycle = TddCycle.create(input.phase, input.passed);
|
|
16
|
-
const
|
|
16
|
+
const workItemId = /^WI-\d+$/.test(input.storyId) ? input.storyId : undefined;
|
|
17
|
+
const commitMessage = CommitMessage.create(input.unit, input.storyId, input.description, workItemId);
|
|
17
18
|
|
|
18
19
|
const readiness = await this.atomicCommitService.execute(tddCycle, commitMessage);
|
|
19
20
|
|
|
@@ -26,6 +26,14 @@ export class RunPlanCheckerLoopUseCase {
|
|
|
26
26
|
revision: result.revision,
|
|
27
27
|
});
|
|
28
28
|
loop.addAttempt(attempt);
|
|
29
|
+
if (loop.status === 'RUNNING' && this.planCheckExecutorPort.supportsRetry === false) {
|
|
30
|
+
return {
|
|
31
|
+
status: 'FAILED_EXCEEDED',
|
|
32
|
+
loopHistory: loop.loopHistory,
|
|
33
|
+
escalationRequired: true,
|
|
34
|
+
stopReason: 'UNCHANGED_INPUT',
|
|
35
|
+
};
|
|
36
|
+
}
|
|
29
37
|
attemptNumber++;
|
|
30
38
|
}
|
|
31
39
|
|
|
@@ -14,7 +14,7 @@ import { SkillStructureValidator } from './domain/services/skill-structure-valid
|
|
|
14
14
|
|
|
15
15
|
// Infrastructure Adapters
|
|
16
16
|
import { GitCommitExecutorAdapter } from './infrastructure/adapters/git-commit-executor-adapter.js';
|
|
17
|
-
import { L1BiomeValidatorAdapter } from './infrastructure/adapters/l1-biome-validator-adapter.js';
|
|
17
|
+
import { L1BiomeValidatorAdapter, type L1BiomeValidatorOptions } from './infrastructure/adapters/l1-biome-validator-adapter.js';
|
|
18
18
|
import { L2ValidatorSystemAdapter } from './infrastructure/adapters/l2-validator-system-adapter.js';
|
|
19
19
|
import { FileSystemLessonSourceReaderAdapter } from './infrastructure/adapters/file-system-lesson-source-reader-adapter.js';
|
|
20
20
|
import { FileSystemLessonArtifactWriterAdapter } from './infrastructure/adapters/file-system-lesson-artifact-writer-adapter.js';
|
|
@@ -60,11 +60,18 @@ class NodeFileSystemAdapter implements FileSystemPort {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
export
|
|
63
|
+
export interface SkillQualityHandlerOptions {
|
|
64
|
+
rootDir?: string;
|
|
65
|
+
l1Config?: L1BiomeValidatorOptions['config'];
|
|
66
|
+
validatorSystemConfig?: object;
|
|
67
|
+
failOnWarning?: boolean;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function createSkillQualityHandlers(options: SkillQualityHandlerOptions = {}) {
|
|
64
71
|
// Infrastructure
|
|
65
72
|
const commitExecutorPort = new GitCommitExecutorAdapter();
|
|
66
|
-
const l1ValidatorPort = new L1BiomeValidatorAdapter();
|
|
67
|
-
const l2ValidatorPort = new L2ValidatorSystemAdapter();
|
|
73
|
+
const l1ValidatorPort = new L1BiomeValidatorAdapter({ rootDir: options.rootDir, config: options.l1Config });
|
|
74
|
+
const l2ValidatorPort = new L2ValidatorSystemAdapter({ config: options.validatorSystemConfig, failOnWarning: options.failOnWarning });
|
|
68
75
|
const lessonSourceReaderPort = new FileSystemLessonSourceReaderAdapter();
|
|
69
76
|
const lessonArtifactWriterPort = new FileSystemLessonArtifactWriterAdapter();
|
|
70
77
|
const lessonArtifactSchemaPort = new AjvLessonArtifactSchemaAdapter();
|
|
@@ -87,6 +94,7 @@ export function createSkillQualityHandlers() {
|
|
|
87
94
|
const checkCoverageUseCase = new CheckCoverageUseCase(requirementTestMatrixPort, coverageRunnerPort, configQueryPort);
|
|
88
95
|
const runPlanCheckerLoopUseCase = new RunPlanCheckerLoopUseCase(
|
|
89
96
|
{
|
|
97
|
+
supportsRetry: false,
|
|
90
98
|
evaluate: async (planDocument: string) => {
|
|
91
99
|
// チェックボックス形式(- [x] / - [ ])でカバレッジを評価する
|
|
92
100
|
const checked = (planDocument.match(/- \[x\]/gi) ?? []).length;
|
|
@@ -99,8 +107,7 @@ export function createSkillQualityHandlers() {
|
|
|
99
107
|
const gaps = planDocument
|
|
100
108
|
.split('\n')
|
|
101
109
|
.filter((line) => /- \[ \]/.test(line))
|
|
102
|
-
.map((line) => line.replace(/^.*- \[ \]\s*/, '').trim())
|
|
103
|
-
.filter(Boolean);
|
|
110
|
+
.map((line) => line.replace(/^.*- \[ \]\s*/, '').trim() || '未記入のチェック項目');
|
|
104
111
|
return { coverageRate, gaps, revision: `${checked}/${total}` };
|
|
105
112
|
},
|
|
106
113
|
}
|
|
@@ -114,7 +121,7 @@ export function createSkillQualityHandlers() {
|
|
|
114
121
|
return {
|
|
115
122
|
executeTddCycleHandler: new ExecuteTddCycleHandler(executeTddCycleUseCase),
|
|
116
123
|
checkCoverageHandler: new CheckCoverageHandler(checkCoverageUseCase),
|
|
117
|
-
runPlanCheckerLoopHandler: new RunPlanCheckerLoopHandler(runPlanCheckerLoopUseCase),
|
|
124
|
+
runPlanCheckerLoopHandler: new RunPlanCheckerLoopHandler(runPlanCheckerLoopUseCase, fileSystemPort),
|
|
118
125
|
collectLessonsHandler: new CollectLessonsHandler(collectLessonsUseCase, writeLessonArtifactUseCase),
|
|
119
126
|
applyCascadeUpdateHandler: new ApplyCascadeUpdateHandler(applyCascadeUpdateUseCase),
|
|
120
127
|
validateSkillStructureHandler: new ValidateSkillStructureHandler(validateSkillStructureUseCase),
|
|
@@ -11,5 +11,7 @@ export interface PlanCheckResult {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export interface PlanCheckExecutorPort {
|
|
14
|
+
/** False for deterministic evaluators; omitted preserves legacy retry behavior. */
|
|
15
|
+
readonly supportsRetry?: boolean;
|
|
14
16
|
evaluate(planDocument: string, previousAttempts: readonly LoopAttempt[]): Promise<PlanCheckResult>;
|
|
15
17
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @layer domain
|
|
3
3
|
* @unit skill-quality
|
|
4
|
+
* @work-item-id WI-220
|
|
4
5
|
*/
|
|
5
6
|
import { SkillQualityError } from '../errors/skill-quality-error.js';
|
|
6
7
|
|
|
@@ -18,11 +19,24 @@ export class CascadeUpdateTarget {
|
|
|
18
19
|
if (!filePath) {
|
|
19
20
|
throw new SkillQualityError('EMPTY_FILE_PATH', 'filePath must be non-empty');
|
|
20
21
|
}
|
|
21
|
-
const storyIdTag =
|
|
22
|
+
const storyIdTag = `@${/^WI-\d+$/.test(storyId) ? 'work-item-id' : 'story-id'} ${storyId}`;
|
|
22
23
|
return new CascadeUpdateTarget(filePath, storyIdTag);
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
equals(other: CascadeUpdateTarget): boolean {
|
|
26
27
|
return this.filePath === other.filePath && this.storyIdTag === other.storyIdTag;
|
|
27
28
|
}
|
|
29
|
+
|
|
30
|
+
renderAnnotation(filePath: string): string {
|
|
31
|
+
return /\.(?:[cm]?[jt]s|[jt]sx)$/i.test(filePath) ? `// ${this.storyIdTag}` : this.storyIdTag;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
hasAnnotationIn(content: string): boolean {
|
|
35
|
+
const storyId = this.storyIdTag.slice(this.storyIdTag.indexOf(' ') + 1);
|
|
36
|
+
for (const match of content.matchAll(/@(?:story-id|issue-id|work-item-id)[ \t]+([^\r\n]+)/g)) {
|
|
37
|
+
const ids = match[1].replace(/-->.*$/, '').split(/[\s,]+/);
|
|
38
|
+
if (ids.includes(storyId)) return true;
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
28
42
|
}
|
|
@@ -5,12 +5,20 @@
|
|
|
5
5
|
import type { L1ValidatorPort } from '../../domain/ports/l1-validator-port.js';
|
|
6
6
|
import type { CommitMessage } from '../../domain/value-objects/commit-message.js';
|
|
7
7
|
import type { ValidationViolation } from '../../domain/types/validation-violation.js';
|
|
8
|
+
import type { BiomeAstEngineModuleOptions } from '../../../biome-ast-engine/composition-root.js';
|
|
9
|
+
|
|
10
|
+
export interface L1BiomeValidatorOptions {
|
|
11
|
+
rootDir?: string;
|
|
12
|
+
config?: BiomeAstEngineModuleOptions;
|
|
13
|
+
}
|
|
8
14
|
|
|
9
15
|
export class L1BiomeValidatorAdapter implements L1ValidatorPort {
|
|
16
|
+
constructor(private readonly options: L1BiomeValidatorOptions = {}) {}
|
|
17
|
+
|
|
10
18
|
async validate(_commitMessage: CommitMessage): Promise<readonly ValidationViolation[]> {
|
|
11
19
|
try {
|
|
12
20
|
const { createBiomeAstEngineModule } = await import('../../../biome-ast-engine/composition-root.js');
|
|
13
|
-
const mod = createBiomeAstEngineModule(process.cwd());
|
|
21
|
+
const mod = createBiomeAstEngineModule(this.options.rootDir ?? process.cwd(), this.options.config);
|
|
14
22
|
const output = await mod.executeLintUseCase.execute({ targets: [] });
|
|
15
23
|
|
|
16
24
|
return output.report.violations.map((violation) => ({
|
package/scripts/harness/skill-quality/infrastructure/adapters/l2-validator-system-adapter.ts
CHANGED
|
@@ -5,20 +5,36 @@
|
|
|
5
5
|
import type { L2ValidatorPort } from '../../domain/ports/l2-validator-port.js';
|
|
6
6
|
import type { CommitMessage } from '../../domain/value-objects/commit-message.js';
|
|
7
7
|
import type { ValidationViolation } from '../../domain/types/validation-violation.js';
|
|
8
|
+
import { isEffectivelyPassed } from '../../../validator-system/domain/services/effective-severity-policy.js';
|
|
9
|
+
|
|
10
|
+
export interface L2ValidatorSystemOptions {
|
|
11
|
+
config?: object;
|
|
12
|
+
failOnWarning?: boolean;
|
|
13
|
+
}
|
|
8
14
|
|
|
9
15
|
export class L2ValidatorSystemAdapter implements L2ValidatorPort {
|
|
16
|
+
constructor(private readonly options: L2ValidatorSystemOptions = {}) {}
|
|
17
|
+
|
|
10
18
|
async validate(_commitMessage: CommitMessage): Promise<readonly ValidationViolation[]> {
|
|
11
19
|
try {
|
|
12
20
|
const { createValidatorSystemModule } = await import('../../../validator-system/composition-root.js');
|
|
13
|
-
const mod = createValidatorSystemModule();
|
|
21
|
+
const mod = createValidatorSystemModule(this.options.config);
|
|
22
|
+
// Direct legacy callers keep warning-as-blocking unless explicitly configured.
|
|
23
|
+
const failOnWarning = this.options.failOnWarning ?? true;
|
|
14
24
|
const report = await mod.runFullValidationUseCase.execute({
|
|
15
25
|
targetPaths: [],
|
|
16
26
|
unitName: '',
|
|
17
27
|
currentPhase: '',
|
|
18
28
|
includeL4: false,
|
|
29
|
+
failOnWarning,
|
|
19
30
|
});
|
|
20
31
|
|
|
21
|
-
|
|
32
|
+
const blockingErrors = report.allErrors.filter((error) => {
|
|
33
|
+
const advisory = isEffectivelyPassed({ passed: false, errors: [error] }, failOnWarning);
|
|
34
|
+
if (advisory) console.warn(`[skill-quality] [${error.code}] ${error.message}`);
|
|
35
|
+
return !advisory;
|
|
36
|
+
});
|
|
37
|
+
return blockingErrors.map((error) => ({
|
|
22
38
|
ruleId: error.code.toString(),
|
|
23
39
|
message: error.message,
|
|
24
40
|
location: '',
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* @layer presentation
|
|
3
3
|
* @unit skill-quality
|
|
4
4
|
* @work-item-id WI-192
|
|
5
|
+
* @work-item-id WI-220
|
|
5
6
|
*/
|
|
6
7
|
import type { ApplyCascadeUpdateUseCase } from '../../application/usecases/apply-cascade-update-usecase.js';
|
|
7
8
|
|
|
@@ -20,12 +21,17 @@ export class ApplyCascadeUpdateHandler {
|
|
|
20
21
|
if (args.format === 'json') {
|
|
21
22
|
return {
|
|
22
23
|
exitCode: output.errors.length > 0 ? 1 : 0,
|
|
23
|
-
message: JSON.stringify({
|
|
24
|
+
message: JSON.stringify({
|
|
25
|
+
dryRun: args.dryRun === true,
|
|
26
|
+
...output,
|
|
27
|
+
operation: 'traceability-tag-update',
|
|
28
|
+
semanticReviewPerformed: false,
|
|
29
|
+
}, null, 2),
|
|
24
30
|
};
|
|
25
31
|
}
|
|
26
32
|
const tagsLine = output.appliedStoryIds.join(', ');
|
|
27
33
|
const verb = args.dryRun ? 'Would update' : 'Updated';
|
|
28
|
-
let msg = `${verb} ${output.updatedCount} files with tags: ${tagsLine}
|
|
34
|
+
let msg = `${verb} ${output.updatedCount} files with tags: ${tagsLine}\nタグ追記のみです。意味レビューは未実施であり、設計内容の反映・承認を保証しません。`;
|
|
29
35
|
|
|
30
36
|
if (output.errors.length > 0) {
|
|
31
37
|
const errLines = output.errors.map((e) => ` - ${e}`).join('\n');
|
|
@@ -16,6 +16,7 @@ export class ExecuteTddCycleHandler {
|
|
|
16
16
|
constructor(private readonly useCase: ExecuteTddCycleUseCase) {}
|
|
17
17
|
|
|
18
18
|
async handle(args: ExecuteTddCycleArgs): Promise<{ exitCode: number; message: string }> {
|
|
19
|
+
const evidenceNotice = '\n注意: --passed は呼出元の申告です。このコマンドはテストを実行しません。';
|
|
19
20
|
try {
|
|
20
21
|
const output = await this.useCase.execute({
|
|
21
22
|
unit: args.unit,
|
|
@@ -26,12 +27,12 @@ export class ExecuteTddCycleHandler {
|
|
|
26
27
|
});
|
|
27
28
|
|
|
28
29
|
if (output.ready) {
|
|
29
|
-
return { exitCode: 0, message: `Commit successful: ${output.committedMessage}` };
|
|
30
|
+
return { exitCode: 0, message: `Commit successful: ${output.committedMessage}${evidenceNotice}` };
|
|
30
31
|
}
|
|
31
32
|
const violationMessages = output.violations.map((v) => ` - [${v.ruleId}] ${v.message}`).join('\n');
|
|
32
|
-
return { exitCode: 1, message: `Validation failed:\n${violationMessages}` };
|
|
33
|
+
return { exitCode: 1, message: `Validation failed:\n${violationMessages}${evidenceNotice}` };
|
|
33
34
|
} catch (err) {
|
|
34
|
-
return { exitCode: 2, message: `Error: ${err instanceof Error ? err.message : String(err)}` };
|
|
35
|
+
return { exitCode: 2, message: `Error: ${err instanceof Error ? err.message : String(err)}${evidenceNotice}` };
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
38
|
}
|
package/scripts/harness/skill-quality/presentation/handlers/run-plan-checker-loop-handler.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* @unit skill-quality
|
|
4
4
|
*/
|
|
5
5
|
import type { RunPlanCheckerLoopUseCase } from '../../application/usecases/run-plan-checker-loop-usecase.js';
|
|
6
|
+
import type { FileSystemPort } from '../../domain/ports/file-system-port.js';
|
|
6
7
|
|
|
7
8
|
export interface RunPlanCheckerLoopArgs {
|
|
8
9
|
planFile: string;
|
|
@@ -10,12 +11,15 @@ export interface RunPlanCheckerLoopArgs {
|
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
export class RunPlanCheckerLoopHandler {
|
|
13
|
-
constructor(
|
|
14
|
+
constructor(
|
|
15
|
+
private readonly useCase: RunPlanCheckerLoopUseCase,
|
|
16
|
+
private readonly planReader?: Pick<FileSystemPort, 'read'>,
|
|
17
|
+
) {}
|
|
14
18
|
|
|
15
19
|
async handle(args: RunPlanCheckerLoopArgs): Promise<{ exitCode: number; message: string }> {
|
|
16
20
|
try {
|
|
17
21
|
const output = await this.useCase.execute({
|
|
18
|
-
planDocument: args.planFile,
|
|
22
|
+
planDocument: this.planReader ? await this.planReader.read(args.planFile) : args.planFile,
|
|
19
23
|
storyId: args.storyId,
|
|
20
24
|
});
|
|
21
25
|
|
|
@@ -24,9 +28,12 @@ export class RunPlanCheckerLoopHandler {
|
|
|
24
28
|
).join('\n');
|
|
25
29
|
|
|
26
30
|
if (output.escalationRequired) {
|
|
27
|
-
|
|
31
|
+
const guidance = output.stopReason === 'UNCHANGED_INPUT'
|
|
32
|
+
? '\n同じ入力の再試行では改善しません。文書を修正するか判断を求めてください。'
|
|
33
|
+
: '';
|
|
34
|
+
return { exitCode: 1, message: `Plan check FAILED_EXCEEDED - escalation required\n${historyLines}${guidance}\nこの結果は設計の意味的承認ではありません。` };
|
|
28
35
|
}
|
|
29
|
-
return { exitCode: 0, message: `Plan check PASSED\n${historyLines}
|
|
36
|
+
return { exitCode: 0, message: `Plan check PASSED\n${historyLines}\nこの結果は設計の意味的承認ではありません。` };
|
|
30
37
|
} catch (err) {
|
|
31
38
|
return { exitCode: 2, message: `Error: ${err instanceof Error ? err.message : String(err)}` };
|
|
32
39
|
}
|
package/scripts/harness/traceability-model/infrastructure/parsers/work-item-frontmatter-parser.ts
CHANGED
|
@@ -31,6 +31,47 @@ const flowArrayPattern = (key: string): RegExp => new RegExp(`^\\s*${key}\\s*:\\
|
|
|
31
31
|
const blockArrayPattern = (key: string): RegExp =>
|
|
32
32
|
new RegExp(`^\\s*${key}\\s*:\\s*\\r?\\n((?:[ \\t]+-[ \\t]+.+\\r?\\n?)+)`, "m");
|
|
33
33
|
|
|
34
|
+
/** Opt-in dependency diagnostics; existing metadata readers keep their old contract. */
|
|
35
|
+
export function parseWorkItemDependencies(content: string): readonly string[] | undefined {
|
|
36
|
+
const body = FRONTMATTER_PATTERN.exec(content)?.[1];
|
|
37
|
+
if (body === undefined) return undefined;
|
|
38
|
+
const lines = body.split(/\r?\n/);
|
|
39
|
+
const headers = lines.flatMap((line, index) => /^[ \t]*depends_on[ \t]*:/.test(line) ? [index] : []);
|
|
40
|
+
if (headers.length === 0) return undefined;
|
|
41
|
+
const invalid = (reason: string): never => {
|
|
42
|
+
throw new WorkItemFrontmatterValidationError(`depends_on ${reason}`);
|
|
43
|
+
};
|
|
44
|
+
if (headers.length !== 1) return invalid('が重複しています');
|
|
45
|
+
if (!lines[headers[0]].startsWith('depends_on')) return invalid('はfrontmatter直下に指定してください');
|
|
46
|
+
const withoutComment = (value: string) => value.replace(/[ \t]+#.*$/, '').trim();
|
|
47
|
+
const declaration = withoutComment(lines[headers[0]].replace(/^[ \t]*depends_on[ \t]*:/, ''));
|
|
48
|
+
const continuation: string[] = [];
|
|
49
|
+
for (const line of lines.slice(headers[0] + 1)) {
|
|
50
|
+
if (line.trim() === '' || line.trimStart().startsWith('#')) continue;
|
|
51
|
+
if (/^[^\s:#][^:]*:/.test(line)) break;
|
|
52
|
+
continuation.push(line);
|
|
53
|
+
}
|
|
54
|
+
let values: string[];
|
|
55
|
+
if (declaration.startsWith('[') && declaration.endsWith(']')) {
|
|
56
|
+
if (continuation.length > 0) return invalid('のflow配列に続く行が不正です');
|
|
57
|
+
const inner = declaration.slice(1, -1).trim();
|
|
58
|
+
values = inner === '' ? [] : inner.split(',');
|
|
59
|
+
} else if (declaration === '') {
|
|
60
|
+
values = [];
|
|
61
|
+
for (const line of continuation) {
|
|
62
|
+
const item = /^[ \t]+-[ \t]+(.+)$/.exec(line);
|
|
63
|
+
if (!item) return invalid('はWI IDの配列で指定してください');
|
|
64
|
+
values.push(withoutComment(item[1]));
|
|
65
|
+
}
|
|
66
|
+
if (values.length === 0) return invalid('の空宣言には [] を指定してください');
|
|
67
|
+
} else {
|
|
68
|
+
return invalid('はWI IDの配列で指定してください');
|
|
69
|
+
}
|
|
70
|
+
const ids = values.map((value) => stripYamlQuotes(value.trim()));
|
|
71
|
+
if (ids.some((id) => !/^WI-\d+$/.test(id))) return invalid('に不正なWI IDまたは空項目があります');
|
|
72
|
+
return Object.freeze(ids);
|
|
73
|
+
}
|
|
74
|
+
|
|
34
75
|
export function parseWorkItemFrontmatter(content: string): WorkItemFrontmatter | null {
|
|
35
76
|
const match = FRONTMATTER_PATTERN.exec(content);
|
|
36
77
|
if (!match) return null;
|
package/skills/README.md
CHANGED
|
@@ -20,4 +20,11 @@
|
|
|
20
20
|
|
|
21
21
|
## 新しいスキルの追加
|
|
22
22
|
|
|
23
|
+
### 利用者向けの選択
|
|
24
|
+
|
|
25
|
+
<!-- @work-item-id WI-223 -->
|
|
26
|
+
`phasegate install --skills consumer --dry-run`で本体メンテナー用の`release-publisher`と`skill-creator`を除く27件を確認できる。適用は`--apply`を明示する。既存の`core`は7件、`all`と省略時は29件のまま。reconcileは各配置先の`.harness-version`に記録したセットを維持する。セット変更だけで以前のスキルやユーザー作成スキルを削除しないため、既存allからの切替は削除移行ではない。
|
|
27
|
+
|
|
28
|
+
配布カタログの正本は`installation/application/bundled-skill-selection.ts`の一箇所。consumerは言語非依存化済みという意味ではなく、Vitest/Playwright等の技術固有スキルは引き続き含まれる。
|
|
29
|
+
|
|
23
30
|
新しいスキルを追加する場合は、この `skills` ディレクトリに直接追加してください。あわせて `docs/guide/skills-overview.md`、README の skill 数、必要なら `skills/phasegate-toolkit-guide/SKILL.md` の参照先を更新します。シンボリックリンクを通じて、対応エージェントから利用可能になります。<!-- @work-item-id WI-154 -->
|
|
@@ -1,141 +1,69 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cascade-updater
|
|
3
|
-
description:
|
|
4
|
-
model: sonnet
|
|
5
|
-
review: opus
|
|
3
|
+
description: WIの設計反映や下位の発見を起点に、上位判断が必要な変更を識別し、設計本文と下位成果物の整合を更新する。
|
|
6
4
|
languages: [typescript]
|
|
7
5
|
---
|
|
8
6
|
|
|
9
7
|
# Cascade Updater
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
## 目的
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
上位の意図を成果物へ伝え、下位で見つかった前提の破綻を必要な上位判断へ戻す。ゲート通過のためのタグ追記だけで終えない。
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
## 入力
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
対象WI、発見・変更の内容と観測元、関連する設計・実装・テスト。既存の依頼とファイルから特定できる情報は再質問しない。意味や変更範囲が決まらない点だけ確認する。
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
- cascade-updater を実行せずに実装へ進もうとすると `[L2-STORY-REFLECTION]` ブロックが発生する(エラー中で本スキルの実行が案内される)
|
|
21
|
-
- `minimal` プリセットでは storyReflection が無効化されるためゲート連動しないが、cascade-updater による設計整合性の維持は推奨される
|
|
22
|
-
- Quick Mode (`relaxedGates: ["phase-gate"]`) 時は storyReflection も緩和されるため、cascade-updater 実行の必須性は緩まる(ただし品質維持のため実行は推奨)
|
|
17
|
+
## 前提条件
|
|
23
18
|
|
|
24
|
-
|
|
19
|
+
プロジェクトのAGENTS.md、ドキュメント配置規則、対象WIと関連product設計を正本とする。配置rootはそのプロジェクトの設定を確認し、Phasegate自体のパスをconsumerへ強制しない。
|
|
25
20
|
|
|
26
|
-
|
|
21
|
+
- 標準配置では単一Unit WIは `docs/inception/{unit}/{WI-XXX}/`、横断WIは `docs/inception/_cross/{WI-XXX}/`。crossのaffectsと共有契約への実際の依存を確認する。
|
|
22
|
+
- 既存の実行権限・保護設定・gateは維持する。このスキルの使用やタグの存在は書込みの認可にならない。
|
|
23
|
+
- 実行モデルや委任可否はプロジェクトのモデルルーティングに従う。固定モデルへの委任や新たな承認段階を必須にしない。
|
|
24
|
+
- 帰属が曖昧な場合だけ [層別判定ガイド](references/層別判定ガイド.md) を読む。ファイルの置き場所だけでリスクを決めない。
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
- **変更内容の記述** — 何が発見/変更されたか
|
|
30
|
-
- **変更が発生したレイヤー** — どのフェーズで発見されたか
|
|
26
|
+
## 実行フロー
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
## ⚠️ 3フェーズ実行ルール
|
|
35
|
-
|
|
36
|
-
**このスキルは3フェーズで実行する。**
|
|
37
|
-
- **Phase 1(計画)**: Opus がスコープ・方針・不明点を整理し、人間の承認を得る
|
|
38
|
-
- **Phase 2(実行)**: プロジェクトのモデルルーティング設定に従い、実行モデルに委譲して成果物を生成する
|
|
39
|
-
- **Phase 3(レビュー)**: Opus が成果物を検証し、問題があれば直接修正する
|
|
40
|
-
|
|
41
|
-
**Phase 1/2/3を同時に実行してはならない。**
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## Phase 1: 影響分析(plan)
|
|
46
|
-
|
|
47
|
-
### 目的
|
|
48
|
-
変更の帰属レイヤーを判定し、影響範囲を特定して人間の承認を得る。
|
|
28
|
+
### 影響と判断を分ける
|
|
49
29
|
|
|
50
|
-
|
|
51
|
-
会話内で以下を報告する(ファイルは作成しない):
|
|
30
|
+
現行設計、発見の根拠、対象revision(commitと必要な作業差分)を確認し、どの前提と下位成果物へ影響するかを対象WIに記録する。既存記録を更新し、並行する新台帳を作らない。
|
|
52
31
|
|
|
53
|
-
|
|
54
|
-
|
|
32
|
+
- **合意済みの意味を変えない整合修正**:依頼された範囲なら追加の一律承認を待たずに進める。例:設計と実装の用語一致、重複説明の統合、契約を変えない内部抽出の設計反映。
|
|
33
|
+
- **上位の判断を変える変更**:目的・受け入れ条件・公開API・認可・データ契約・業務不変条件・Unit境界、または依頼範囲の変更は決定者へ確認する。既に明示承認された判断を同じ内容で再度要求しない。
|
|
34
|
+
- **判断不明**:影響する契約と不明点を示す。安全な調査や計画は続け、未確定の前提に依存する実装は保留する。未知を自動許可にも全作業停止にも変えない。
|
|
55
35
|
|
|
56
|
-
|
|
57
|
-
- 発見元: {フェーズ/ストーリー}
|
|
58
|
-
- 内容: {変更内容}
|
|
36
|
+
上位判断が必要なときは、既存WI/必要なADRへ「観測・根拠」「変わる前提とrevision」「選択肢と影響」「決定者」「停止範囲」「再開条件」を残し、判断を求める。止めるのはその判断に依存する作業だけ。承認待ちを同じコマンドの自動再試行へ置き換えない。
|
|
59
37
|
|
|
60
|
-
|
|
61
|
-
- 判定結果: {環境設計 / 論理設計 / Domain / ストーリー}
|
|
62
|
-
- 理由: {判定理由}
|
|
63
|
-
参考: references/層別判定ガイド.md
|
|
38
|
+
### 設計本文へ反映する
|
|
64
39
|
|
|
65
|
-
|
|
66
|
-
| # | ファイル | 予定される変更内容 |
|
|
67
|
-
|---|---------|-----------------|
|
|
40
|
+
合意した最上位の設計から必要な下位設計、実装・テストへ伝える。実装はプロジェクトのフェーズ順序・必要なproduct反映を満たしてから行う。調査だけの依頼なら変更案までで止める。
|
|
68
41
|
|
|
69
|
-
|
|
42
|
+
productは**現行仕様を一貫して読める本文**へ統合・置換する。旧説明と矛盾する追記を積み重ねない。意味を変える削除には上位判断が必要だが、合意済み意味を保つ重複・旧説明の整理まで一律承認にしない。理由・旧仕様との差・根拠はWI/ADR/Gitで追跡可能にする。
|
|
70
43
|
|
|
71
|
-
|
|
72
|
-
{質問の詳細と背景}
|
|
73
|
-
**推奨案:** {AIの推奨案}
|
|
44
|
+
新しいWI反映には `@work-item-id WI-XXX` を付ける。既存legacyタグと履歴参照は維持し、一括改番・置換しない。タグは参照の証拠であって、本文の意味的反映の証明ではない。
|
|
74
45
|
|
|
75
|
-
|
|
76
|
-
(人間が回答を記入)
|
|
77
|
-
```
|
|
46
|
+
### 判断後に再開・終了する
|
|
78
47
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
---
|
|
48
|
+
| 判断 | 次の行動 |
|
|
49
|
+
|---|---|
|
|
50
|
+
| 承認 | 決定と対象revisionを記録し、上位設計から依存成果物へ反映して再検証する。満たした再開条件で対象作業を再開する |
|
|
51
|
+
| 却下 | その変更案を終了する。旧契約内で目的を達成できる場合は再計画し、同じ案の承認要求を繰り返さない |
|
|
52
|
+
| 代替案 | 明示的に選ばれた案と範囲に合わせて再計画する。提示された選択肢を承認と推定しない |
|
|
53
|
+
| 判断後に前提が変更 | 変更された前提と影響だけを再評価する。古い承認を新revisionへ無条件に流用しない |
|
|
86
54
|
|
|
87
|
-
|
|
55
|
+
設計レビュー、機械検証、テスト結果を別々に記録する。World Modelを利用している場合は既存の明示依存/pinの両端のrevisionを確認し、その運用に従って必要なレビューを更新する。未導入環境に導入を要求せず、baseline/waiverを削除して解決したことにしない。
|
|
88
56
|
|
|
89
|
-
|
|
90
|
-
- 人間がPhase 1の影響分析を承認した
|
|
57
|
+
## 出力と完了条件
|
|
91
58
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
1. **該当レイヤーの文書を更新** — 変更内容を反映(追記優先、変更理由を記録)
|
|
95
|
-
2. **下位レイヤーの影響確認** — 更新により下位文書に矛盾が生じないか確認・更新
|
|
96
|
-
3. **更新レポート出力** — 変更した全文書の一覧と変更内容を報告
|
|
97
|
-
|
|
98
|
-
### 更新時の原則
|
|
99
|
-
|
|
100
|
-
- **更新は該当レイヤー以下のみ** — 上位の抽象設計は汚さない
|
|
101
|
-
- **追記優先** — 既存の記述を削除するのではなく、新しい制約・ルールを追記する
|
|
102
|
-
- **変更理由を記録** — なぜこの変更が必要になったかを文書内に簡潔に記録する
|
|
103
|
-
|
|
104
|
-
### Phase 2 最低出力基準(Sonnet委任時の品質制約)
|
|
105
|
-
|
|
106
|
-
以下の基準を満たさない出力は不完全とみなし、Phase 3レビューでBLOCKとする。
|
|
107
|
-
|
|
108
|
-
| 基準 | 最低要件 |
|
|
109
|
-
|------|---------|
|
|
110
|
-
| 帰属レイヤー明記 | 各変更が帰属するレイヤーが明示されていること |
|
|
111
|
-
| 変更理由記録 | 全変更箇所に変更理由が記録されていること |
|
|
112
|
-
| 追記優先 | 既存記述の削除ではなく追記で対応していること(削除は明示的承認があった場合のみ) |
|
|
113
|
-
| 下位影響確認 | 更新による下位文書への影響が確認・記録されていること |
|
|
114
|
-
| 更新レポート | 変更した全文書の一覧と変更内容が報告されていること |
|
|
115
|
-
|
|
116
|
-
詳細な判定パターンと具体例は [references/層別判定ガイド.md](references/層別判定ガイド.md) を参照。
|
|
117
|
-
|
|
118
|
-
---
|
|
59
|
+
対象WIの記録から、変更理由・判断、対象revision、更新した上位/下位文書、関連実装・テストと検証結果へ到達できるようにする。無関係なWIの再審査はしない。
|
|
119
60
|
|
|
120
|
-
|
|
61
|
+
完了前に、現行productの矛盾が解消されたか、上位の決定が必要な下位成果物へ伝わったか、検証が更新後のrevisionを対象としているかを確認する。未実施テストや残る上位判断は未完了と明記する。下位成果物への反映が未完ならタグが揃っていても完了としない。
|
|
121
62
|
|
|
122
|
-
|
|
123
|
-
メインセッション(model-routing.md の Architect ロール)が実行する。Sonnetへの再委任は行わない。
|
|
63
|
+
## CLI・ゲートとの境界
|
|
124
64
|
|
|
125
|
-
|
|
126
|
-
1. Sonnetが出力したファイルを読み込む
|
|
127
|
-
2. プロジェクトのレビュー基準に沿って検証する
|
|
128
|
-
3. **スキル固有レビュー観点**を検証する
|
|
129
|
-
4. 判定結果を出力する
|
|
65
|
+
`skill:apply-cascade-update` は互換用のタグ追記CLIであり、設計本文の統合更新や意味レビューを代行しない。CLIの成功を本スキルの完了と扱わない。
|
|
130
66
|
|
|
131
|
-
|
|
132
|
-
- [ ] 変更が正しいレイヤーに帰属しているか(上位の抽象設計を汚していないか)
|
|
133
|
-
- [ ] 変更理由が全箇所に記録されているか
|
|
134
|
-
- [ ] 既存記述の不必要な削除がないか
|
|
135
|
-
- [ ] 下位文書への影響が確認されているか
|
|
136
|
-
- [ ] Phase 1の影響分析と実際の更新範囲が一致しているか
|
|
67
|
+
storyReflectionで止まった場合は、エラーが示すWI・不足文書・反映先を確認し、inception/productを正規の順で修正してから再検証する。同じ根拠・revisionで解決済みなのに拒否が残る場合は、入力と診断を保存して原因を調査・引き継ぎ、保護解除や同一状態の無限再試行をしない。Quick Mode等の利用だけで設計整合や承認が済んだと推定しない。
|
|
137
68
|
|
|
138
|
-
|
|
139
|
-
- **BLOCK項目にFAIL** → Opusが直接修正してから完了とする
|
|
140
|
-
- **WARNのみFAIL** → Opusが直接修正してから完了とする
|
|
141
|
-
- **全PASS** → 完了
|
|
69
|
+
ゲート設定の詳細は配備されたPhasegateの `docs/guide/configuration.md` とADR-013を必要時に参照する(consumerでは `node_modules/phasegate/docs/`、本リポジトリでは `docs/`)。
|
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
変更・発見の種類ごとに、どのレイヤーの設計文書を更新すべきかの判定基準と具体例。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
帰属と承認要否は別に判断する。頻度やファイル位置ではなく、変更で意味が変わる最上位の前提を確認する。以下の例でも、目的・契約・認可・不変条件に影響するならその決定へ戻る。
|
|
6
|
+
|
|
7
|
+
## 環境設計に帰属するもの
|
|
6
8
|
|
|
7
9
|
**判定基準:** コードの正しさではなく、環境の正しさに関する問題
|
|
8
10
|
|
|
9
11
|
| パターン | 例 |
|
|
10
12
|
|---------|-----|
|
|
11
13
|
| 設定ファイルの漏れ | サービス/関数が設定ファイルに未登録 |
|
|
12
|
-
| ランタイム制約 |
|
|
14
|
+
| ランタイム制約 | 合意済みランタイムと実行環境の不一致(認証アルゴリズムの変更は認可契約も確認) |
|
|
13
15
|
| フレームワーク制約 | 特定ファイルからのexportルール、ビルド制約 |
|
|
14
16
|
| シードデータ不足 | テストに必要なデータ層の欠落 |
|
|
15
17
|
| マイグレーション漏れ | DB変更が適用されていない |
|
|
@@ -37,7 +39,7 @@
|
|
|
37
39
|
| 状態遷移の不足 | 必要なドメインイベントが未定義 |
|
|
38
40
|
| 不変条件の誤り | ビジネスルールの理解が間違っていた |
|
|
39
41
|
|
|
40
|
-
## ストーリー/Unit
|
|
42
|
+
## ストーリー/Unitに帰属するもの
|
|
41
43
|
|
|
42
44
|
**判定基準:** そもそも何を作るかの理解に関する問題
|
|
43
45
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: release-publisher
|
|
3
3
|
kind: advisory
|
|
4
|
-
description:
|
|
4
|
+
description: Phasegate本体パッケージのリリースを依頼されたときのメンテナー向け手順。利用者プロジェクトのリリースや一般的なnpm認証相談には適用しない。
|
|
5
5
|
model: sonnet
|
|
6
6
|
review: opus
|
|
7
7
|
languages: [typescript]
|
|
@@ -11,6 +11,8 @@ languages: [typescript]
|
|
|
11
11
|
|
|
12
12
|
## 目的
|
|
13
13
|
|
|
14
|
+
対象はPhasegate本体のリポジトリだけ。以下の認証・バージョニング規則を利用者プロジェクトへ適用しない。publish、tag、pushはユーザーが依頼した範囲だけ実施する。対象や現行の公開手順が確認できない場合は先に確認する。
|
|
15
|
+
|
|
14
16
|
phasegate パッケージのリリース(version bump → git tag → npm publish)を、誤操作・認証事故なしに完遂するための厳格手順ガイド(advisory)。正となる規範は `CLAUDE.md` の「バージョニングルール」「npm publish ルール」節、および `DEVELOPMENT.md` の「Versioning and Release」「Troubleshooting npm publish authentication」節。本スキルはそれらを実行手順として展開する。
|
|
15
17
|
|
|
16
18
|
## 絶対ルール(違反禁止)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: skill-creator
|
|
3
3
|
kind: advisory
|
|
4
|
-
description:
|
|
4
|
+
description: Phasegate本体のバンドルスキルを追加・改訂するときのメンテナー向けガイド。利用者プロジェクト独自のスキル作成には適用しない。
|
|
5
5
|
model: opus
|
|
6
6
|
languages: [typescript]
|
|
7
7
|
---
|
|
@@ -57,8 +57,8 @@ phasegate のスキル frontmatter は `name` / `description` に加えて、他
|
|
|
57
57
|
|
|
58
58
|
新規スキルは skill-structure バリデータ(`scripts/harness/skill-quality/domain/services/skill-structure-validator.ts`)に**必ず合格**する。バリデータはスキルの **kind** ごとに必須セクションを決める:
|
|
59
59
|
|
|
60
|
-
- **lifecycle
|
|
61
|
-
- **advisory**(allowlist
|
|
60
|
+
- **lifecycle**(既定): `frontmatter` / `languageMetadata` / `purpose` / `inputs` / `outputs` / `prerequisites` / `executionFlow` の 7 セクションを全保有すること。
|
|
61
|
+
- **advisory**(allowlist。本スキル含む): `frontmatter` / `languageMetadata` / `purpose` の 3 セクションのみ必須。件数の正本は以下のcorpusテスト。
|
|
62
62
|
|
|
63
63
|
### セクション名 → 見出しの対応(sectionMap)
|
|
64
64
|
|
|
@@ -77,16 +77,15 @@ phasegate のスキル frontmatter は `name` / `description` に加えて、他
|
|
|
77
77
|
### kind の登録場所(allowlist / taxonomy)
|
|
78
78
|
|
|
79
79
|
- kind 型と必須セクションの定義: `scripts/harness/skill-quality/domain/types/skill-kind.ts` と `.../value-objects/skill-structure.ts`。
|
|
80
|
-
- **advisory allowlist の pin**: `scripts/harness/__tests__/integration/skill-quality/skill-corpus-conformance.test.ts` の `ADVISORY_SKILLS`
|
|
80
|
+
- **advisory allowlist の pin**: `scripts/harness/__tests__/integration/skill-quality/skill-corpus-conformance.test.ts` の `ADVISORY_SKILLS` 配列。列挙されていない自己宣言はテストが fail する。**advisory を増やす場合はこのテストの allowlist を意図的に更新すること**(lifecycle 要求の回避を防ぐ pin)。lifecycle スキルを追加する場合は allowlist 変更不要だが、7 セクションを全て満たす必要がある。
|
|
81
81
|
|
|
82
82
|
## カタログ登録(新規スキル追加時に必須)
|
|
83
83
|
|
|
84
84
|
新規スキルは SKILL.md を書くだけでは配信されない。以下のカタログ・件数 pin を必ず更新する:
|
|
85
85
|
|
|
86
|
-
1. `scripts/harness/
|
|
87
|
-
2. `
|
|
88
|
-
3.
|
|
89
|
-
4. advisory を追加する場合は前述の `skill-corpus-conformance.test.ts` の `ADVISORY_SKILLS` と、テスト内の件数期待値(`skills.length` / lifecycle・advisory の内訳)も更新する。
|
|
86
|
+
1. 単一正本 `scripts/harness/installation/application/bundled-skill-selection.ts` のカテゴリと配布選択。setup側は委譲するためカタログを複製しない。consumerには本体用のrelease-publisher/skill-creatorを含めず、旧core/allの互換は維持する。
|
|
87
|
+
2. `skills/README.md`・`docs/guide/skills-overview.md`の配布説明と件数を実体に合わせる。
|
|
88
|
+
3. advisoryを追加する場合は前述のcorpusテストのallowlistと件数期待値も更新する。
|
|
90
89
|
|
|
91
90
|
> なお `scripts/harness/` 配下のソース(`skill-deployer.ts` / `bundled-skill-selection.ts` 等)の変更はフェーズゲート対象であり、`quick-implementor` / `story-implementor` スキル経由で行う(CLAUDE.md 参照)。スキル本文(`skills/**` の docs)編集はゲート緩和対象。
|
|
92
91
|
|
|
@@ -113,5 +112,5 @@ phasegate のスキル frontmatter は `name` / `description` に加えて、他
|
|
|
113
112
|
3. **雛形の用意** — 同種の既存スキル(lifecycle は例えば `unit-designer`、advisory は `phasegate-config-doctor`)の SKILL.md を土台にコピーし、frontmatter・見出しを埋める。
|
|
114
113
|
4. **本文作成** — 日本語散文で。3 フェーズ系なら結合文字列をバイト単位で流用。詳細は `references/` へ切り出す。
|
|
115
114
|
5. **構造検証** — `npx vitest run scripts/harness/__tests__/integration/skill-quality`(corpus-conformance)で宣言 kind の必須セクションに合格することを確認。
|
|
116
|
-
6. **カタログ登録** — `
|
|
115
|
+
6. **カタログ登録** — `bundled-skill-selection.ts`と関連する配布説明・corpus期待値を更新。
|
|
117
116
|
7. **反復** — 実タスクで使い、SKILL.md / references を改善する。
|