phasegate 0.160.12 → 0.160.13
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/README.md +9 -0
- package/docs/guide/getting-started.md +1 -0
- package/docs/guide/installation.md +9 -0
- package/docs/guide/recipes.md +9 -0
- package/docs/guide/setup-artifacts.md +1 -0
- package/docs/templates/personal/git-info-exclude +6 -0
- package/docs/templates/personal/phasegate-local-config.json +7 -0
- package/package.json +1 -1
- package/scripts/harness/installation/application/usecases/run-install.ts +50 -3
- package/scripts/harness/installation/application/usecases/run-uninstall.ts +11 -1
- package/scripts/harness/installation/presentation/cli/install-handler.ts +3 -1
- package/scripts/harness/main.ts +7 -4
- package/skills/README.md +2 -0
- package/skills/phasegate-config-doctor/SKILL.md +3 -0
- package/skills/phasegate-toolkit-guide/SKILL.md +2 -0
package/README.md
CHANGED
|
@@ -102,6 +102,15 @@ npx phasegate doctor
|
|
|
102
102
|
|
|
103
103
|
`install` merges PhaseGate into the current project without discarding existing Claude/Codex hooks or Husky scripts. It reports planned changes before writing, adds package scripts and the `phasegate` devDependency, creates agent skill links, writes `AGENTS.md` / `CLAUDE.md` PhaseGate managed sections for the selected agent targets, writes the CI workflow when missing, and records managed files in `.phasegate/manifest.json`. If an existing file needs a forced managed update, run `npx phasegate install --apply --force`; PhaseGate backs up replaced files under `.phasegate/backups/`. <!-- @work-item-id WI-174 -->
|
|
104
104
|
|
|
105
|
+
For personal evaluation inside a team-owned repository, use local-only install:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
npx phasegate install --personal --dry-run
|
|
109
|
+
npx phasegate install --personal --apply
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`--personal` does not plan or write `package.json`, `AGENTS.md`, `CLAUDE.md`, `.husky/*`, `.github/workflows/*`, or `.gitignore`. It creates `.phasegate-local/config.json`, adds a managed local-only block to `.git/info/exclude`, records personal artifacts in `.phasegate/manifest.json`, and reports Codex user-level hook setup as a manual action instead of writing `.codex/hooks.json`. <!-- @work-item-id WI-207 -->
|
|
113
|
+
|
|
105
114
|
For agent-driven setup planning, use:
|
|
106
115
|
|
|
107
116
|
```bash
|
|
@@ -12,6 +12,7 @@ Start with one question: what kind of repository are you setting up?
|
|
|
12
12
|
|---|---|---|
|
|
13
13
|
| New project with agent hooks | `npx phasegate init --name <project> --agent both --with-husky --with-ci` | `phasegate.config.json`, skills, hooks, agent context files, Husky, and CI targets exist |
|
|
14
14
|
| Existing repository | `npx phasegate install --dry-run` then `npx phasegate install --apply` | Existing hooks/scripts are preserved and `.phasegate/manifest.json` records managed targets |
|
|
15
|
+
| Personal evaluation in a team repository | `npx phasegate install --personal --dry-run` then `npx phasegate install --personal --apply` | Team-owned files stay untouched; `.phasegate-local/config.json` and `.git/info/exclude` local-only entries are recorded |
|
|
15
16
|
| CI-only rollout | `npx phasegate setup:agent --intent ci-only --with-ci --dry-run --json` | The plan explains CI changes without requiring local hooks |
|
|
16
17
|
| Codex-only project | `npx phasegate init --agent codex --with-husky` | `.codex/hooks.json`, `AGENTS.md`, `.codex/skills`, and pre-commit backstop are present |
|
|
17
18
|
| Strict validation rollout | `npx phasegate setup:agent --intent strict --dry-run --json` | The plan lists strict checks, L4 risk, rollback, and validation commands |
|
|
@@ -58,6 +58,15 @@ npx phasegate doctor
|
|
|
58
58
|
|
|
59
59
|
`install --dry-run` reports whether each target will be created, merged, skipped, or refused. `install --apply` performs the merge, adds package scripts and the `phasegate` devDependency, creates `.claude/skills` and `.codex/skills` links, writes `CLAUDE.md` / `AGENTS.md` managed sections for selected agent targets, writes `.github/workflows/phasegate-aidlc-gate.yml` when CI is enabled, and records managed entries in `.phasegate/manifest.json`. See [Setup Artifacts](setup-artifacts.md) for the full managed target, generated artifact, runtime state, legacy artifact, and user-level setting inventory. <!-- @work-item-id WI-152 --> <!-- @work-item-id WI-169 --> <!-- @work-item-id WI-174 -->
|
|
60
60
|
|
|
61
|
+
For personal evaluation inside a team-owned repository:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npx phasegate install --personal --dry-run
|
|
65
|
+
npx phasegate install --personal --apply
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Personal install keeps team-owned files out of both the plan and apply path: `package.json`, `AGENTS.md`, `CLAUDE.md`, `.husky/*`, `.github/workflows/*`, and `.gitignore` are not touched. PhaseGate writes only local artifacts: `.phasegate-local/config.json`, `.phasegate/manifest.json`, and a managed block in `.git/info/exclude`. Codex user-level hook setup is reported as a manual action instead of writing project-local `.codex/hooks.json`. <!-- @work-item-id WI-207 -->
|
|
69
|
+
|
|
61
70
|
For agent-readable planning before writing files:
|
|
62
71
|
|
|
63
72
|
```bash
|
package/docs/guide/recipes.md
CHANGED
|
@@ -24,6 +24,15 @@ npx phasegate baseline --dry-run
|
|
|
24
24
|
|
|
25
25
|
Use this when a repository already has meaningful history or custom automation. Treat any refused target as an agent-assisted review task instead of forcing it blindly.
|
|
26
26
|
|
|
27
|
+
## Personal Evaluation Recipe
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx phasegate install --personal --dry-run
|
|
31
|
+
npx phasegate install --personal --apply
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Use this inside a team-owned repository when you want local PhaseGate artifacts without changing `package.json`, agent context files, Husky hooks, CI workflows, or team `.gitignore`. <!-- @work-item-id WI-207 -->
|
|
35
|
+
|
|
27
36
|
## Agent Hooks Recipe
|
|
28
37
|
|
|
29
38
|
```bash
|
|
@@ -14,6 +14,7 @@ PhaseGate setup is more than `phasegate.config.json`. A healthy installation is
|
|
|
14
14
|
| Configuration | `phasegate.config.json`, `package.json` | User owned, PhaseGate assisted | Created by `init`; `install` may merge scripts/devDependency into `package.json` |
|
|
15
15
|
| Generated artifact | `.phasegate/manifest.json`, `.phasegate/backups/*`, `.phasegate/uninstalled-*.json`, `.phasegate/baseline.json` | PhaseGate | Written by lifecycle commands and validators; safe to regenerate only through the owning command |
|
|
16
16
|
| Runtime state/report | `.phasegate/hook-skip-events.jsonl`, explicit `doctor --report-out <path>` output, `reports/regression/*`, resolved `reporting.outputDir` reports | PhaseGate command output | Produced while hooks, doctor, and validation commands run |
|
|
17
|
+
| Personal install artifact | `.phasegate-local/config.json`, `.git/info/exclude` PhaseGate block | One developer on one machine | Created by `phasegate install --personal`; team `.gitignore` and team-owned files are not modified |
|
|
17
18
|
| Legacy artifact | `.harness-hooks.yml`, old Fuse hook files, `.harness/session-state.json`, `.harness/context-priority.json`, `.harness/reports` fallback | Compatibility only | Not required for current install lifecycle unless a project intentionally keeps an archived integration |
|
|
18
19
|
| User-level setting | Codex CLI `hooks` feature flag | User machine | Must be enabled manually with `codex features enable hooks`; project commands do not modify it |
|
|
19
20
|
|
package/package.json
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
// @work-item-id WI-177
|
|
8
8
|
// @work-item-id WI-182
|
|
9
9
|
// @work-item-id WI-183
|
|
10
|
+
// @work-item-id WI-207
|
|
10
11
|
|
|
11
12
|
import { mkdir, readFile, writeFile, copyFile, chmod, access, lstat, readlink, symlink } from "node:fs/promises";
|
|
12
13
|
import { dirname, join } from "node:path";
|
|
@@ -18,7 +19,7 @@ import type { ManifestRepositoryPort } from "../ports/manifest-repository-port.j
|
|
|
18
19
|
import type { HashCalculatorPort } from "../ports/hash-calculator-port.js";
|
|
19
20
|
|
|
20
21
|
type InstallAction = "missing" | "will-merge" | "will-skip" | "will-overwrite";
|
|
21
|
-
type StrategyType = "json" | "shell" | "yaml-add" | "package-json" | "markdown-managed";
|
|
22
|
+
type StrategyType = "json" | "shell" | "yaml-add" | "package-json" | "markdown-managed" | "text-managed" | "copy";
|
|
22
23
|
|
|
23
24
|
export interface InstallPlanItem {
|
|
24
25
|
readonly path: string;
|
|
@@ -45,6 +46,7 @@ export interface RunInstallInput {
|
|
|
45
46
|
readonly skillSet?: "core" | "all";
|
|
46
47
|
readonly workflow?: "standard" | "strict";
|
|
47
48
|
readonly agent?: "claude" | "codex" | "both";
|
|
49
|
+
readonly personal?: boolean;
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
export interface RunInstallResult {
|
|
@@ -79,6 +81,8 @@ const SHELL_BEGIN = "# === phasegate managed (BEGIN) ===";
|
|
|
79
81
|
const SHELL_END = "# === phasegate managed (END) ===";
|
|
80
82
|
const MARKDOWN_BEGIN = "<!-- phasegate:managed-section:start -->";
|
|
81
83
|
const MARKDOWN_END = "<!-- phasegate:managed-section:end -->";
|
|
84
|
+
const TEXT_BEGIN = "# phasegate personal install exclude (BEGIN)";
|
|
85
|
+
const TEXT_END = "# phasegate personal install exclude (END)";
|
|
82
86
|
|
|
83
87
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
84
88
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -152,6 +156,14 @@ function mergeShell(existing: string | null, incoming: string): string {
|
|
|
152
156
|
return `${existing.replace(/\s*$/, "\n\n")}${block}\n`;
|
|
153
157
|
}
|
|
154
158
|
|
|
159
|
+
function mergeTextManaged(existing: string | null, incoming: string): string {
|
|
160
|
+
const block = `${TEXT_BEGIN}\n${incoming.trim()}\n${TEXT_END}`;
|
|
161
|
+
if (existing === null || existing.trim().length === 0) return `${block}\n`;
|
|
162
|
+
const pattern = new RegExp(`${escapeRegExp(TEXT_BEGIN)}[\\s\\S]*?${escapeRegExp(TEXT_END)}`);
|
|
163
|
+
if (pattern.test(existing)) return existing.replace(pattern, block).replace(/\s*$/, "\n");
|
|
164
|
+
return `${existing.replace(/\s*$/, "\n\n")}${block}\n`;
|
|
165
|
+
}
|
|
166
|
+
|
|
155
167
|
function managedMarkdownBlock(content: string): string {
|
|
156
168
|
const start = content.indexOf(MARKDOWN_BEGIN);
|
|
157
169
|
const end = content.indexOf(MARKDOWN_END);
|
|
@@ -282,7 +294,9 @@ export class RunInstallUseCase {
|
|
|
282
294
|
const skillSet = input.skillSet ?? "all";
|
|
283
295
|
const workflow = input.workflow ?? "standard";
|
|
284
296
|
const agent = input.agent ?? (includeClaude && includeCodex ? "both" : includeCodex ? "codex" : "claude");
|
|
285
|
-
const targets =
|
|
297
|
+
const targets = input.personal
|
|
298
|
+
? this.createPersonalTargets()
|
|
299
|
+
: this.createTargets({ includeClaude, includeCodex, includeHusky, includeCi });
|
|
286
300
|
const existingManifest = await this.manifestRepository.load(input.projectRoot);
|
|
287
301
|
const baseManifest = existingManifest ?? DeploymentManifest.create(input.phasegateVersion);
|
|
288
302
|
let manifest = baseManifest;
|
|
@@ -363,7 +377,7 @@ export class RunInstallUseCase {
|
|
|
363
377
|
}
|
|
364
378
|
}
|
|
365
379
|
|
|
366
|
-
const linkPaths = [
|
|
380
|
+
const linkPaths = input.personal ? [] : [
|
|
367
381
|
...(includeClaude ? [".claude/skills"] : []),
|
|
368
382
|
...(includeCodex ? [".codex/skills"] : []),
|
|
369
383
|
];
|
|
@@ -400,6 +414,19 @@ export class RunInstallUseCase {
|
|
|
400
414
|
}
|
|
401
415
|
}
|
|
402
416
|
|
|
417
|
+
if (input.personal && includeCodex) {
|
|
418
|
+
plan.push({
|
|
419
|
+
path: "~/.codex/hooks.json",
|
|
420
|
+
action: "will-skip",
|
|
421
|
+
repairMode: "manual",
|
|
422
|
+
strategy: "json",
|
|
423
|
+
changed: false,
|
|
424
|
+
summary: "~/.codex/hooks.json: personal mode does not write user-level Codex settings; configure hooks manually",
|
|
425
|
+
diff: "manual user-level Codex hook setup required",
|
|
426
|
+
skillHint: null,
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
|
|
403
430
|
if (input.apply && changed.length > 0) {
|
|
404
431
|
try {
|
|
405
432
|
await this.manifestRepository.save(input.projectRoot, manifest);
|
|
@@ -498,8 +525,26 @@ export class RunInstallUseCase {
|
|
|
498
525
|
];
|
|
499
526
|
}
|
|
500
527
|
|
|
528
|
+
private createPersonalTargets(): readonly InstallTarget[] {
|
|
529
|
+
return [
|
|
530
|
+
{
|
|
531
|
+
path: ".phasegate-local/config.json",
|
|
532
|
+
strategy: "copy" as const,
|
|
533
|
+
templatePath: "docs/templates/personal/phasegate-local-config.json",
|
|
534
|
+
},
|
|
535
|
+
{
|
|
536
|
+
path: ".git/info/exclude",
|
|
537
|
+
strategy: "text-managed" as const,
|
|
538
|
+
templatePath: "docs/templates/personal/git-info-exclude",
|
|
539
|
+
block: { start: TEXT_BEGIN, end: TEXT_END, content: "phasegate personal install exclude block" },
|
|
540
|
+
},
|
|
541
|
+
];
|
|
542
|
+
}
|
|
543
|
+
|
|
501
544
|
private repairMode(target: InstallTarget, before: string | null): RepairMode {
|
|
502
545
|
if (target.strategy === "shell") return shellRepairMode(before);
|
|
546
|
+
if (target.strategy === "text-managed") return "mechanical";
|
|
547
|
+
if (target.strategy === "copy") return "mechanical";
|
|
503
548
|
if (target.strategy === "json") return jsonRepairMode(before);
|
|
504
549
|
if (target.strategy === "markdown-managed") return "mechanical";
|
|
505
550
|
return "mechanical";
|
|
@@ -513,7 +558,9 @@ export class RunInstallUseCase {
|
|
|
513
558
|
|
|
514
559
|
private merge(target: InstallTarget, before: string | null, template: string, version: string): string {
|
|
515
560
|
if (target.strategy === "yaml-add") return before ?? template;
|
|
561
|
+
if (target.strategy === "copy") return before ?? template;
|
|
516
562
|
if (target.strategy === "shell") return mergeShell(before, template);
|
|
563
|
+
if (target.strategy === "text-managed") return mergeTextManaged(before, template);
|
|
517
564
|
if (target.strategy === "markdown-managed") return mergeManagedMarkdown(before, template);
|
|
518
565
|
if (target.strategy === "package-json") {
|
|
519
566
|
const existing = before === null ? {} : (JSON.parse(before) as unknown);
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// @work-item-id WI-147
|
|
4
4
|
// @work-item-id WI-174
|
|
5
5
|
// @work-item-id WI-199
|
|
6
|
+
// @work-item-id WI-207
|
|
6
7
|
|
|
7
8
|
import { access, copyFile, lstat, mkdir, readFile, readlink, rm, rmdir, writeFile } from "node:fs/promises";
|
|
8
9
|
import { dirname, join, relative, resolve } from "node:path";
|
|
@@ -12,7 +13,7 @@ import type { HashCalculatorPort } from "../ports/hash-calculator-port.js";
|
|
|
12
13
|
import type { ManifestRepositoryPort } from "../ports/manifest-repository-port.js";
|
|
13
14
|
|
|
14
15
|
type UninstallAction = "missing-manifest" | "delete" | "unlink" | "reverse-merge" | "skip" | "refuse";
|
|
15
|
-
type StrategyType = "created" | "json" | "shell" | "package-json" | "markdown-managed" | "symlink" | "yaml-add" | "unknown";
|
|
16
|
+
type StrategyType = "created" | "json" | "shell" | "package-json" | "markdown-managed" | "symlink" | "yaml-add" | "text-managed" | "unknown";
|
|
16
17
|
|
|
17
18
|
export interface UninstallPlanItem {
|
|
18
19
|
readonly path: string;
|
|
@@ -47,6 +48,8 @@ const SHELL_BEGIN = "# === phasegate managed (BEGIN) ===";
|
|
|
47
48
|
const SHELL_END = "# === phasegate managed (END) ===";
|
|
48
49
|
const MARKDOWN_BEGIN = "<!-- phasegate:managed-section:start -->";
|
|
49
50
|
const MARKDOWN_END = "<!-- phasegate:managed-section:end -->";
|
|
51
|
+
const TEXT_BEGIN = "# phasegate personal install exclude (BEGIN)";
|
|
52
|
+
const TEXT_END = "# phasegate personal install exclude (END)";
|
|
50
53
|
const PHASEGATE_SCRIPT_PREFIX = "phasegate:";
|
|
51
54
|
const PROTECTED_UNINSTALL_PATHS = new Set(["package.json", "package-lock.json"]);
|
|
52
55
|
|
|
@@ -119,6 +122,11 @@ export function reverseManagedMarkdown(currentContent: string): string {
|
|
|
119
122
|
return currentContent.replace(pattern, "\n").replace(/\n{3,}/g, "\n\n").replace(/\s*$/, "\n").replace(/^\n/, "");
|
|
120
123
|
}
|
|
121
124
|
|
|
125
|
+
export function reverseTextManaged(currentContent: string): string {
|
|
126
|
+
const pattern = new RegExp(`\\n?${escapeRegExp(TEXT_BEGIN)}[\\s\\S]*?${escapeRegExp(TEXT_END)}\\n?`);
|
|
127
|
+
return currentContent.replace(pattern, "\n").replace(/\n{3,}/g, "\n\n").replace(/\s*$/, "\n").replace(/^\n/, "");
|
|
128
|
+
}
|
|
129
|
+
|
|
122
130
|
export function reversePackageJsonMerge(currentContent: string): string {
|
|
123
131
|
const parsed = JSON.parse(currentContent) as unknown;
|
|
124
132
|
const result = isRecord(parsed) ? { ...parsed } : {};
|
|
@@ -312,6 +320,7 @@ export class RunUninstallUseCase {
|
|
|
312
320
|
private async reverseMerged(harnessRoot: string, path: string, currentContent: string, strategy: StrategyType): Promise<string> {
|
|
313
321
|
if (strategy === "shell") return currentContent.includes(SHELL_BEGIN) ? reverseShellMerge(currentContent) : currentContent;
|
|
314
322
|
if (strategy === "markdown-managed") return currentContent.includes(MARKDOWN_BEGIN) ? reverseManagedMarkdown(currentContent) : currentContent;
|
|
323
|
+
if (strategy === "text-managed") return currentContent.includes(TEXT_BEGIN) ? reverseTextManaged(currentContent) : currentContent;
|
|
315
324
|
if (strategy === "package-json") return reversePackageJsonMerge(currentContent);
|
|
316
325
|
if (strategy === "json") return reverseJsonMerge(currentContent, await readFile(join(harnessRoot, this.templateFor(path)), "utf8"));
|
|
317
326
|
throw new Error(`Unsupported merged strategy: ${strategy}`);
|
|
@@ -322,6 +331,7 @@ export class RunUninstallUseCase {
|
|
|
322
331
|
if (mode === "created") return path.endsWith(".yml") || path.endsWith(".yaml") ? "yaml-add" : "created";
|
|
323
332
|
if (path === "package.json") return "package-json";
|
|
324
333
|
if (path === "AGENTS.md" || path === "CLAUDE.md") return "markdown-managed";
|
|
334
|
+
if (path === ".git/info/exclude") return "text-managed";
|
|
325
335
|
if (path.endsWith(".json")) return "json";
|
|
326
336
|
if (path.startsWith(".husky/")) return "shell";
|
|
327
337
|
return "unknown";
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// @layer presentation
|
|
3
3
|
// @work-item-id WI-146
|
|
4
4
|
// @work-item-id WI-175
|
|
5
|
+
// @work-item-id WI-207
|
|
5
6
|
|
|
6
7
|
import type { RunInstallUseCase } from "../../application/usecases/run-install.js";
|
|
7
8
|
|
|
@@ -20,6 +21,7 @@ export interface InstallHandlerInput {
|
|
|
20
21
|
readonly skillSet?: "core" | "all";
|
|
21
22
|
readonly workflow?: "standard" | "strict";
|
|
22
23
|
readonly agent?: "claude" | "codex" | "both";
|
|
24
|
+
readonly personal?: boolean;
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
export interface InstallHandlerResult {
|
|
@@ -39,7 +41,7 @@ export class InstallHandler {
|
|
|
39
41
|
};
|
|
40
42
|
}
|
|
41
43
|
const lines = [
|
|
42
|
-
input.apply ?
|
|
44
|
+
input.apply ? `phasegate install${input.personal ? " --personal" : ""} apply` : `phasegate install${input.personal ? " --personal" : ""} dry-run`,
|
|
43
45
|
...result.plan.map((item) => {
|
|
44
46
|
const hint = item.skillHint ? `; hint: ${item.skillHint}` : "";
|
|
45
47
|
return `- ${item.path}: ${item.action} (${item.repairMode}, ${item.strategy}); diff: ${item.diff}${hint}`;
|
package/scripts/harness/main.ts
CHANGED
|
@@ -171,7 +171,7 @@ Setup:
|
|
|
171
171
|
scaffold-wi <unit|_cross> <story|issue|chore>
|
|
172
172
|
Create docs/inception/{unit}/WI-XXX/description.md
|
|
173
173
|
emit-agent-rules Print AGENTS.md / CLAUDE.md WI workflow rules block
|
|
174
|
-
install Install phasegate managed files (--dry-run|--apply, --force)
|
|
174
|
+
install Install phasegate managed files (--dry-run|--apply, --force, --personal)
|
|
175
175
|
uninstall Uninstall phasegate managed files (--dry-run|--apply, --force)
|
|
176
176
|
reconcile Reconcile phasegate managed files (--dry-run|--apply, --force)
|
|
177
177
|
setup:agent Diagnose repo setup and produce/apply an agent-readable setup plan
|
|
@@ -625,6 +625,7 @@ Options:
|
|
|
625
625
|
--workflow <standard|strict> Rendered agent context workflow mode (default: standard)
|
|
626
626
|
--with-husky Include Husky hook targets
|
|
627
627
|
--with-ci Include GitHub Actions target
|
|
628
|
+
--personal Use local-only install: no package.json, agent docs, Husky, CI, or .gitignore writes
|
|
628
629
|
--json Output machine-readable JSON
|
|
629
630
|
--help, -h Show this help`,
|
|
630
631
|
"setup:agent": `Usage: phasegate setup:agent [options]
|
|
@@ -2045,7 +2046,7 @@ async function main(): Promise<void> {
|
|
|
2045
2046
|
}
|
|
2046
2047
|
|
|
2047
2048
|
case "install": {
|
|
2048
|
-
const KNOWN_INSTALL_FLAGS = ["--dry-run", "--apply", "--force", "--json", "--agent", "--skills", "--workflow", "--with-husky", "--with-ci"];
|
|
2049
|
+
const KNOWN_INSTALL_FLAGS = ["--dry-run", "--apply", "--force", "--json", "--agent", "--skills", "--workflow", "--with-husky", "--with-ci", "--personal"];
|
|
2049
2050
|
const flagError = validateKnownFlags(args, KNOWN_INSTALL_FLAGS);
|
|
2050
2051
|
if (flagError) {
|
|
2051
2052
|
console.error(flagError);
|
|
@@ -2066,6 +2067,7 @@ async function main(): Promise<void> {
|
|
|
2066
2067
|
}
|
|
2067
2068
|
const includeClaude = agent === "claude" || agent === "both";
|
|
2068
2069
|
const includeCodex = agent === "codex" || agent === "both";
|
|
2070
|
+
const personal = hasFlag(args, "--personal");
|
|
2069
2071
|
const mod = createInstallationModule();
|
|
2070
2072
|
const phasegateVersion = await getHarnessVersion(harnessRoot);
|
|
2071
2073
|
const result = await mod.installHandler.execute({
|
|
@@ -2077,11 +2079,12 @@ async function main(): Promise<void> {
|
|
|
2077
2079
|
force: hasFlag(args, "--force"),
|
|
2078
2080
|
includeClaude,
|
|
2079
2081
|
includeCodex,
|
|
2080
|
-
includeHusky: true,
|
|
2081
|
-
includeCi: true,
|
|
2082
|
+
includeHusky: personal ? false : true,
|
|
2083
|
+
includeCi: personal ? false : true,
|
|
2082
2084
|
skillSet: skillSetRaw,
|
|
2083
2085
|
workflow: parseWorkflowMode(workflowRaw),
|
|
2084
2086
|
agent,
|
|
2087
|
+
personal,
|
|
2085
2088
|
json,
|
|
2086
2089
|
});
|
|
2087
2090
|
console.log(result.stdout);
|
package/skills/README.md
CHANGED
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
|
|
17
17
|
`.agent/skills` は旧 setup 由来の互換パスです。新規導入では管理対象にしません。<!-- @work-item-id WI-157 -->
|
|
18
18
|
|
|
19
|
+
`phasegate install --personal` はチーム所有リポジトリでの個人評価用です。このモードでは `.claude/skills` / `.codex/skills` のリンクを作成せず、`.phasegate-local/config.json` と `.git/info/exclude` の local-only managed block だけを扱います。通常の共有導入が必要になった時点で `phasegate install --dry-run` / `phasegate install --apply` を使います。<!-- @work-item-id WI-207 -->
|
|
20
|
+
|
|
19
21
|
## 新しいスキルの追加
|
|
20
22
|
|
|
21
23
|
新しいスキルを追加する場合は、この `skills` ディレクトリに直接追加してください。あわせて `docs/guide/skills-overview.md`、README の skill 数、必要なら `skills/phasegate-toolkit-guide/SKILL.md` の参照先を更新します。シンボリックリンクを通じて、対応エージェントから利用可能になります。<!-- @work-item-id WI-154 -->
|
|
@@ -35,6 +35,8 @@ phasegate を導入した直後の config は単純な default で、実プロ
|
|
|
35
35
|
| hook config | `.claude/scripts/hook-config.json` | 既存 hook 設定確認 |
|
|
36
36
|
| doctor report | 明示された report path、またはユーザーが指定した `.phasegate/last-doctor-report.json` | `repairMode` / `repairHint` / `suggestedSkill` の確認 |
|
|
37
37
|
| manifest | `.phasegate/manifest.json` | install / reconcile / uninstall の managed target と hash 状態確認 |
|
|
38
|
+
| personal config | `.phasegate-local/config.json` | `install --personal` の local-only 設定確認 |
|
|
39
|
+
| git local exclude | `.git/info/exclude` | `install --personal` の repository-local ignore block 確認 |
|
|
38
40
|
| Claude hooks | `.claude/settings.json` | managed hook JSON と user customization の確認 |
|
|
39
41
|
| Codex hooks | `.codex/hooks.json` | managed hook JSON と Codex hook 配線確認 |
|
|
40
42
|
| Husky scripts | `.husky/pre-commit`, `.husky/commit-msg`, `.husky/pre-push` | pre-commit backstop と bypass audit の確認 |
|
|
@@ -127,6 +129,7 @@ product-architect で Unit を作り、いくつかの logical_design を書い
|
|
|
127
129
|
#### 観点 9: setup lifecycle と doctor finding
|
|
128
130
|
|
|
129
131
|
- `phasegate doctor --json` の finding に `repairMode: "ai-assisted"` と `suggestedSkill.skillName = "phasegate-config-doctor"` がある → 本 skill が merge 方針、保持する user content、実行すべき `install --apply` / `--force` / `reconcile --apply` を提案する
|
|
132
|
+
- チーム所有リポジトリで個人評価だけを行う相談では、通常の `install --apply` ではなく `phasegate install --personal --dry-run` を先に提案する。personal install は `package.json`, `AGENTS.md`, `CLAUDE.md`, `.husky/*`, `.github/workflows/*`, `.gitignore`, `.codex/hooks.json`, skill symlink を変更対象にしない。変更対象は `.phasegate-local/config.json`, `.phasegate/manifest.json`, `.git/info/exclude` の managed block に限定し、Codex user-level hook setup は manual action として扱う。<!-- @work-item-id WI-207 -->
|
|
130
133
|
- Claude-only / Codex-only 導入後は `phasegate doctor --agent claude --json` または `phasegate doctor --agent codex --json` を使って selected agent の readiness を読む。`scopedOutFindings` は未選択 agent の `not-applicable` 情報なので、ユーザーがその agent を導入したいと言っていない限り repair 提案にしない。`repairHint: null` / `suggestedSkill: null` は意図的な抑制で、`currentScopeRepairTarget: false` と `repairModeApplicability: "only-if-agent-selected"` は raw `repairMode` が current scope の修復指示ではないという印である。<!-- @work-item-id WI-178, WI-179, WI-180 -->
|
|
131
134
|
- `repairHint` がある mechanical finding → 原則として hint のコマンドを優先し、実行前に対象ファイルと manifest の差分を確認
|
|
132
135
|
- manifest parse error → `.phasegate/manifest.json` を手で修復する前に backup / uninstall / reinstall の選択肢を提示
|
|
@@ -130,6 +130,8 @@ docs/guide/ # phasegate リポジトリ自体 (dogfood)
|
|
|
130
130
|
- 既存プロジェクト導入: `docs/guide/retrofit-adoption.md`
|
|
131
131
|
- setup artifact / doctor finding / legacy artifact: `docs/guide/setup-artifacts.md`
|
|
132
132
|
|
|
133
|
+
チーム所有リポジトリで個人評価だけを行いたい場合は、`docs/guide/installation.md` の personal install セクションを読む。`phasegate install --personal` は `package.json`、`AGENTS.md`、`CLAUDE.md`、`.husky/*`、`.github/workflows/*`、`.gitignore`、`.codex/hooks.json`、skill symlink を変更せず、`.phasegate-local/config.json` と `.git/info/exclude` の managed block を使う。Codex user-level hook setup は manual action として説明する。<!-- @work-item-id WI-207 -->
|
|
134
|
+
|
|
133
135
|
`setup-artifacts.md` は managed target / generated artifact / runtime state / legacy artifact / user-level setting の分類を持つ。`doctor --report-out` は明示 path への出力で、`.phasegate/last-doctor-report.json` は固定生成物ではない点もここを参照する。<!-- @work-item-id WI-153 -->
|
|
134
136
|
|
|
135
137
|
Claude-only / Codex-only setup の確認では、full `phasegate doctor` と scoped doctor を区別する。ユーザーが `setup:agent --agent claude` を選んだ場合は `phasegate doctor --agent claude --json` を優先し、`scopedOutFindings` の Codex finding は「未選択 agent の not-applicable 情報」であり修復対象ではないと説明する。`repairHint: null` / `suggestedSkill: null` は意図的な抑制で、`currentScopeRepairTarget: false` と `repairModeApplicability: "only-if-agent-selected"` は `repairMode` が current scope の修復指示ではないという印である。full doctor は両 agent を導入したい場合の診断として扱う。<!-- @work-item-id WI-178, WI-179, WI-180 -->
|