persona-harness 0.3.2-alpha.2 → 0.3.3-alpha.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/.persona/rules/backend/gradle-bootstrap.md +1 -1
- package/CHANGELOG.md +51 -0
- package/dist/cli/bootstrap.d.ts +8 -0
- package/dist/cli/bootstrap.js +154 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cli/index.js +8 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/plan-prompts.js +5 -0
- package/dist/cli/plan-prompts.js.map +1 -1
- package/dist/cli/plan.js +92 -1
- package/dist/cli/plan.js.map +1 -1
- package/dist/cli/workflow-command.js +37 -4
- package/dist/cli/workflow-command.js.map +1 -1
- package/dist/cli/workflow-output.d.ts +1 -0
- package/dist/cli/workflow-output.js +37 -7
- package/dist/cli/workflow-output.js.map +1 -1
- package/dist/cli/workflow-status.js +53 -14
- package/dist/cli/workflow-status.js.map +1 -1
- package/dist/phase0/injection.js +4 -3
- package/dist/phase0/injection.js.map +1 -1
- package/dist/phase0/java-role-discovery.js +26 -1
- package/dist/phase0/java-role-discovery.js.map +1 -1
- package/docs/current/release/next-version-readiness.md +11 -2
- package/docs/current/release/v0.3.2-alpha.2-release-notes.md +6 -0
- package/docs/current/release/v0.3.2-alpha.3-clean-short-request-review.md +285 -0
- package/docs/current/release/v0.3.2-alpha.3-on-off-ab-review.md +220 -0
- package/docs/current/release/v0.3.2-alpha.3-release-notes.md +108 -0
- package/docs/current/release/v0.3.3-alpha.0-release-notes.md +132 -0
- package/package.json +1 -1
- package/packages/shared-skills/skills/programming/references/java/backend.md +2 -0
|
@@ -20,7 +20,7 @@ enforcement: inject_only
|
|
|
20
20
|
|
|
21
21
|
- Gradle build file에서는 Java/Spring Boot backend 기준을 유지하고 Maven `pom.xml`을 생성하지 않는다.
|
|
22
22
|
- `settings.gradle` 또는 `settings.gradle.kts`는 하나의 Spring Boot application root project 이름을 명확히 둔다.
|
|
23
|
-
- `build.gradle` 또는 `build.gradle.kts`는 Spring Boot backend를 만들기 위한 최소 plugin/dependency/source compatibility만 다루며, 호환되는 Spring Boot plugin / Gradle launcher or wrapper / JDK toolchain 조합을 먼저 선택하고 그 선택을 build file에 명시한다. JUnit Platform 실행에는 `testRuntimeOnly "org.junit.platform:junit-platform-launcher"` 또는 동등한 runtime launcher를 포함한다.
|
|
23
|
+
- `build.gradle` 또는 `build.gradle.kts`는 Spring Boot backend를 만들기 위한 최소 plugin/dependency/source compatibility만 다루며, 호환되는 Spring Boot plugin / Gradle launcher or wrapper / JDK toolchain 조합을 먼저 선택하고 그 선택을 build file에 명시한다. 가능하면 Gradle wrapper(`gradlew`, `gradlew.bat`, `gradle/wrapper/`)를 포함해 `./gradlew test`, `./gradlew build`, `./gradlew bootRun`으로 검증할 수 있게 하며, JUnit Platform 실행에는 `testRuntimeOnly "org.junit.platform:junit-platform-launcher"` 또는 동등한 runtime launcher를 포함한다.
|
|
24
24
|
- 실행 가능한 Spring Boot app에서는 `bootJar`를 끄지 않는다. `tasks.named("bootJar") { enabled = false }` 또는 동등한 설정은 plain Java library로 명시된 프로젝트가 아니면 사용하지 않는다. `gradle build` 출력에 `:bootJar SKIPPED`가 나오면 실행 가능한 Spring Boot app 검증을 통과한 것으로 기록하지 않는다. `bootJar`가 `CopyProcessingSpec.getDirMode()` 같은 호환성 오류로 실패하면, `bootJar`를 비활성화하지 말고 Spring Boot plugin을 현재 Gradle과 호환되는 line으로 올리거나 Gradle wrapper를 해당 plugin이 지원하는 line으로 고정한다.
|
|
25
25
|
- 로컬 launcher가 Gradle 9.x이면 Spring Boot 3.3.x 같은 오래된 plugin line을 기본으로 섞지 않는다. 호환 여부가 불명확하면 executable app 기준으로 `gradle test`, `gradle build`, `gradle bootRun`이 모두 통과하는 line을 선택한다.
|
|
26
26
|
- build 설정은 presentation/application/domain/infrastructure package 구조를 대신하지 않는다.
|
package/CHANGELOG.md
CHANGED
|
@@ -6,8 +6,59 @@ This project uses npm prerelease versions for tester-facing alpha builds. During
|
|
|
6
6
|
|
|
7
7
|
## Unreleased
|
|
8
8
|
|
|
9
|
+
No unreleased changes yet.
|
|
10
|
+
|
|
11
|
+
## [0.3.3-alpha.0] - 2026-06-23
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- Added Existing Project Adaptation Mode to `ph plan`, with automatic `greenfield` versus `existing-code` project mode output.
|
|
16
|
+
- Added existing Java source discovery for package root and layer/style hints so brownfield projects can prefer their current package, naming, repository, DTO, and domain flow.
|
|
17
|
+
- Added plan/prompt/workflow guidance that existing code wins over greenfield guidance.
|
|
18
|
+
- Added README read coverage fallback from `.persona/evidence` when filled workflow reports omit explicit README ranges.
|
|
19
|
+
- Added existing Spring-style role discovery coverage for Controller, Service, Repository, DTO, Domain, Exception, and Test files.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- Changed Java Role Read Follow-up to ask for representative role files instead of every discovered Java file, while still recording full role-discovery evidence.
|
|
24
|
+
- Relaxed workflow finish classification when raw-shell checklist text remains but final verification was rerun through `npx ph bearshell`.
|
|
25
|
+
|
|
26
|
+
### Verification
|
|
27
|
+
|
|
28
|
+
- Existing Spring-style smoke used a current local tarball install, `npx ph init`, accepted plan workflow, and OpenCode `openai/gpt-5.4-mini-fast` with the short prompt `README.md 보고 구현해줘`.
|
|
29
|
+
- Observed `Mode: existing-code`, package root `com.acme.todo`, layer hints `domain, dto, repository, service, web`.
|
|
30
|
+
- Generated code stayed in the existing `web/service/repository/dto/domain` package flow rather than forcing `presentation/application/domain/infrastructure`.
|
|
31
|
+
- Java role discovery evidence covered Controller, Service, Repository, DTO, Domain, and Test files.
|
|
32
|
+
- `gradle test`, `gradle build`, and HTTP smoke passed through the generated project.
|
|
33
|
+
|
|
34
|
+
### Known Gaps
|
|
35
|
+
|
|
36
|
+
- OpenCode may still inspect package metadata such as `node_modules/persona-harness/package.json` before settling into the workflow rail.
|
|
37
|
+
- Agents may still perform an initial raw shell probe before rerunning final verification through `npx ph bearshell`.
|
|
38
|
+
- Long README continuation remains the next product gap; full TDD workflow is still future scope.
|
|
39
|
+
|
|
40
|
+
## [0.3.2-alpha.3] - 2026-06-23
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- Added `ph bootstrap backend` as an AI-facing fast path that fills missing backend profile, policy, accepted plan, and workflow report templates.
|
|
45
|
+
- Added conditional workflow behavior for non-harness projects: when `.persona/` is absent, `ph workflow implement` now returns an advisory PASS and does not block normal implementation.
|
|
46
|
+
- Added stricter initialized-harness behavior: when `.persona/` exists but profile/plan/report artifacts are missing, `ph workflow implement` now directs the agent to `npx ph bootstrap backend`.
|
|
47
|
+
- Added `ph workflow continue` as an AI-facing alias for the accepted-plan continuation prompt used after interrupted or long README implementations.
|
|
48
|
+
- Added clean short-request review evidence for the current alpha.3 candidate.
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- Strengthened Gradle wrapper guidance in Java/Spring implementation rails so generated apps prefer `./gradlew`/`gradlew.bat` verification and do not treat missing system Gradle as application failure.
|
|
53
|
+
- Clarified raw shell environment probe warnings as non-blocking notes when final verification was rerun through `npx ph bearshell`.
|
|
54
|
+
- Updated injection guidance so Persona Harness workflow gates apply only after a project has opted in with `.persona/`.
|
|
55
|
+
|
|
9
56
|
### Known Gaps
|
|
10
57
|
|
|
58
|
+
- OpenCode may still read `.persona/rules` directly before settling into the workflow rail.
|
|
59
|
+
- Workflow finish can still be satisfied by report text, so future hardening should reduce report-only self-attestation risk.
|
|
60
|
+
- This release still does not certify generated application product quality.
|
|
61
|
+
|
|
11
62
|
## [0.3.2-alpha.2] - 2026-06-22
|
|
12
63
|
|
|
13
64
|
### Added
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CliRunResult } from "./bearshell.js";
|
|
2
|
+
type BootstrapOptions = {
|
|
3
|
+
readonly projectDir?: string;
|
|
4
|
+
readonly packageRoot?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function bootstrapUsage(invocation?: string): string;
|
|
7
|
+
export declare function runBootstrapCommand(args: readonly string[], options?: BootstrapOptions, invocationName?: string): CliRunResult;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import { PROFILE_PATH } from "./intake-profile.js";
|
|
5
|
+
import { initializePersonaHarness } from "./init.js";
|
|
6
|
+
import { runIntakeCommand } from "./intake.js";
|
|
7
|
+
import { IMPLEMENTATION_REPORT_PATH, PLAN_PATH, REVIEW_REPORT_PATH } from "./plan.js";
|
|
8
|
+
import { runPlanCommand } from "./plan-command.js";
|
|
9
|
+
import { runPolicyCommand } from "./policy.js";
|
|
10
|
+
import { readBackendProjectProfileState } from "../phase0/project-profile.js";
|
|
11
|
+
const PERSONA_DIR = ".persona";
|
|
12
|
+
const POLICY_OVERLAY_PATH = ".persona/policies/overlay.jsonc";
|
|
13
|
+
export function bootstrapUsage(invocation = "ph") {
|
|
14
|
+
return [
|
|
15
|
+
`Usage: ${invocation} bootstrap backend [--force]`,
|
|
16
|
+
"",
|
|
17
|
+
"Prepares the backend Persona Harness workflow for AI implementation.",
|
|
18
|
+
"",
|
|
19
|
+
"What it fills when missing:",
|
|
20
|
+
`- ${PERSONA_DIR}/ harness files`,
|
|
21
|
+
`- ${PROFILE_PATH}`,
|
|
22
|
+
`- ${POLICY_OVERLAY_PATH}`,
|
|
23
|
+
`- ${PLAN_PATH}`,
|
|
24
|
+
`- ${IMPLEMENTATION_REPORT_PATH}`,
|
|
25
|
+
`- ${REVIEW_REPORT_PATH}`,
|
|
26
|
+
"",
|
|
27
|
+
"Scope:",
|
|
28
|
+
"- Java/Spring backend workflow convenience",
|
|
29
|
+
"- no generated app product-quality certification",
|
|
30
|
+
"- no frontend/infra workflow",
|
|
31
|
+
].join("\n");
|
|
32
|
+
}
|
|
33
|
+
function parseBootstrapArgs(args) {
|
|
34
|
+
if (args.length === 0 || args[0] === "--help" || args[0] === "-h" || args[0] === "help") {
|
|
35
|
+
return { kind: "help" };
|
|
36
|
+
}
|
|
37
|
+
if (args[0] !== "backend") {
|
|
38
|
+
return { kind: "invalid", message: `Unknown bootstrap command: ${args[0]}` };
|
|
39
|
+
}
|
|
40
|
+
let force = false;
|
|
41
|
+
for (const arg of args.slice(1)) {
|
|
42
|
+
if (arg === "--force") {
|
|
43
|
+
force = true;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
return { kind: "invalid", message: `Unknown option: ${arg}` };
|
|
47
|
+
}
|
|
48
|
+
return { kind: "backend", force };
|
|
49
|
+
}
|
|
50
|
+
function projectDirFor(options) {
|
|
51
|
+
return resolve(options.projectDir ?? process.cwd());
|
|
52
|
+
}
|
|
53
|
+
function failStep(step, result) {
|
|
54
|
+
return {
|
|
55
|
+
status: 1,
|
|
56
|
+
stdout: "",
|
|
57
|
+
stderr: [
|
|
58
|
+
`Persona Harness backend bootstrap failed during ${step}.`,
|
|
59
|
+
"",
|
|
60
|
+
result.stderr.trim().length > 0 ? result.stderr.trim() : result.stdout.trim(),
|
|
61
|
+
"",
|
|
62
|
+
].join("\n"),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function runAndRecord(actions, step, result, successMessage) {
|
|
66
|
+
if (result.status !== 0) {
|
|
67
|
+
return failStep(step, result);
|
|
68
|
+
}
|
|
69
|
+
actions.push(successMessage);
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
function runBackendBootstrap(options, force) {
|
|
73
|
+
const projectDir = projectDirFor(options);
|
|
74
|
+
const actions = [];
|
|
75
|
+
const skipped = [];
|
|
76
|
+
if (!existsSync(join(projectDir, PERSONA_DIR))) {
|
|
77
|
+
initializePersonaHarness({ projectDir, packageRoot: options.packageRoot });
|
|
78
|
+
actions.push("initialized .persona and OpenCode plugin config");
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
skipped.push(".persona already exists");
|
|
82
|
+
}
|
|
83
|
+
const profileState = readBackendProjectProfileState(projectDir);
|
|
84
|
+
if (force || profileState.status !== "ready") {
|
|
85
|
+
const result = runIntakeCommand(["--default", "backend", "--force"], { projectDir }, "ph");
|
|
86
|
+
const failure = runAndRecord(actions, "profile", result, "created default backend profile");
|
|
87
|
+
if (failure !== undefined) {
|
|
88
|
+
return failure;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
skipped.push(`${PROFILE_PATH} already ready`);
|
|
93
|
+
}
|
|
94
|
+
if (force || !existsSync(join(projectDir, POLICY_OVERLAY_PATH))) {
|
|
95
|
+
const policyArgs = force ? ["init", "--force"] : ["init"];
|
|
96
|
+
const result = runPolicyCommand(policyArgs, { projectDir }, "ph");
|
|
97
|
+
const failure = runAndRecord(actions, "policy", result, "created backend policy overlay");
|
|
98
|
+
if (failure !== undefined) {
|
|
99
|
+
return failure;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
skipped.push(`${POLICY_OVERLAY_PATH} already exists`);
|
|
104
|
+
}
|
|
105
|
+
if (force || !existsSync(join(projectDir, PLAN_PATH))) {
|
|
106
|
+
const result = runPlanCommand(["--auto-accept"], { projectDir }, "ph");
|
|
107
|
+
const failure = runAndRecord(actions, "plan", result, "created and accepted backend workflow plan");
|
|
108
|
+
if (failure !== undefined) {
|
|
109
|
+
return failure;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
skipped.push(`${PLAN_PATH} already exists`);
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
status: 0,
|
|
117
|
+
stdout: [
|
|
118
|
+
"Persona Harness backend bootstrap complete.",
|
|
119
|
+
"",
|
|
120
|
+
"Actions:",
|
|
121
|
+
...(actions.length > 0 ? actions.map((action) => `- ${action}`) : ["- no changes needed"]),
|
|
122
|
+
"",
|
|
123
|
+
"Skipped:",
|
|
124
|
+
...(skipped.length > 0 ? skipped.map((item) => `- ${item}`) : ["- none"]),
|
|
125
|
+
"",
|
|
126
|
+
"Ready workflow files:",
|
|
127
|
+
`- ${PROFILE_PATH}`,
|
|
128
|
+
`- ${POLICY_OVERLAY_PATH}`,
|
|
129
|
+
`- ${PLAN_PATH}`,
|
|
130
|
+
`- ${IMPLEMENTATION_REPORT_PATH}`,
|
|
131
|
+
`- ${REVIEW_REPORT_PATH}`,
|
|
132
|
+
"",
|
|
133
|
+
"Next:",
|
|
134
|
+
"- Ask the AI agent to run `npx ph workflow implement` before implementation.",
|
|
135
|
+
"- Short TUI requests like `README.md 보고 구현해줘` should use the workflow rail, not ad hoc commands.",
|
|
136
|
+
"",
|
|
137
|
+
"Scope:",
|
|
138
|
+
"- workflow convenience only",
|
|
139
|
+
"- no generated app product-quality certification",
|
|
140
|
+
].join("\n") + "\n",
|
|
141
|
+
stderr: "",
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
export function runBootstrapCommand(args, options = {}, invocationName = "ph") {
|
|
145
|
+
const parsed = parseBootstrapArgs(args);
|
|
146
|
+
if (parsed.kind === "help") {
|
|
147
|
+
return { status: 0, stdout: `${bootstrapUsage(invocationName)}\n`, stderr: "" };
|
|
148
|
+
}
|
|
149
|
+
if (parsed.kind === "invalid") {
|
|
150
|
+
return { status: 1, stdout: "", stderr: `${parsed.message}\n\n${bootstrapUsage(invocationName)}\n` };
|
|
151
|
+
}
|
|
152
|
+
return runBackendBootstrap(options, parsed.force);
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/cli/bootstrap.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import process from "node:process";
|
|
3
3
|
import { createInterface } from "node:readline/promises";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { runBootstrapCommand } from "./bootstrap.js";
|
|
5
6
|
import { runInitCommand } from "./init.js";
|
|
6
7
|
import { runBearshell } from "./bearshell.js";
|
|
7
8
|
import { runHistoryCommand } from "./history.js";
|
|
@@ -21,6 +22,9 @@ export function runPersonaCli(args, options = {}) {
|
|
|
21
22
|
if (command === "init") {
|
|
22
23
|
return runInitCommand({ projectDir: options.cwd, packageRoot: options.packageRoot });
|
|
23
24
|
}
|
|
25
|
+
if (command === "bootstrap") {
|
|
26
|
+
return runBootstrapCommand(args.slice(1), { projectDir: options.cwd, packageRoot: options.packageRoot }, invocationName);
|
|
27
|
+
}
|
|
24
28
|
if (command === "intake") {
|
|
25
29
|
return runIntakeCommand(args.slice(1), { projectDir: options.cwd }, invocationName);
|
|
26
30
|
}
|
|
@@ -72,6 +76,7 @@ function personaCliUsage(invocationName) {
|
|
|
72
76
|
"",
|
|
73
77
|
"Commands:",
|
|
74
78
|
" init Install Persona Harness config into the current project.",
|
|
79
|
+
" bootstrap backend Fill missing backend profile/policy/plan workflow pieces.",
|
|
75
80
|
" intake Create a draft backend project profile for planning.",
|
|
76
81
|
" plan Create a blackbear architecture plan draft before implementation.",
|
|
77
82
|
" policy Create backend-only policy overlay files.",
|
|
@@ -80,6 +85,7 @@ function personaCliUsage(invocationName) {
|
|
|
80
85
|
" bearshell <command> [args...] Run a bounded command helper for repo inspection and smoke tests.",
|
|
81
86
|
" workflow check Report plan/report/evidence workflow status.",
|
|
82
87
|
" workflow implement Print the single AI-facing implementation rail.",
|
|
88
|
+
" workflow continue Print the accepted-plan continuation prompt.",
|
|
83
89
|
" workflow start implement Print the AI-facing implementation workflow rail.",
|
|
84
90
|
" workflow finish implement Block final answer until implementation workflow evidence is complete.",
|
|
85
91
|
" workflow guard implement Block implementation until plan workflow state is ready.",
|
|
@@ -92,6 +98,7 @@ function personaCliUsage(invocationName) {
|
|
|
92
98
|
"",
|
|
93
99
|
"Examples:",
|
|
94
100
|
` ${invocationName} init`,
|
|
101
|
+
` ${invocationName} bootstrap backend`,
|
|
95
102
|
` ${invocationName} intake`,
|
|
96
103
|
` ${invocationName} plan`,
|
|
97
104
|
` ${invocationName} policy init`,
|
|
@@ -100,6 +107,7 @@ function personaCliUsage(invocationName) {
|
|
|
100
107
|
` ${invocationName} bearshell npm test`,
|
|
101
108
|
` ${invocationName} workflow check`,
|
|
102
109
|
` ${invocationName} workflow implement`,
|
|
110
|
+
` ${invocationName} workflow continue`,
|
|
103
111
|
` ${invocationName} workflow start implement`,
|
|
104
112
|
` ${invocationName} workflow finish implement`,
|
|
105
113
|
` ${invocationName} workflow guard implement`,
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/plan-prompts.js
CHANGED
|
@@ -10,6 +10,8 @@ export function createPlanOnlyPrompt() {
|
|
|
10
10
|
"긴 README.md나 plan은 한 번에 다 읽었다고 가정하지 말고, Read 출력이 잘리면 `npx ph bearshell --shell 'sed -n \"1,220p\" README.md'`, `npx ph bearshell --shell 'sed -n \"221,440p\" README.md'`처럼 범위를 나눠 끝까지 읽어줘.",
|
|
11
11
|
"",
|
|
12
12
|
"계획에는 요구사항 요약, Java/Spring Gradle 기술 선택, package/layer 구조, storage/persistence 선택, repository boundary, DTO boundary, domain behavior 기준을 포함해줘.",
|
|
13
|
+
"기존 Java/Spring 코드가 있으면 먼저 package/layer/naming/repository/DTO/domain style을 발견하고, existing code wins over greenfield guidance 원칙으로 그 구조에 맞춘 계획을 작성해줘.",
|
|
14
|
+
"새 프로젝트처럼 기존 코드가 없을 때만 0% -> 80% greenfield baseline package flow를 기본값으로 사용해줘.",
|
|
13
15
|
"",
|
|
14
16
|
"계획이 불확실하면 구현하지 말고 질문이나 가정을 .persona/workflow/plan.md에 명확히 남겨줘.",
|
|
15
17
|
"",
|
|
@@ -33,7 +35,10 @@ export function createImplementationPrompt() {
|
|
|
33
35
|
"구현 보고서의 Read Coverage에는 체크만 하지 말고 `README read method`, `README ranges read`, `Plan read method`, `Plan ranges read`, `Unread ranges`를 실제 실행 증거 기준으로 적어줘.",
|
|
34
36
|
"",
|
|
35
37
|
"구현 중에는 Java/Spring Gradle backend Clean Code 범위를 유지하고, plan에 없는 frontend/infra/desktop 범위로 확장하지 마.",
|
|
38
|
+
"기존 Java/Spring 코드가 있으면 먼저 package/layer/naming/repository/DTO/domain style을 읽고, existing code wins over greenfield guidance 원칙으로 현재 프로젝트 흐름에 맞춰 구현해줘.",
|
|
39
|
+
"새 프로젝트처럼 기존 코드가 없을 때만 0% -> 80% greenfield baseline package flow를 기본값으로 사용해줘.",
|
|
36
40
|
"실행 가능한 Spring Boot 앱이면 `bootJar`를 비활성화하지 마. `gradle build` 출력에 `:bootJar SKIPPED`가 나오면 build 통과로 기록하지 말고, Spring Boot plugin / Gradle wrapper / JDK toolchain 호환성을 맞춰 다시 검증해줘.",
|
|
41
|
+
"가능하면 생성 프로젝트에 Gradle wrapper를 포함하고, 검증은 `./gradlew test`, `./gradlew build`, `./gradlew bootRun` 또는 Windows `gradlew.bat` 기준으로 기록해줘.",
|
|
37
42
|
"",
|
|
38
43
|
"구현 후 .persona/workflow/implementation-report.md를 채우고 `npx ph plan --report-filled implementation`을 실행해줘.",
|
|
39
44
|
"",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan-prompts.js","sourceRoot":"","sources":["../../src/cli/plan-prompts.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,oBAAoB;IAClC,OAAO;QACL,yIAAyI;QACzI,EAAE;QACF,8GAA8G;QAC9G,uGAAuG;QACvG,EAAE;QACF,4HAA4H;QAC5H,EAAE;QACF,6LAA6L;QAC7L,EAAE;QACF,gJAAgJ;QAChJ,EAAE;QACF,gEAAgE;QAChE,EAAE;QACF,8HAA8H;QAC9H,EAAE;QACF,6FAA6F;KAC9F,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC;AAED,MAAM,UAAU,0BAA0B;IACxC,OAAO;QACL,mFAAmF;QACnF,EAAE;QACF,sLAAsL;QACtL,EAAE;QACF,8GAA8G;QAC9G,uGAAuG;QACvG,EAAE;QACF,6IAA6I;QAC7I,EAAE;QACF,6LAA6L;QAC7L,2JAA2J;QAC3J,EAAE;QACF,oGAAoG;QACpG,gLAAgL;QAChL,EAAE;QACF,0GAA0G;QAC1G,EAAE;QACF,mIAAmI;QACnI,EAAE;QACF,iMAAiM;QACjM,EAAE;QACF,6FAA6F;KAC9F,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC"}
|
|
1
|
+
{"version":3,"file":"plan-prompts.js","sourceRoot":"","sources":["../../src/cli/plan-prompts.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,oBAAoB;IAClC,OAAO;QACL,yIAAyI;QACzI,EAAE;QACF,8GAA8G;QAC9G,uGAAuG;QACvG,EAAE;QACF,4HAA4H;QAC5H,EAAE;QACF,6LAA6L;QAC7L,EAAE;QACF,gJAAgJ;QAChJ,uJAAuJ;QACvJ,+EAA+E;QAC/E,EAAE;QACF,gEAAgE;QAChE,EAAE;QACF,8HAA8H;QAC9H,EAAE;QACF,6FAA6F;KAC9F,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC;AAED,MAAM,UAAU,0BAA0B;IACxC,OAAO;QACL,mFAAmF;QACnF,EAAE;QACF,sLAAsL;QACtL,EAAE;QACF,8GAA8G;QAC9G,uGAAuG;QACvG,EAAE;QACF,6IAA6I;QAC7I,EAAE;QACF,6LAA6L;QAC7L,2JAA2J;QAC3J,EAAE;QACF,oGAAoG;QACpG,uJAAuJ;QACvJ,+EAA+E;QAC/E,gLAAgL;QAChL,sIAAsI;QACtI,EAAE;QACF,0GAA0G;QAC1G,EAAE;QACF,mIAAmI;QACnI,EAAE;QACF,iMAAiM;QACjM,EAAE;QACF,6FAA6F;KAC9F,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC"}
|
package/dist/cli/plan.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import { loadBackendPolicyOverlay } from "../phase0/policy-overlay.js";
|
|
@@ -13,6 +13,8 @@ export const PLAN_PATH = ".persona/workflow/plan.md";
|
|
|
13
13
|
export const IMPLEMENTATION_REPORT_PATH = ".persona/workflow/implementation-report.md";
|
|
14
14
|
export const REVIEW_REPORT_PATH = ".persona/workflow/review-report.md";
|
|
15
15
|
const README_PATH = "README.md";
|
|
16
|
+
const EXISTING_CODE_SCAN_ROOTS = ["src/main/java", "src/test/java"];
|
|
17
|
+
const EXISTING_CODE_SCAN_LIMIT = 40;
|
|
16
18
|
function readReadmeHeading(projectDir) {
|
|
17
19
|
const readmePath = join(projectDir, README_PATH);
|
|
18
20
|
if (!existsSync(readmePath)) {
|
|
@@ -52,6 +54,93 @@ function readmeLines(projectDir) {
|
|
|
52
54
|
heading === undefined ? "README status: missing" : `README heading: ${heading}`,
|
|
53
55
|
];
|
|
54
56
|
}
|
|
57
|
+
function collectJavaSourceFiles(projectDir) {
|
|
58
|
+
const javaFiles = [];
|
|
59
|
+
const visit = (relativeDir) => {
|
|
60
|
+
if (javaFiles.length >= EXISTING_CODE_SCAN_LIMIT) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const absoluteDir = join(projectDir, relativeDir);
|
|
64
|
+
if (!existsSync(absoluteDir)) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
for (const entry of readdirSync(absoluteDir).sort()) {
|
|
68
|
+
const relativePath = `${relativeDir}/${entry}`;
|
|
69
|
+
const absolutePath = join(projectDir, relativePath);
|
|
70
|
+
const stat = statSync(absolutePath);
|
|
71
|
+
if (stat.isDirectory()) {
|
|
72
|
+
visit(relativePath);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (stat.isFile() && entry.endsWith(".java")) {
|
|
76
|
+
javaFiles.push(relativePath);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
for (const root of EXISTING_CODE_SCAN_ROOTS) {
|
|
81
|
+
visit(root);
|
|
82
|
+
}
|
|
83
|
+
return javaFiles;
|
|
84
|
+
}
|
|
85
|
+
function packageNameFromJavaFile(projectDir, relativePath) {
|
|
86
|
+
const match = /^package\s+([^;]+);/m.exec(readFileSync(join(projectDir, relativePath), "utf8"));
|
|
87
|
+
return match?.[1]?.trim();
|
|
88
|
+
}
|
|
89
|
+
function commonPackagePrefix(packages) {
|
|
90
|
+
if (packages.length === 0) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
const segments = packages[0]?.split(".") ?? [];
|
|
94
|
+
let prefixLength = segments.length;
|
|
95
|
+
for (const packageName of packages.slice(1)) {
|
|
96
|
+
const current = packageName.split(".");
|
|
97
|
+
while (prefixLength > 0 && segments.slice(0, prefixLength).join(".") !== current.slice(0, prefixLength).join(".")) {
|
|
98
|
+
prefixLength -= 1;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return prefixLength > 0 ? segments.slice(0, prefixLength).join(".") : undefined;
|
|
102
|
+
}
|
|
103
|
+
function layerNamesFromJavaFiles(files) {
|
|
104
|
+
const layerCandidates = new Set();
|
|
105
|
+
for (const file of files) {
|
|
106
|
+
for (const segment of file.split("/")) {
|
|
107
|
+
if (/^(presentation|application|domain|infrastructure|controller|service|repository|dto|web|global|config|exception)$/i.test(segment)) {
|
|
108
|
+
layerCandidates.add(segment);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return [...layerCandidates].sort();
|
|
113
|
+
}
|
|
114
|
+
function projectModeLines(projectDir) {
|
|
115
|
+
const javaFiles = collectJavaSourceFiles(projectDir);
|
|
116
|
+
if (javaFiles.length === 0) {
|
|
117
|
+
return [
|
|
118
|
+
"## Project Mode",
|
|
119
|
+
"",
|
|
120
|
+
"Mode: greenfield",
|
|
121
|
+
"",
|
|
122
|
+
"- Goal: create a consistent 0% -> 80% Java/Spring backend baseline for a new project.",
|
|
123
|
+
"- Use the Java/Spring backend baseline package flow when README/profile do not define an existing convention.",
|
|
124
|
+
"- Keep the baseline advisory: user requirements and explicit instructions still win.",
|
|
125
|
+
];
|
|
126
|
+
}
|
|
127
|
+
const packages = javaFiles
|
|
128
|
+
.map((file) => packageNameFromJavaFile(projectDir, file))
|
|
129
|
+
.filter((packageName) => packageName !== undefined);
|
|
130
|
+
const packageRoot = commonPackagePrefix(packages);
|
|
131
|
+
const layers = layerNamesFromJavaFiles(javaFiles);
|
|
132
|
+
return [
|
|
133
|
+
"## Project Mode",
|
|
134
|
+
"",
|
|
135
|
+
"Mode: existing-code",
|
|
136
|
+
"",
|
|
137
|
+
`- Existing source files detected: ${javaFiles.length}`,
|
|
138
|
+
packageRoot === undefined ? "- Existing package root: unknown" : `- Existing package root: ${packageRoot}`,
|
|
139
|
+
layers.length === 0 ? "- Existing layer/style hints: none detected" : `- Existing layer/style hints: ${layers.join(", ")}`,
|
|
140
|
+
"- existing code wins over greenfield guidance: follow current package, naming, layer, repository, DTO, and domain style before introducing the baseline structure.",
|
|
141
|
+
"- If current code conflicts with profile guidance, record the conflict in this plan before implementation.",
|
|
142
|
+
];
|
|
143
|
+
}
|
|
55
144
|
function createPlanDraft(projectDir) {
|
|
56
145
|
const policyOverlaySummary = policyOverlayLines(projectDir);
|
|
57
146
|
return [
|
|
@@ -67,6 +156,8 @@ function createPlanDraft(projectDir) {
|
|
|
67
156
|
...profileSummaryLines(projectDir),
|
|
68
157
|
...(policyOverlaySummary.length > 0 ? ["", ...policyOverlaySummary] : []),
|
|
69
158
|
"",
|
|
159
|
+
...projectModeLines(projectDir),
|
|
160
|
+
"",
|
|
70
161
|
"## Architecture / Technology Plan",
|
|
71
162
|
"",
|
|
72
163
|
"- [ ] 요구사항의 핵심 유스케이스를 README 기준으로 정리한다.",
|
package/dist/cli/plan.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/cli/plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/cli/plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AACnG,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,OAAO,MAAM,cAAc,CAAA;AAElC,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAA;AACtE,OAAO,EAAE,gCAAgC,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAA;AAI/G,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAA;IAC9B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,2BAA2B,CAAA;AACpD,MAAM,CAAC,MAAM,0BAA0B,GAAG,4CAA4C,CAAA;AACtF,MAAM,CAAC,MAAM,kBAAkB,GAAG,oCAAoC,CAAA;AACtE,MAAM,WAAW,GAAG,WAAW,CAAA;AAC/B,MAAM,wBAAwB,GAAG,CAAC,eAAe,EAAE,eAAe,CAAU,CAAA;AAC5E,MAAM,wBAAwB,GAAG,EAAE,CAAA;AAEnC,SAAS,iBAAiB,CAAC,UAAkB;IAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;IAChD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;IAC/C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;QACxC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QAC1B,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,SAAS,mBAAmB,CAAC,UAAkB;IAC7C,MAAM,OAAO,GAAG,gCAAgC,CAAC,UAAU,CAAC,CAAA;IAC5D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,OAAO;QACL,cAAc;QACd,aAAa;QACb,EAAE;QACF,YAAY;QACZ,kDAAkD;QAClD,kCAAkC;QAClC,oDAAoD;KACrD,CAAA;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,UAAkB;IAC5C,OAAO,wBAAwB,CAAC,UAAU,CAAC,CAAC,YAAY,CAAA;AAC1D,CAAC;AAED,SAAS,WAAW,CAAC,UAAkB;IACrC,MAAM,OAAO,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAA;IAC7C,OAAO;QACL,0BAA0B,WAAW,IAAI;QACzC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,mBAAmB,OAAO,EAAE;KAChF,CAAA;AACH,CAAC;AAED,SAAS,sBAAsB,CAAC,UAAkB;IAChD,MAAM,SAAS,GAAa,EAAE,CAAA;IAC9B,MAAM,KAAK,GAAG,CAAC,WAAmB,EAAQ,EAAE;QAC1C,IAAI,SAAS,CAAC,MAAM,IAAI,wBAAwB,EAAE,CAAC;YACjD,OAAM;QACR,CAAC;QACD,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;QACjD,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,OAAM;QACR,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YACpD,MAAM,YAAY,GAAG,GAAG,WAAW,IAAI,KAAK,EAAE,CAAA;YAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAA;YACnD,MAAM,IAAI,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAA;YACnC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACvB,KAAK,CAAC,YAAY,CAAC,CAAA;gBACnB,SAAQ;YACV,CAAC;YACD,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC7C,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;YAC9B,CAAC;QACH,CAAC;IACH,CAAC,CAAA;IAED,KAAK,MAAM,IAAI,IAAI,wBAAwB,EAAE,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,CAAA;IACb,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,SAAS,uBAAuB,CAAC,UAAkB,EAAE,YAAoB;IACvE,MAAM,KAAK,GAAG,sBAAsB,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC,CAAA;IAC/F,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAA;AAC3B,CAAC;AAED,SAAS,mBAAmB,CAAC,QAA2B;IACtD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAA;IAC9C,IAAI,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAA;IAClC,KAAK,MAAM,WAAW,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACtC,OAAO,YAAY,GAAG,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAClH,YAAY,IAAI,CAAC,CAAA;QACnB,CAAC;IACH,CAAC;IACD,OAAO,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AACjF,CAAC;AAED,SAAS,uBAAuB,CAAC,KAAwB;IACvD,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAA;IACzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YACtC,IAAI,mHAAmH,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBACtI,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,eAAe,CAAC,CAAC,IAAI,EAAE,CAAA;AACpC,CAAC;AAED,SAAS,gBAAgB,CAAC,UAAkB;IAC1C,MAAM,SAAS,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAA;IACpD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO;YACL,iBAAiB;YACjB,EAAE;YACF,kBAAkB;YAClB,EAAE;YACF,uFAAuF;YACvF,+GAA+G;YAC/G,sFAAsF;SACvF,CAAA;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,SAAS;SACvB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,uBAAuB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;SACxD,MAAM,CAAC,CAAC,WAAW,EAAyB,EAAE,CAAC,WAAW,KAAK,SAAS,CAAC,CAAA;IAC5E,MAAM,WAAW,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAA;IACjD,MAAM,MAAM,GAAG,uBAAuB,CAAC,SAAS,CAAC,CAAA;IACjD,OAAO;QACL,iBAAiB;QACjB,EAAE;QACF,qBAAqB;QACrB,EAAE;QACF,qCAAqC,SAAS,CAAC,MAAM,EAAE;QACvD,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAC,4BAA4B,WAAW,EAAE;QAC1G,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,6CAA6C,CAAC,CAAC,CAAC,iCAAiC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAC1H,oKAAoK;QACpK,4GAA4G;KAC7G,CAAA;AACH,CAAC;AAED,SAAS,eAAe,CAAC,UAAkB;IACzC,MAAM,oBAAoB,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAA;IAC3D,OAAO;QACL,+BAA+B;QAC/B,EAAE;QACF,mBAAmB;QACnB,eAAe;QACf,EAAE;QACF,WAAW;QACX,EAAE;QACF,GAAG,WAAW,CAAC,UAAU,CAAC;QAC1B,EAAE;QACF,GAAG,mBAAmB,CAAC,UAAU,CAAC;QAClC,GAAG,CAAC,oBAAoB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,EAAE;QACF,GAAG,gBAAgB,CAAC,UAAU,CAAC;QAC/B,EAAE;QACF,mCAAmC;QACnC,EAAE;QACF,yCAAyC;QACzC,2CAA2C;QAC3C,8BAA8B;QAC9B,yDAAyD;QACzD,8CAA8C;QAC9C,EAAE;QACF,cAAc;QACd,EAAE;QACF,0BAA0B;QAC1B,0CAA0C;QAC1C,iCAAiC;QACjC,yBAAyB;QACzB,gCAAgC;QAChC,EAAE;QACF,eAAe;QACf,EAAE;QACF,0EAA0E;QAC1E,uCAAuC;QACvC,wGAAwG;QACxG,iEAAiE;QACjE,wDAAwD;QACxD,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC;AAED,SAAS,kCAAkC,CAAC,UAAkB;IAC5D,OAAO;QACL,+BAA+B;QAC/B,EAAE;QACF,eAAe;QACf,kBAAkB;QAClB,EAAE;QACF,WAAW;QACX,EAAE;QACF,GAAG,WAAW,CAAC,UAAU,CAAC;QAC1B,EAAE;QACF,0CAA0C;QAC1C,EAAE;QACF,kBAAkB;QAClB,EAAE;QACF,uBAAuB;QACvB,uBAAuB;QACvB,qBAAqB;QACrB,qBAAqB;QACrB,+BAA+B;QAC/B,+BAA+B;QAC/B,yBAAyB;QACzB,kBAAkB;QAClB,wBAAwB;QACxB,EAAE;QACF,sBAAsB;QACtB,EAAE;QACF,+BAA+B;QAC/B,kCAAkC;QAClC,yBAAyB;QACzB,EAAE;QACF,iBAAiB;QACjB,EAAE;QACF,sCAAsC;QACtC,uCAAuC;QACvC,0EAA0E;QAC1E,sGAAsG;QACtG,0GAA0G;QAC1G,6DAA6D;QAC7D,EAAE;QACF,cAAc;QACd,EAAE;QACF,uDAAuD;QACvD,yDAAyD;QACzD,gDAAgD;QAChD,EAAE;QACF,qBAAqB;QACrB,EAAE;QACF,8DAA8D;QAC9D,EAAE;QACF,UAAU;QACV,EAAE;QACF,eAAe;QACf,UAAU;QACV,EAAE;QACF,iBAAiB;QACjB,EAAE;QACF,oCAAoC;QACpC,sBAAsB;QACtB,sBAAsB;QACtB,aAAa;QACb,sBAAsB;QACtB,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC;AAED,SAAS,0BAA0B,CAAC,UAAkB;IACpD,OAAO;QACL,uBAAuB;QACvB,EAAE;QACF,eAAe;QACf,kBAAkB;QAClB,EAAE;QACF,WAAW;QACX,EAAE;QACF,GAAG,WAAW,CAAC,UAAU,CAAC;QAC1B,EAAE;QACF,0CAA0C;QAC1C,qEAAqE;QACrE,EAAE;QACF,uBAAuB;QACvB,EAAE;QACF,sEAAsE;QACtE,iCAAiC;QACjC,2BAA2B;QAC3B,EAAE;QACF,oBAAoB;QACpB,EAAE;QACF,4DAA4D;QAC5D,+CAA+C;QAC/C,4DAA4D;QAC5D,0DAA0D;QAC1D,4CAA4C;QAC5C,EAAE;QACF,wBAAwB;QACxB,EAAE;QACF,gDAAgD;QAChD,iDAAiD;QACjD,uEAAuE;QACvE,oHAAoH;QACpH,gEAAgE;QAChE,EAAE;QACF,qBAAqB;QACrB,EAAE;QACF,sDAAsD;QACtD,EAAE;QACF,qBAAqB;QACrB,EAAE;QACF,sDAAsD;QACtD,WAAW;QACX,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC;AAED,SAAS,qBAAqB,CAAC,UAAkB;IAC/C,OAAO,CAAC,SAAS,EAAE,0BAA0B,EAAE,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;AACzH,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,UAAuB,EAAE,EAAE,KAAK,GAAG,KAAK;IAC7E,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;IAC/D,MAAM,YAAY,GAAG,8BAA8B,CAAC,UAAU,CAAC,CAAA;IAC/D,IAAI,YAAY,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QACpC,MAAM,IAAI,cAAc,CACtB;YACE,8CAA8C;YAC9C,YAAY,CAAC,OAAO;YACpB,2DAA2D;YAC3D,yDAAyD;SAC1D,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAA;IACH,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC,CAAA;IAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;IAC5C,MAAM,wBAAwB,GAAG,IAAI,CAAC,UAAU,EAAE,0BAA0B,CAAC,CAAA;IAC7E,MAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAA;IAE7D,MAAM,aAAa,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAA;IACvD,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACvC,MAAM,IAAI,cAAc,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,6DAA6D,CAAC,CAAA;IACpH,CAAC;IAED,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC3C,aAAa,CAAC,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC,CAAA;IACpD,aAAa,CAAC,wBAAwB,EAAE,kCAAkC,CAAC,UAAU,CAAC,CAAC,CAAA;IACvF,aAAa,CAAC,gBAAgB,EAAE,0BAA0B,CAAC,UAAU,CAAC,CAAC,CAAA;IACvE,OAAO,QAAQ,CAAA;AACjB,CAAC"}
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
1
3
|
import { readBackendProjectProfileState } from "../phase0/project-profile.js";
|
|
2
|
-
import {
|
|
4
|
+
import { runResumeCommand } from "./plan-next.js";
|
|
5
|
+
import { failedGuardOutput, failedRunnerOutput, passedFinishOutput, passedGuardOutput, passedImplementOutput, passedStartOutput, uninitializedHarnessOutput, } from "./workflow-output.js";
|
|
3
6
|
import { formatWorkflowStatus, readWorkflowStatus } from "./workflow-status.js";
|
|
4
7
|
export function workflowUsage(invocation = "ph") {
|
|
5
8
|
return [
|
|
6
|
-
`Usage: ${invocation} workflow <check|implement|start implement|finish implement|guard implement|guard final>`,
|
|
9
|
+
`Usage: ${invocation} workflow <check|implement|continue|start implement|finish implement|guard implement|guard final>`,
|
|
7
10
|
"",
|
|
8
11
|
"Checks or guards Persona Harness workflow artifacts before or after implementation.",
|
|
9
12
|
"",
|
|
10
13
|
"Scope:",
|
|
11
14
|
"- workflow check is report-only",
|
|
12
15
|
"- workflow implement prints a single AI-facing implementation rail",
|
|
16
|
+
"- workflow continue prints the accepted-plan continuation prompt",
|
|
13
17
|
"- workflow start/finish are AI-facing workflow rails",
|
|
14
18
|
"- workflow guard uses strict exit codes for AI-facing workflow discipline",
|
|
15
19
|
"- no generated app quality certification",
|
|
@@ -22,6 +26,9 @@ function parseWorkflowArgs(args) {
|
|
|
22
26
|
if (args[0] === "implement") {
|
|
23
27
|
return args.length === 1 ? { kind: "implement" } : { kind: "invalid", message: "workflow implement does not accept extra arguments." };
|
|
24
28
|
}
|
|
29
|
+
if (args[0] === "continue") {
|
|
30
|
+
return args.length === 1 ? { kind: "continue" } : { kind: "invalid", message: "workflow continue does not accept extra arguments." };
|
|
31
|
+
}
|
|
25
32
|
if (args[0] === "guard") {
|
|
26
33
|
if (args.length !== 2) {
|
|
27
34
|
return { kind: "invalid", message: "workflow guard requires implement or final." };
|
|
@@ -58,9 +65,17 @@ function implementationGuardReasons(summary) {
|
|
|
58
65
|
const reasons = [];
|
|
59
66
|
const profileState = readBackendProjectProfileState(summary.projectDir);
|
|
60
67
|
if (profileState.status !== "ready") {
|
|
61
|
-
reasons.push(
|
|
68
|
+
reasons.push([
|
|
69
|
+
"Harness initialized but project profile is not ready.",
|
|
70
|
+
profileState.message,
|
|
71
|
+
"Fast path: run npx ph bootstrap backend.",
|
|
72
|
+
"Manual path: run npx ph intake --default backend or npx ph intake --interactive.",
|
|
73
|
+
].join(" "));
|
|
62
74
|
}
|
|
63
|
-
if (summary.plan
|
|
75
|
+
if (summary.plan === "missing") {
|
|
76
|
+
reasons.push(".persona/workflow/plan.md is missing. Run npx ph bootstrap backend or npx ph plan --auto-accept.");
|
|
77
|
+
}
|
|
78
|
+
else if (summary.plan !== "accepted") {
|
|
64
79
|
reasons.push(".persona/workflow/plan.md must be accepted");
|
|
65
80
|
}
|
|
66
81
|
if (summary.implementation === "missing") {
|
|
@@ -93,8 +108,14 @@ function finalGuardReasons(summary) {
|
|
|
93
108
|
}
|
|
94
109
|
return reasons;
|
|
95
110
|
}
|
|
111
|
+
function hasPersonaHarness(summary) {
|
|
112
|
+
return existsSync(join(summary.projectDir, ".persona"));
|
|
113
|
+
}
|
|
96
114
|
function runWorkflowGuard(guardKind, options) {
|
|
97
115
|
const summary = readWorkflowStatus(options.projectDir);
|
|
116
|
+
if (!hasPersonaHarness(summary)) {
|
|
117
|
+
return uninitializedHarnessOutput();
|
|
118
|
+
}
|
|
98
119
|
const reasons = guardKind === "implement" ? implementationGuardReasons(summary) : finalGuardReasons(summary);
|
|
99
120
|
if (reasons.length > 0) {
|
|
100
121
|
return failedGuardOutput(guardKind, reasons);
|
|
@@ -103,6 +124,9 @@ function runWorkflowGuard(guardKind, options) {
|
|
|
103
124
|
}
|
|
104
125
|
function runWorkflowStart(runnerKind, options) {
|
|
105
126
|
const summary = readWorkflowStatus(options.projectDir);
|
|
127
|
+
if (!hasPersonaHarness(summary)) {
|
|
128
|
+
return uninitializedHarnessOutput();
|
|
129
|
+
}
|
|
106
130
|
const reasons = implementationGuardReasons(summary);
|
|
107
131
|
if (reasons.length > 0) {
|
|
108
132
|
return failedRunnerOutput("start", runnerKind, reasons);
|
|
@@ -111,6 +135,9 @@ function runWorkflowStart(runnerKind, options) {
|
|
|
111
135
|
}
|
|
112
136
|
function runWorkflowImplement(options) {
|
|
113
137
|
const summary = readWorkflowStatus(options.projectDir);
|
|
138
|
+
if (!hasPersonaHarness(summary)) {
|
|
139
|
+
return uninitializedHarnessOutput();
|
|
140
|
+
}
|
|
114
141
|
const reasons = implementationGuardReasons(summary);
|
|
115
142
|
if (reasons.length > 0) {
|
|
116
143
|
return failedRunnerOutput("implement", "implement", reasons);
|
|
@@ -119,6 +146,9 @@ function runWorkflowImplement(options) {
|
|
|
119
146
|
}
|
|
120
147
|
function runWorkflowFinish(runnerKind, options) {
|
|
121
148
|
const summary = readWorkflowStatus(options.projectDir);
|
|
149
|
+
if (!hasPersonaHarness(summary)) {
|
|
150
|
+
return uninitializedHarnessOutput();
|
|
151
|
+
}
|
|
122
152
|
const reasons = finalGuardReasons(summary);
|
|
123
153
|
if (reasons.length > 0) {
|
|
124
154
|
return failedRunnerOutput("finish", runnerKind, reasons);
|
|
@@ -139,6 +169,9 @@ export function runWorkflowCommand(args, options = {}, invocationName = "ph") {
|
|
|
139
169
|
if (parsed.kind === "implement") {
|
|
140
170
|
return runWorkflowImplement(options);
|
|
141
171
|
}
|
|
172
|
+
if (parsed.kind === "continue") {
|
|
173
|
+
return runResumeCommand(options);
|
|
174
|
+
}
|
|
142
175
|
if (parsed.kind === "start") {
|
|
143
176
|
return runWorkflowStart(parsed.runnerKind, options);
|
|
144
177
|
}
|