phasegate 0.160.18 → 0.160.19
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 +1 -1
- package/docs/guide/installation.md +1 -1
- package/docs/guide/setup-artifacts.md +4 -1
- package/docs/templates/personal/git-info-exclude +1 -0
- package/package.json +1 -1
- package/scripts/harness/installation/application/checks/claude-context-missing-check.ts +35 -0
- package/scripts/harness/installation/application/checks/codex-context-missing-check.ts +32 -0
- package/scripts/harness/installation/application/usecases/run-doctor-diagnostics.ts +3 -2
- package/scripts/harness/installation/application/usecases/run-install.ts +12 -7
- package/scripts/harness/installation/application/usecases/run-uninstall.ts +5 -1
- package/scripts/harness/installation/composition-root.ts +5 -0
- package/scripts/harness/installation/domain/check-id.ts +3 -0
- package/scripts/harness/installation/domain/repair-table.ts +3 -0
package/README.md
CHANGED
|
@@ -109,7 +109,7 @@ npx phasegate install --personal --agent claude --dry-run
|
|
|
109
109
|
npx phasegate install --personal --agent claude --apply
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
`--personal` does not plan or write `package.json`, `
|
|
112
|
+
`--personal` does not plan or write `package.json`, `CLAUDE.md`, `.husky/*`, `.github/workflows/*`, `.gitignore`, GitHub CLI config, repo secrets, or CI settings. It creates `.phasegate-local/phasegate.config.json`, runtime-visible local agent context (`.claude/CLAUDE.md` for Claude, and `AGENTS.md` for Codex only when that root file is absent or already PhaseGate-managed), real local-only agent runtime artifacts for the selected agent (`.claude/settings.json` + `.claude/skills/` and/or `.codex/hooks.json` + `.codex/skills/`), local git hooks under `.git/hooks/`, local reference docs under `.phasegate-local/docs/`, a managed local-only block in `.git/info/exclude`, and `.phasegate/manifest.json`. If a team `AGENTS.md` already exists, personal Codex install leaves it unchanged and `doctor --personal --agent codex` reports the remaining context step instead of hiding it behind `AGENTS.override.md`. Codex user-level hook feature enablement remains a manual action. <!-- @work-item-id WI-207 --> <!-- @work-item-id WI-208 --> <!-- @work-item-id WI-209 --> <!-- @work-item-id WI-213 --> <!-- @work-item-id WI-215 -->
|
|
113
113
|
|
|
114
114
|
For agent-driven setup planning, use:
|
|
115
115
|
|
|
@@ -65,7 +65,7 @@ npx phasegate install --personal --agent claude --dry-run
|
|
|
65
65
|
npx phasegate install --personal --agent claude --apply
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
Personal install keeps team-owned files out of
|
|
68
|
+
Personal install keeps team-owned files out of the apply path: `package.json`, `CLAUDE.md`, `.husky/*`, `.github/workflows/*`, `.gitignore`, GitHub CLI config, repo secrets, and CI settings are not touched. PhaseGate writes `.phasegate-local/phasegate.config.json`, creates runtime-visible local agent context (`.claude/CLAUDE.md` for Claude, and `AGENTS.md` for Codex only when that root file is absent or already PhaseGate-managed), creates real local-only agent runtime artifacts for the selected agent (`.claude/settings.json` + `.claude/skills/` and/or `.codex/hooks.json` + `.codex/skills/`), deploys local git hooks under `.git/hooks/`, copies reference docs under `.phasegate-local/docs/`, records `.phasegate/manifest.json`, and manages a local exclude block in `.git/info/exclude`. If a team `AGENTS.md` already exists, personal Codex install leaves it unchanged and `doctor --personal --agent codex` reports the remaining context step instead of hiding it behind `AGENTS.override.md`. Codex user-level hook feature enablement is still reported as a manual action. <!-- @work-item-id WI-207 --> <!-- @work-item-id WI-208 --> <!-- @work-item-id WI-209 --> <!-- @work-item-id WI-213 --> <!-- @work-item-id WI-215 -->
|
|
69
69
|
|
|
70
70
|
If an existing repository keeps design or governance docs outside `docs/`, set `paths.designDocs`, `paths.inceptionDocs`, `paths.principlesDocs`, and `paths.folderRulesDoc` in `phasegate.config.json` before setup/reconcile. PhaseGate deploy and hook protection use those mappings instead of forcing the default `docs/` layout. <!-- @work-item-id WI-214 -->
|
|
71
71
|
|
|
@@ -7,6 +7,7 @@ PhaseGate setup is more than `phasegate.config.json`. A healthy installation is
|
|
|
7
7
|
<!-- @work-item-id WI-169 -->
|
|
8
8
|
<!-- @work-item-id WI-208 -->
|
|
9
9
|
<!-- @work-item-id WI-209 -->
|
|
10
|
+
<!-- @work-item-id WI-215 -->
|
|
10
11
|
|
|
11
12
|
## Artifact Classes
|
|
12
13
|
|
|
@@ -16,7 +17,7 @@ PhaseGate setup is more than `phasegate.config.json`. A healthy installation is
|
|
|
16
17
|
| Configuration | `phasegate.config.json`, `package.json` | User owned, PhaseGate assisted | Created by `init` or project install when absent; `install` may merge scripts/devDependency into `package.json` |
|
|
17
18
|
| 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 |
|
|
18
19
|
| 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 |
|
|
19
|
-
| Personal install artifact | `.phasegate-local/phasegate.config.json`, ignored real `.claude/settings.json` + `.claude/skills/`, ignored real `.codex/hooks.json` + `.codex/skills/`, `.git/info/exclude` PhaseGate block | One developer on one machine | Created by `phasegate install --personal --agent <agent>`; team `.gitignore`, team-owned files, GitHub CLI config, repo secrets, and CI settings are not modified |
|
|
20
|
+
| Personal install artifact | `.phasegate-local/phasegate.config.json`, ignored real `.claude/CLAUDE.md` + `.claude/settings.json` + `.claude/skills/`, ignored real `.codex/hooks.json` + `.codex/skills/`, optional ignored root `AGENTS.md`, `.git/info/exclude` PhaseGate block | One developer on one machine | Created by `phasegate install --personal --agent <agent>`; team `.gitignore`, team-owned files, GitHub CLI config, repo secrets, and CI settings are not modified |
|
|
20
21
|
| 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 |
|
|
21
22
|
| 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 |
|
|
22
23
|
|
|
@@ -44,6 +45,8 @@ PhaseGate setup is more than `phasegate.config.json`. A healthy installation is
|
|
|
44
45
|
|
|
45
46
|
If `.claude/*` or `.codex/*` already exists and is not a PhaseGate-managed personal artifact, personal install reports manual review and preserves the existing path. <!-- @work-item-id WI-209 -->
|
|
46
47
|
|
|
48
|
+
Personal agent context is also placed only where the runtime will read it. Claude Code uses `.claude/CLAUDE.md`. Codex uses root `AGENTS.md` when PhaseGate can create or manage it locally; if a team `AGENTS.md` already exists, PhaseGate leaves it unchanged and doctor reports `codex-context-missing` instead of creating `AGENTS.override.md`. <!-- @work-item-id WI-215 -->
|
|
49
|
+
|
|
47
50
|
Project install uses a different topology: selected bundled skills are deployed once to root `skills/`, and `.claude/skills` / `.codex/skills` point to that shared target. If an older project install has the links but an empty `skills/` target, `phasegate doctor` reports the selected agent skill check and `phasegate reconcile --apply` repairs the shared skill bodies. <!-- @work-item-id WI-210 -->
|
|
48
51
|
|
|
49
52
|
## Doctor Findings
|
package/package.json
CHANGED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// @unit installation
|
|
2
|
+
// @layer application
|
|
3
|
+
// @work-item-id WI-215
|
|
4
|
+
|
|
5
|
+
import type { FileInspectorPort } from "../ports/file-inspector-port.js";
|
|
6
|
+
import type { HeuristicCheck } from "../../domain/ports/heuristic-check.js";
|
|
7
|
+
import type { DiagnosticFinding } from "../../domain/diagnostic-finding.js";
|
|
8
|
+
import { createFinding, projectPath } from "./check-utils.js";
|
|
9
|
+
|
|
10
|
+
const MARKDOWN_BEGIN = "<!-- phasegate:managed-section:start -->";
|
|
11
|
+
|
|
12
|
+
export class ClaudeContextMissingCheck implements HeuristicCheck {
|
|
13
|
+
readonly checkId = "claude-context-missing" as const;
|
|
14
|
+
private readonly target = ".claude/CLAUDE.md";
|
|
15
|
+
private readonly projectTarget = "CLAUDE.md";
|
|
16
|
+
private readonly legacyTarget = ".claude/CLAUDE.local.md";
|
|
17
|
+
|
|
18
|
+
async run(projectRoot: string, inspector: FileInspectorPort): Promise<DiagnosticFinding | null> {
|
|
19
|
+
const content = await inspector.readText(projectPath(projectRoot, this.target));
|
|
20
|
+
if (content?.includes(MARKDOWN_BEGIN) === true && content.includes("PhaseGate")) return null;
|
|
21
|
+
const projectContent = await inspector.readText(projectPath(projectRoot, this.projectTarget));
|
|
22
|
+
if (projectContent?.includes(MARKDOWN_BEGIN) === true && projectContent.includes("PhaseGate")) return null;
|
|
23
|
+
|
|
24
|
+
const legacyContent = await inspector.readText(projectPath(projectRoot, this.legacyTarget));
|
|
25
|
+
return createFinding({
|
|
26
|
+
checkId: this.checkId,
|
|
27
|
+
severity: "red",
|
|
28
|
+
target: this.target,
|
|
29
|
+
message: legacyContent?.includes("PhaseGate") === true
|
|
30
|
+
? ".claude/CLAUDE.local.md は Claude Code の documented discovery path ではありません"
|
|
31
|
+
: ".claude/CLAUDE.md に runtime-visible PhaseGate context がありません",
|
|
32
|
+
repairMode: "mechanical",
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// @unit installation
|
|
2
|
+
// @layer application
|
|
3
|
+
// @work-item-id WI-215
|
|
4
|
+
|
|
5
|
+
import type { FileInspectorPort } from "../ports/file-inspector-port.js";
|
|
6
|
+
import type { HeuristicCheck } from "../../domain/ports/heuristic-check.js";
|
|
7
|
+
import type { DiagnosticFinding } from "../../domain/diagnostic-finding.js";
|
|
8
|
+
import { createFinding, projectPath } from "./check-utils.js";
|
|
9
|
+
|
|
10
|
+
const MARKDOWN_BEGIN = "<!-- phasegate:managed-section:start -->";
|
|
11
|
+
|
|
12
|
+
export class CodexContextMissingCheck implements HeuristicCheck {
|
|
13
|
+
readonly checkId = "codex-context-missing" as const;
|
|
14
|
+
private readonly target = "AGENTS.md";
|
|
15
|
+
private readonly legacyTarget = ".codex/AGENTS.local.md";
|
|
16
|
+
|
|
17
|
+
async run(projectRoot: string, inspector: FileInspectorPort): Promise<DiagnosticFinding | null> {
|
|
18
|
+
const content = await inspector.readText(projectPath(projectRoot, this.target));
|
|
19
|
+
if (content?.includes(MARKDOWN_BEGIN) === true && content.includes("PhaseGate")) return null;
|
|
20
|
+
|
|
21
|
+
const legacyContent = await inspector.readText(projectPath(projectRoot, this.legacyTarget));
|
|
22
|
+
return createFinding({
|
|
23
|
+
checkId: this.checkId,
|
|
24
|
+
severity: "red",
|
|
25
|
+
target: this.target,
|
|
26
|
+
message: legacyContent?.includes("PhaseGate") === true
|
|
27
|
+
? ".codex/AGENTS.local.md は Codex の default discovery path ではありません"
|
|
28
|
+
: "AGENTS.md に runtime-visible PhaseGate context がありません",
|
|
29
|
+
repairMode: content === null ? "mechanical" : "manual",
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// @work-item-id WI-145
|
|
4
4
|
// @work-item-id WI-178
|
|
5
5
|
// @work-item-id WI-208
|
|
6
|
+
// @work-item-id WI-215
|
|
6
7
|
|
|
7
8
|
import { DiagnosticReport } from "../../domain/diagnostic-report.js";
|
|
8
9
|
import type { CheckId } from "../../domain/check-id.js";
|
|
@@ -32,8 +33,8 @@ export interface RunDoctorDiagnosticsOutput {
|
|
|
32
33
|
readonly exitCode: number;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
const CLAUDE_ONLY_CHECKS = new Set<CheckId>(["claude-hook-missing", "claude-skills-symlink"]);
|
|
36
|
-
const CODEX_ONLY_CHECKS = new Set<CheckId>(["codex-hook-missing", "codex-skills-symlink"]);
|
|
36
|
+
const CLAUDE_ONLY_CHECKS = new Set<CheckId>(["claude-hook-missing", "claude-context-missing", "claude-skills-symlink"]);
|
|
37
|
+
const CODEX_ONLY_CHECKS = new Set<CheckId>(["codex-hook-missing", "codex-context-missing", "codex-skills-symlink"]);
|
|
37
38
|
const PERSONAL_SCOPED_OUT_CHECKS = new Set<CheckId>([
|
|
38
39
|
"husky-pre-commit-missing",
|
|
39
40
|
"husky-commit-msg-missing",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
// @work-item-id WI-210
|
|
14
14
|
// @work-item-id WI-213
|
|
15
15
|
// @work-item-id WI-214
|
|
16
|
+
// @work-item-id WI-215
|
|
16
17
|
|
|
17
18
|
import { mkdir, readFile, writeFile, copyFile, chmod, access, lstat, readlink, symlink, readdir, rm } from "node:fs/promises";
|
|
18
19
|
import { dirname, join } from "node:path";
|
|
@@ -78,6 +79,7 @@ interface InstallTarget {
|
|
|
78
79
|
readonly templatePath: string;
|
|
79
80
|
readonly executable?: boolean;
|
|
80
81
|
readonly block?: ManagedBlockInput;
|
|
82
|
+
readonly personalManualIfUnmanaged?: boolean;
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
const SKILL_HINT = "invoke /phasegate-config-doctor";
|
|
@@ -89,7 +91,7 @@ const MARKDOWN_BEGIN = "<!-- phasegate:managed-section:start -->";
|
|
|
89
91
|
const MARKDOWN_END = "<!-- phasegate:managed-section:end -->";
|
|
90
92
|
const TEXT_BEGIN = "# phasegate personal install exclude (BEGIN)";
|
|
91
93
|
const TEXT_END = "# phasegate personal install exclude (END)";
|
|
92
|
-
const PERSONAL_AGENT_RUNTIME_FILES = new Set([".claude/settings.json", ".codex/hooks.json"]);
|
|
94
|
+
const PERSONAL_AGENT_RUNTIME_FILES = new Set([".claude/CLAUDE.md", ".claude/settings.json", "AGENTS.md", ".codex/hooks.json"]);
|
|
93
95
|
const SHARED_SKILLS_VERSION_PATH = "skills/.harness-version";
|
|
94
96
|
const PERSONAL_PRINCIPLES_DOCS = ".phasegate-local/docs/principles";
|
|
95
97
|
const PERSONAL_FOLDER_RULES_DOC = ".phasegate-local/docs/folder_management_rules.md";
|
|
@@ -350,8 +352,9 @@ export class RunInstallUseCase {
|
|
|
350
352
|
const existingEntry = baseManifest.findEntry(target.path);
|
|
351
353
|
const beforeHash = before === null ? null : this.hashCalculator.compute(before);
|
|
352
354
|
const unmanagedPersonalRuntimeFile = input.personal
|
|
353
|
-
&& PERSONAL_AGENT_RUNTIME_FILES.has(target.path)
|
|
355
|
+
&& (PERSONAL_AGENT_RUNTIME_FILES.has(target.path) || target.personalManualIfUnmanaged === true)
|
|
354
356
|
&& before !== null
|
|
357
|
+
&& !before.includes(MARKDOWN_BEGIN)
|
|
355
358
|
&& (existingEntry === null || beforeHash === null || !beforeHash.equals(existingEntry.hash));
|
|
356
359
|
const repairMode = unmanagedPersonalRuntimeFile ? "manual" : this.repairMode(target, before);
|
|
357
360
|
const next = unmanagedPersonalRuntimeFile ? before : this.merge(target, before, template, input.phasegateVersion);
|
|
@@ -364,7 +367,7 @@ export class RunInstallUseCase {
|
|
|
364
367
|
strategy: target.strategy,
|
|
365
368
|
changed: didChange,
|
|
366
369
|
summary: unmanagedPersonalRuntimeFile
|
|
367
|
-
? `${target.path}: existing non-phasegate path requires manual review`
|
|
370
|
+
? `${target.path}: existing non-phasegate runtime path requires manual review`
|
|
368
371
|
: didChange ? `${target.path}: ${action}` : `${target.path}: already up to date`,
|
|
369
372
|
diff: unmanagedPersonalRuntimeFile ? "manual review required" : this.diffSummary(before, next),
|
|
370
373
|
skillHint: repairMode === "ai-assisted" ? SKILL_HINT : null,
|
|
@@ -629,10 +632,11 @@ export class RunInstallUseCase {
|
|
|
629
632
|
...(options.includeClaude
|
|
630
633
|
? [
|
|
631
634
|
{
|
|
632
|
-
path: ".claude/CLAUDE.
|
|
635
|
+
path: ".claude/CLAUDE.md",
|
|
633
636
|
strategy: "markdown-managed" as const,
|
|
634
637
|
templatePath: "docs/templates/agent-context/CLAUDE.md.template.md",
|
|
635
|
-
block: { start: MARKDOWN_BEGIN, end: MARKDOWN_END, content: "phasegate personal CLAUDE.
|
|
638
|
+
block: { start: MARKDOWN_BEGIN, end: MARKDOWN_END, content: "phasegate personal .claude/CLAUDE.md managed section" },
|
|
639
|
+
personalManualIfUnmanaged: true,
|
|
636
640
|
},
|
|
637
641
|
{
|
|
638
642
|
path: ".claude/settings.json",
|
|
@@ -644,10 +648,11 @@ export class RunInstallUseCase {
|
|
|
644
648
|
...(options.includeCodex
|
|
645
649
|
? [
|
|
646
650
|
{
|
|
647
|
-
path: "
|
|
651
|
+
path: "AGENTS.md",
|
|
648
652
|
strategy: "markdown-managed" as const,
|
|
649
653
|
templatePath: "docs/templates/agent-context/AGENTS.md.template.md",
|
|
650
|
-
block: { start: MARKDOWN_BEGIN, end: MARKDOWN_END, content: "phasegate personal AGENTS.
|
|
654
|
+
block: { start: MARKDOWN_BEGIN, end: MARKDOWN_END, content: "phasegate personal AGENTS.md managed section" },
|
|
655
|
+
personalManualIfUnmanaged: true,
|
|
651
656
|
},
|
|
652
657
|
{
|
|
653
658
|
path: ".codex/hooks.json",
|
|
@@ -365,7 +365,9 @@ export class RunUninstallUseCase {
|
|
|
365
365
|
if (mode === "symlink") return "symlink";
|
|
366
366
|
if (mode === "created") return path.endsWith(".yml") || path.endsWith(".yaml") ? "yaml-add" : "created";
|
|
367
367
|
if (path === "package.json") return "package-json";
|
|
368
|
-
if (path === "AGENTS.md" || path === "CLAUDE.md"
|
|
368
|
+
if (path === "AGENTS.md" || path === "CLAUDE.md" || path === ".claude/CLAUDE.md" || path === ".claude/CLAUDE.local.md" || path === ".codex/AGENTS.local.md") {
|
|
369
|
+
return "markdown-managed";
|
|
370
|
+
}
|
|
369
371
|
if (path === ".git/info/exclude") return "text-managed";
|
|
370
372
|
if (path.endsWith(".json")) return "json";
|
|
371
373
|
if (path.startsWith(".husky/")) return "shell";
|
|
@@ -376,7 +378,9 @@ export class RunUninstallUseCase {
|
|
|
376
378
|
if (path === ".claude/settings.json") return "templates/.claude/settings.json";
|
|
377
379
|
if (path === ".codex/hooks.json") return "templates/.codex/hooks.json";
|
|
378
380
|
if (path === "CLAUDE.md") return "docs/templates/agent-context/CLAUDE.md.template.md";
|
|
381
|
+
if (path === ".claude/CLAUDE.md" || path === ".claude/CLAUDE.local.md") return "docs/templates/agent-context/CLAUDE.md.template.md";
|
|
379
382
|
if (path === "AGENTS.md") return "docs/templates/agent-context/AGENTS.md.template.md";
|
|
383
|
+
if (path === ".codex/AGENTS.local.md") return "docs/templates/agent-context/AGENTS.md.template.md";
|
|
380
384
|
throw new Error(`No template for ${path}`);
|
|
381
385
|
}
|
|
382
386
|
|
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
// @layer presentation
|
|
3
3
|
// @work-item-id WI-145
|
|
4
4
|
// @work-item-id WI-148
|
|
5
|
+
// @work-item-id WI-215
|
|
5
6
|
|
|
7
|
+
import { ClaudeContextMissingCheck } from "./application/checks/claude-context-missing-check.js";
|
|
6
8
|
import { ClaudeHookMissingCheck } from "./application/checks/claude-hook-missing-check.js";
|
|
7
9
|
import { ClaudeSkillsSymlinkCheck } from "./application/checks/claude-skills-symlink-check.js";
|
|
10
|
+
import { CodexContextMissingCheck } from "./application/checks/codex-context-missing-check.js";
|
|
8
11
|
import { CodexHookMissingCheck } from "./application/checks/codex-hook-missing-check.js";
|
|
9
12
|
import { CodexSkillsSymlinkCheck } from "./application/checks/codex-skills-symlink-check.js";
|
|
10
13
|
import { CiWorkflowMissingCheck } from "./application/checks/ci-workflow-missing-check.js";
|
|
@@ -42,7 +45,9 @@ export function createInstallationModule() {
|
|
|
42
45
|
const hashCalculator = new NodeCryptoHashAdapter();
|
|
43
46
|
const checks = [
|
|
44
47
|
new ClaudeHookMissingCheck(),
|
|
48
|
+
new ClaudeContextMissingCheck(),
|
|
45
49
|
new CodexHookMissingCheck(),
|
|
50
|
+
new CodexContextMissingCheck(),
|
|
46
51
|
new HuskyPreCommitMissingCheck(),
|
|
47
52
|
new HuskyCommitMsgMissingCheck(),
|
|
48
53
|
new HuskyPrePushMissingCheck(),
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
// @unit installation
|
|
2
2
|
// @layer domain
|
|
3
3
|
// @work-item-id WI-145
|
|
4
|
+
// @work-item-id WI-215
|
|
4
5
|
|
|
5
6
|
export const CHECK_IDS = [
|
|
6
7
|
"claude-hook-missing",
|
|
8
|
+
"claude-context-missing",
|
|
7
9
|
"codex-hook-missing",
|
|
10
|
+
"codex-context-missing",
|
|
8
11
|
"husky-pre-commit-missing",
|
|
9
12
|
"husky-commit-msg-missing",
|
|
10
13
|
"husky-pre-push-missing",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @unit installation
|
|
2
2
|
// @layer domain
|
|
3
3
|
// @work-item-id WI-145
|
|
4
|
+
// @work-item-id WI-215
|
|
4
5
|
|
|
5
6
|
import type { CheckId } from "./check-id.js";
|
|
6
7
|
import { SuggestedSkill } from "./suggested-skill.js";
|
|
@@ -23,7 +24,9 @@ export class RepairTable {
|
|
|
23
24
|
constructor() {
|
|
24
25
|
this.table = new Map<CheckId, SuggestedSkill | null>([
|
|
25
26
|
["claude-hook-missing", CONFIG_DOCTOR],
|
|
27
|
+
["claude-context-missing", CONFIG_DOCTOR],
|
|
26
28
|
["codex-hook-missing", CONFIG_DOCTOR],
|
|
29
|
+
["codex-context-missing", CONFIG_DOCTOR],
|
|
27
30
|
["husky-pre-commit-missing", CONFIG_DOCTOR],
|
|
28
31
|
["husky-commit-msg-missing", CONFIG_DOCTOR],
|
|
29
32
|
["husky-pre-push-missing", null],
|