@skillcap/gdh 0.2.1 → 0.3.1

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.
@@ -33,6 +33,21 @@ export const CURSOR_MCP_RELATIVE_PATH = ".cursor/mcp.json";
33
33
  export const CURSOR_RULE_RELATIVE_PATH = ".cursor/rules/gdh-agent.mdc";
34
34
  export const CURSOR_ONBOARD_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-onboard/SKILL.md";
35
35
  export const CODEX_ONBOARD_SKILL_RELATIVE_PATH = ".codex/skills/gdh-onboard/SKILL.md";
36
+ export const CLAUDE_STATUS_COMMAND_RELATIVE_PATH = ".claude/commands/gdh/status.md";
37
+ export const CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH = ".claude/commands/gdh/migrate.md";
38
+ export const CLAUDE_CHECK_COMMAND_RELATIVE_PATH = ".claude/commands/gdh/check.md";
39
+ export const CLAUDE_PREPARE_COMMAND_RELATIVE_PATH = ".claude/commands/gdh/prepare.md";
40
+ export const CLAUDE_VERIFY_COMMAND_RELATIVE_PATH = ".claude/commands/gdh/verify.md";
41
+ export const CODEX_STATUS_SKILL_RELATIVE_PATH = ".codex/skills/gdh-status/SKILL.md";
42
+ export const CODEX_MIGRATE_SKILL_RELATIVE_PATH = ".codex/skills/gdh-migrate/SKILL.md";
43
+ export const CODEX_CHECK_SKILL_RELATIVE_PATH = ".codex/skills/gdh-check/SKILL.md";
44
+ export const CODEX_PREPARE_SKILL_RELATIVE_PATH = ".codex/skills/gdh-prepare/SKILL.md";
45
+ export const CODEX_VERIFY_SKILL_RELATIVE_PATH = ".codex/skills/gdh-verify/SKILL.md";
46
+ export const CURSOR_STATUS_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-status/SKILL.md";
47
+ export const CURSOR_MIGRATE_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-migrate/SKILL.md";
48
+ export const CURSOR_CHECK_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-check/SKILL.md";
49
+ export const CURSOR_PREPARE_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-prepare/SKILL.md";
50
+ export const CURSOR_VERIFY_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-verify/SKILL.md";
36
51
  export const LOCAL_PATH_HINTS_RELATIVE_PATH = ".gdh-state/local-paths.json";
37
52
  export const MCP_LAUNCHER_RELATIVE_PATH = ".gdh/bin/gdh-mcp.mjs";
38
53
  export const GDH_MCP_SERVER_NAME = "gdh";
@@ -118,7 +133,9 @@ export async function installSupportedAgentAdapters(targetPath, options = {}) {
118
133
  };
119
134
  }
120
135
  export async function inspectProjectLifecycleCompatibility(targetPath) {
121
- const resolvedTargetPath = path.resolve(targetPath);
136
+ const rawTargetPath = path.resolve(targetPath);
137
+ const projectRoot = await resolveProjectRoot(rawTargetPath);
138
+ const resolvedTargetPath = projectRoot ?? rawTargetPath;
122
139
  const projectConfig = await readProjectConfig(resolvedTargetPath);
123
140
  if (projectConfig === null) {
124
141
  const blockedSurface = createLifecycleSurfaceStatus({
@@ -397,6 +414,569 @@ export function renderCursorOnboardSkill() {
397
414
  "",
398
415
  ].join("\n");
399
416
  }
417
+ // --- gdh-status skill renders ---
418
+ export function renderClaudeStatusCommand() {
419
+ return [
420
+ "---",
421
+ "name: gdh:status",
422
+ "description: Check GDH project readiness, surface migration needs, and suggest next step",
423
+ "allowed-tools:",
424
+ " - Read",
425
+ " - Grep",
426
+ " - Glob",
427
+ " - Bash",
428
+ "---",
429
+ "<objective>",
430
+ "Check GDH project readiness, surface migration needs, and suggest the most productive next step.",
431
+ "</objective>",
432
+ "",
433
+ "<process>",
434
+ "Follow this order:",
435
+ "",
436
+ "1. Run `gdh status` and explain each readiness field.",
437
+ "2. Check if migration is needed with `gdh migrate`.",
438
+ "3. Surface any degraded or unavailable capabilities.",
439
+ "4. Suggest the most productive next step based on current state.",
440
+ "</process>",
441
+ "",
442
+ "<rules>",
443
+ "- Do not start editing code.",
444
+ "- Prefer structured GDH surfaces over repo guesswork.",
445
+ "- Keep output short and operational.",
446
+ "</rules>",
447
+ "",
448
+ ].join("\n");
449
+ }
450
+ export function renderCodexStatusSkill() {
451
+ return [
452
+ "---",
453
+ 'name: "gdh-status"',
454
+ 'description: "Check GDH project readiness, surface migration needs, and suggest next step"',
455
+ "metadata:",
456
+ ' short-description: "Check GDH project readiness, surface migration needs, and suggest next step"',
457
+ "---",
458
+ "",
459
+ "<codex_skill_adapter>",
460
+ "## Invocation",
461
+ "- This skill is invoked when the user says `/gdh-status` or mentions `$gdh-status`.",
462
+ "- Treat any extra user text as additional status context.",
463
+ "",
464
+ "## User questions",
465
+ "- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
466
+ "- If structured user-input tooling is unavailable, ask concise plain-text questions instead.",
467
+ "</codex_skill_adapter>",
468
+ "",
469
+ "<objective>",
470
+ "Check GDH project readiness, surface migration needs, and suggest the most productive next step.",
471
+ "</objective>",
472
+ "",
473
+ "<process>",
474
+ "Follow this order:",
475
+ "",
476
+ "- run `gdh status` and explain each readiness field",
477
+ "- check if migration is needed with `gdh migrate`",
478
+ "- surface any degraded or unavailable capabilities",
479
+ "- suggest the most productive next step based on current state",
480
+ "</process>",
481
+ "",
482
+ "<rules>",
483
+ "- Do not start editing code.",
484
+ "- Prefer structured GDH surfaces over repo guesswork.",
485
+ "- Keep output short and operational.",
486
+ "</rules>",
487
+ "",
488
+ ].join("\n");
489
+ }
490
+ export function renderCursorStatusSkill() {
491
+ return [
492
+ "---",
493
+ "name: gdh-status",
494
+ 'description: "Check GDH project readiness, surface migration needs, and suggest next step"',
495
+ "---",
496
+ "",
497
+ "<cursor_skill_adapter>",
498
+ "## Invocation",
499
+ "- This skill is invoked when the user says `/gdh-status` or mentions `gdh-status`.",
500
+ "- Treat any extra user text as additional status context.",
501
+ "",
502
+ "## User questions",
503
+ "- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
504
+ "- Keep questions conversational and concise.",
505
+ "</cursor_skill_adapter>",
506
+ "",
507
+ "<objective>",
508
+ "Check GDH project readiness, surface migration needs, and suggest the most productive next step.",
509
+ "</objective>",
510
+ "",
511
+ "<process>",
512
+ "Follow this order:",
513
+ "",
514
+ "- run `gdh status` and explain each readiness field",
515
+ "- check if migration is needed with `gdh migrate`",
516
+ "- surface any degraded or unavailable capabilities",
517
+ "- suggest the most productive next step based on current state",
518
+ "</process>",
519
+ "",
520
+ "<rules>",
521
+ "- Do not start editing code.",
522
+ "- Prefer structured GDH surfaces over repo guesswork.",
523
+ "- Keep output short and operational.",
524
+ "</rules>",
525
+ "",
526
+ ].join("\n");
527
+ }
528
+ // --- gdh-migrate skill renders ---
529
+ export function renderClaudeMigrateCommand() {
530
+ return [
531
+ "---",
532
+ "name: gdh:migrate",
533
+ "description: Preview and apply GDH project migrations",
534
+ "allowed-tools:",
535
+ " - Read",
536
+ " - Grep",
537
+ " - Glob",
538
+ " - Bash",
539
+ " - AskUserQuestion",
540
+ "---",
541
+ "<objective>",
542
+ "Preview and apply GDH project migrations safely with explicit user approval.",
543
+ "</objective>",
544
+ "",
545
+ "<process>",
546
+ "Follow this order:",
547
+ "",
548
+ "1. Run `gdh migrate` to preview pending migrations.",
549
+ "2. Explain what each migration step will change and why.",
550
+ "3. Offer to run `gdh migrate --apply` if the user approves.",
551
+ "4. After apply, run `gdh status` to verify the migration succeeded.",
552
+ "</process>",
553
+ "",
554
+ "<rules>",
555
+ "- Never apply migrations without explicit user approval.",
556
+ "- Show the dry-run output first.",
557
+ "- Keep explanations concise.",
558
+ "</rules>",
559
+ "",
560
+ ].join("\n");
561
+ }
562
+ export function renderCodexMigrateSkill() {
563
+ return [
564
+ "---",
565
+ 'name: "gdh-migrate"',
566
+ 'description: "Preview and apply GDH project migrations"',
567
+ "metadata:",
568
+ ' short-description: "Preview and apply GDH project migrations"',
569
+ "---",
570
+ "",
571
+ "<codex_skill_adapter>",
572
+ "## Invocation",
573
+ "- This skill is invoked when the user says `/gdh-migrate` or mentions `$gdh-migrate`.",
574
+ "- Treat any extra user text as additional migration context.",
575
+ "",
576
+ "## User questions",
577
+ "- Always ask before applying migrations.",
578
+ "- If structured user-input tooling is unavailable, ask concise plain-text questions instead.",
579
+ "</codex_skill_adapter>",
580
+ "",
581
+ "<objective>",
582
+ "Preview and apply GDH project migrations safely with explicit user approval.",
583
+ "</objective>",
584
+ "",
585
+ "<process>",
586
+ "Follow this order:",
587
+ "",
588
+ "- run `gdh migrate` to preview pending migrations",
589
+ "- explain what each migration step will change and why",
590
+ "- offer to run `gdh migrate --apply` if the user approves",
591
+ "- after apply, run `gdh status` to verify the migration succeeded",
592
+ "</process>",
593
+ "",
594
+ "<rules>",
595
+ "- Never apply migrations without explicit user approval.",
596
+ "- Show the dry-run output first.",
597
+ "- Keep explanations concise.",
598
+ "</rules>",
599
+ "",
600
+ ].join("\n");
601
+ }
602
+ export function renderCursorMigrateSkill() {
603
+ return [
604
+ "---",
605
+ "name: gdh-migrate",
606
+ 'description: "Preview and apply GDH project migrations"',
607
+ "---",
608
+ "",
609
+ "<cursor_skill_adapter>",
610
+ "## Invocation",
611
+ "- This skill is invoked when the user says `/gdh-migrate` or mentions `gdh-migrate`.",
612
+ "- Treat any extra user text as additional migration context.",
613
+ "",
614
+ "## User questions",
615
+ "- Always ask before applying migrations.",
616
+ "- Keep questions conversational and concise.",
617
+ "</cursor_skill_adapter>",
618
+ "",
619
+ "<objective>",
620
+ "Preview and apply GDH project migrations safely with explicit user approval.",
621
+ "</objective>",
622
+ "",
623
+ "<process>",
624
+ "Follow this order:",
625
+ "",
626
+ "- run `gdh migrate` to preview pending migrations",
627
+ "- explain what each migration step will change and why",
628
+ "- offer to run `gdh migrate --apply` if the user approves",
629
+ "- after apply, run `gdh status` to verify the migration succeeded",
630
+ "</process>",
631
+ "",
632
+ "<rules>",
633
+ "- Never apply migrations without explicit user approval.",
634
+ "- Show the dry-run output first.",
635
+ "- Keep explanations concise.",
636
+ "</rules>",
637
+ "",
638
+ ].join("\n");
639
+ }
640
+ // --- gdh-check skill renders ---
641
+ export function renderClaudeCheckCommand() {
642
+ return [
643
+ "---",
644
+ "name: gdh:check",
645
+ "description: Run GDH authoring checks and explain diagnostics",
646
+ "allowed-tools:",
647
+ " - Read",
648
+ " - Grep",
649
+ " - Glob",
650
+ " - Bash",
651
+ "---",
652
+ "<objective>",
653
+ "Run GDH authoring checks and explain diagnostics in human-readable terms.",
654
+ "</objective>",
655
+ "",
656
+ "<process>",
657
+ "Follow this order:",
658
+ "",
659
+ "1. Run `gdh authoring check`.",
660
+ "2. Explain each diagnostic finding with severity and provenance.",
661
+ "3. Surface any import-state caveats or editor-side warnings.",
662
+ "4. If issues found, suggest concrete remediation steps.",
663
+ "</process>",
664
+ "",
665
+ "<rules>",
666
+ "- Do not fix issues automatically unless asked.",
667
+ "- Explain diagnostics in human-readable terms.",
668
+ "- Report both hard failures and informational caveats.",
669
+ "</rules>",
670
+ "",
671
+ ].join("\n");
672
+ }
673
+ export function renderCodexCheckSkill() {
674
+ return [
675
+ "---",
676
+ 'name: "gdh-check"',
677
+ 'description: "Run GDH authoring checks and explain diagnostics"',
678
+ "metadata:",
679
+ ' short-description: "Run GDH authoring checks and explain diagnostics"',
680
+ "---",
681
+ "",
682
+ "<codex_skill_adapter>",
683
+ "## Invocation",
684
+ "- This skill is invoked when the user says `/gdh-check` or mentions `$gdh-check`.",
685
+ "- Treat any extra user text as additional check context.",
686
+ "",
687
+ "## User questions",
688
+ "- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
689
+ "- If structured user-input tooling is unavailable, ask concise plain-text questions instead.",
690
+ "</codex_skill_adapter>",
691
+ "",
692
+ "<objective>",
693
+ "Run GDH authoring checks and explain diagnostics in human-readable terms.",
694
+ "</objective>",
695
+ "",
696
+ "<process>",
697
+ "Follow this order:",
698
+ "",
699
+ "- run `gdh authoring check`",
700
+ "- explain each diagnostic finding with severity and provenance",
701
+ "- surface any import-state caveats or editor-side warnings",
702
+ "- if issues found, suggest concrete remediation steps",
703
+ "</process>",
704
+ "",
705
+ "<rules>",
706
+ "- Do not fix issues automatically unless asked.",
707
+ "- Explain diagnostics in human-readable terms.",
708
+ "- Report both hard failures and informational caveats.",
709
+ "</rules>",
710
+ "",
711
+ ].join("\n");
712
+ }
713
+ export function renderCursorCheckSkill() {
714
+ return [
715
+ "---",
716
+ "name: gdh-check",
717
+ 'description: "Run GDH authoring checks and explain diagnostics"',
718
+ "---",
719
+ "",
720
+ "<cursor_skill_adapter>",
721
+ "## Invocation",
722
+ "- This skill is invoked when the user says `/gdh-check` or mentions `gdh-check`.",
723
+ "- Treat any extra user text as additional check context.",
724
+ "",
725
+ "## User questions",
726
+ "- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
727
+ "- Keep questions conversational and concise.",
728
+ "</cursor_skill_adapter>",
729
+ "",
730
+ "<objective>",
731
+ "Run GDH authoring checks and explain diagnostics in human-readable terms.",
732
+ "</objective>",
733
+ "",
734
+ "<process>",
735
+ "Follow this order:",
736
+ "",
737
+ "- run `gdh authoring check`",
738
+ "- explain each diagnostic finding with severity and provenance",
739
+ "- surface any import-state caveats or editor-side warnings",
740
+ "- if issues found, suggest concrete remediation steps",
741
+ "</process>",
742
+ "",
743
+ "<rules>",
744
+ "- Do not fix issues automatically unless asked.",
745
+ "- Explain diagnostics in human-readable terms.",
746
+ "- Report both hard failures and informational caveats.",
747
+ "</rules>",
748
+ "",
749
+ ].join("\n");
750
+ }
751
+ // --- gdh-prepare skill renders ---
752
+ export function renderClaudePrepareCommand() {
753
+ return [
754
+ "---",
755
+ "name: gdh:prepare",
756
+ "description: Prepare a Godot target for authoring or runtime work",
757
+ "allowed-tools:",
758
+ " - Read",
759
+ " - Grep",
760
+ " - Glob",
761
+ " - Bash",
762
+ " - AskUserQuestion",
763
+ "---",
764
+ "<objective>",
765
+ "Prepare a Godot target for authoring or runtime work using GDH target preparation.",
766
+ "</objective>",
767
+ "",
768
+ "<process>",
769
+ "Follow this order:",
770
+ "",
771
+ "1. Run `gdh target prepare --dry-run` first to preview planned actions.",
772
+ "2. Explain what hydration and import refresh will do.",
773
+ "3. If the user approves, run `gdh target prepare`.",
774
+ "4. If a `--source-target` is relevant, explain when and why to use it.",
775
+ "5. Verify preparation succeeded with `gdh status`.",
776
+ "</process>",
777
+ "",
778
+ "<rules>",
779
+ "- Always show dry-run first.",
780
+ "- Explain worktree hydration context.",
781
+ "- Do not skip import refresh without explicit reason.",
782
+ "</rules>",
783
+ "",
784
+ ].join("\n");
785
+ }
786
+ export function renderCodexPrepareSkill() {
787
+ return [
788
+ "---",
789
+ 'name: "gdh-prepare"',
790
+ 'description: "Prepare a Godot target for authoring or runtime work"',
791
+ "metadata:",
792
+ ' short-description: "Prepare a Godot target for authoring or runtime work"',
793
+ "---",
794
+ "",
795
+ "<codex_skill_adapter>",
796
+ "## Invocation",
797
+ "- This skill is invoked when the user says `/gdh-prepare` or mentions `$gdh-prepare`.",
798
+ "- Treat any extra user text as additional preparation context.",
799
+ "",
800
+ "## User questions",
801
+ "- Ask before running preparation if the user has not explicitly approved.",
802
+ "- If structured user-input tooling is unavailable, ask concise plain-text questions instead.",
803
+ "</codex_skill_adapter>",
804
+ "",
805
+ "<objective>",
806
+ "Prepare a Godot target for authoring or runtime work using GDH target preparation.",
807
+ "</objective>",
808
+ "",
809
+ "<process>",
810
+ "Follow this order:",
811
+ "",
812
+ "- run `gdh target prepare --dry-run` first to preview planned actions",
813
+ "- explain what hydration and import refresh will do",
814
+ "- if the user approves, run `gdh target prepare`",
815
+ "- if a `--source-target` is relevant, explain when and why to use it",
816
+ "- verify preparation succeeded with `gdh status`",
817
+ "</process>",
818
+ "",
819
+ "<rules>",
820
+ "- Always show dry-run first.",
821
+ "- Explain worktree hydration context.",
822
+ "- Do not skip import refresh without explicit reason.",
823
+ "</rules>",
824
+ "",
825
+ ].join("\n");
826
+ }
827
+ export function renderCursorPrepareSkill() {
828
+ return [
829
+ "---",
830
+ "name: gdh-prepare",
831
+ 'description: "Prepare a Godot target for authoring or runtime work"',
832
+ "---",
833
+ "",
834
+ "<cursor_skill_adapter>",
835
+ "## Invocation",
836
+ "- This skill is invoked when the user says `/gdh-prepare` or mentions `gdh-prepare`.",
837
+ "- Treat any extra user text as additional preparation context.",
838
+ "",
839
+ "## User questions",
840
+ "- Ask before running preparation if the user has not explicitly approved.",
841
+ "- Keep questions conversational and concise.",
842
+ "</cursor_skill_adapter>",
843
+ "",
844
+ "<objective>",
845
+ "Prepare a Godot target for authoring or runtime work using GDH target preparation.",
846
+ "</objective>",
847
+ "",
848
+ "<process>",
849
+ "Follow this order:",
850
+ "",
851
+ "- run `gdh target prepare --dry-run` first to preview planned actions",
852
+ "- explain what hydration and import refresh will do",
853
+ "- if the user approves, run `gdh target prepare`",
854
+ "- if a `--source-target` is relevant, explain when and why to use it",
855
+ "- verify preparation succeeded with `gdh status`",
856
+ "</process>",
857
+ "",
858
+ "<rules>",
859
+ "- Always show dry-run first.",
860
+ "- Explain worktree hydration context.",
861
+ "- Do not skip import refresh without explicit reason.",
862
+ "</rules>",
863
+ "",
864
+ ].join("\n");
865
+ }
866
+ // --- gdh-verify skill renders ---
867
+ export function renderClaudeVerifyCommand() {
868
+ return [
869
+ "---",
870
+ "name: gdh:verify",
871
+ "description: Evaluate verification readiness and done-policy for changed files",
872
+ "allowed-tools:",
873
+ " - Read",
874
+ " - Grep",
875
+ " - Glob",
876
+ " - Bash",
877
+ "---",
878
+ "<objective>",
879
+ "Evaluate verification readiness and done-policy for changed files using GDH verification surfaces.",
880
+ "</objective>",
881
+ "",
882
+ "<process>",
883
+ "Follow this order:",
884
+ "",
885
+ "1. Identify changed files from git diff or user input.",
886
+ "2. Run `gdh verify recommend` with those files to get recommended validation kinds.",
887
+ "3. Run `gdh verify done` with performed validations to check done eligibility.",
888
+ "4. Summarize gaps between recommended and performed validation.",
889
+ "5. Suggest specific next verification steps.",
890
+ "</process>",
891
+ "",
892
+ "<rules>",
893
+ "- Do not mark work as done if done-policy is not satisfied.",
894
+ "- Surface all recommended validation kinds.",
895
+ "- Keep the summary actionable.",
896
+ "</rules>",
897
+ "",
898
+ ].join("\n");
899
+ }
900
+ export function renderCodexVerifySkill() {
901
+ return [
902
+ "---",
903
+ 'name: "gdh-verify"',
904
+ 'description: "Evaluate verification readiness and done-policy for changed files"',
905
+ "metadata:",
906
+ ' short-description: "Evaluate verification readiness and done-policy for changed files"',
907
+ "---",
908
+ "",
909
+ "<codex_skill_adapter>",
910
+ "## Invocation",
911
+ "- This skill is invoked when the user says `/gdh-verify` or mentions `$gdh-verify`.",
912
+ "- Treat any extra user text as additional verification context.",
913
+ "",
914
+ "## User questions",
915
+ "- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
916
+ "- If structured user-input tooling is unavailable, ask concise plain-text questions instead.",
917
+ "</codex_skill_adapter>",
918
+ "",
919
+ "<objective>",
920
+ "Evaluate verification readiness and done-policy for changed files using GDH verification surfaces.",
921
+ "</objective>",
922
+ "",
923
+ "<process>",
924
+ "Follow this order:",
925
+ "",
926
+ "- identify changed files from git diff or user input",
927
+ "- run `gdh verify recommend` with those files to get recommended validation kinds",
928
+ "- run `gdh verify done` with performed validations to check done eligibility",
929
+ "- summarize gaps between recommended and performed validation",
930
+ "- suggest specific next verification steps",
931
+ "</process>",
932
+ "",
933
+ "<rules>",
934
+ "- Do not mark work as done if done-policy is not satisfied.",
935
+ "- Surface all recommended validation kinds.",
936
+ "- Keep the summary actionable.",
937
+ "</rules>",
938
+ "",
939
+ ].join("\n");
940
+ }
941
+ export function renderCursorVerifySkill() {
942
+ return [
943
+ "---",
944
+ "name: gdh-verify",
945
+ 'description: "Evaluate verification readiness and done-policy for changed files"',
946
+ "---",
947
+ "",
948
+ "<cursor_skill_adapter>",
949
+ "## Invocation",
950
+ "- This skill is invoked when the user says `/gdh-verify` or mentions `gdh-verify`.",
951
+ "- Treat any extra user text as additional verification context.",
952
+ "",
953
+ "## User questions",
954
+ "- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
955
+ "- Keep questions conversational and concise.",
956
+ "</cursor_skill_adapter>",
957
+ "",
958
+ "<objective>",
959
+ "Evaluate verification readiness and done-policy for changed files using GDH verification surfaces.",
960
+ "</objective>",
961
+ "",
962
+ "<process>",
963
+ "Follow this order:",
964
+ "",
965
+ "- identify changed files from git diff or user input",
966
+ "- run `gdh verify recommend` with those files to get recommended validation kinds",
967
+ "- run `gdh verify done` with performed validations to check done eligibility",
968
+ "- summarize gaps between recommended and performed validation",
969
+ "- suggest specific next verification steps",
970
+ "</process>",
971
+ "",
972
+ "<rules>",
973
+ "- Do not mark work as done if done-policy is not satisfied.",
974
+ "- Surface all recommended validation kinds.",
975
+ "- Keep the summary actionable.",
976
+ "</rules>",
977
+ "",
978
+ ].join("\n");
979
+ }
400
980
  async function inspectProjectMcpSupport(targetPath, options) {
401
981
  const projectConfig = await readProjectConfig(targetPath);
402
982
  const enabled = resolveProjectMcpEnabled(projectConfig);
@@ -601,9 +1181,80 @@ async function inspectCodexRegistration(targetPath, enabled, codexServerName, co
601
1181
  summary: `Codex has the expected user-local MCP registration \`${codexServerName}\`.`,
602
1182
  };
603
1183
  }
1184
+ function inspectCodexSkillSurface(targetPath, relativePath, content, expectedContent, skillName) {
1185
+ return [
1186
+ createSurfaceStatus({
1187
+ kind: "skill_file",
1188
+ scope: "repo",
1189
+ targetPath,
1190
+ relativePath,
1191
+ present: content !== null,
1192
+ state: content === null
1193
+ ? "missing"
1194
+ : content === expectedContent
1195
+ ? "ready"
1196
+ : "misconfigured",
1197
+ summary: content === null
1198
+ ? `Codex \`/${skillName}\` skill is missing and should install under .codex/skills/.`
1199
+ : content === expectedContent
1200
+ ? `Codex can discover the managed \`/${skillName}\` skill.`
1201
+ : `Codex \`/${skillName}\` skill exists but no longer matches the expected managed GDH skill.`,
1202
+ version: null,
1203
+ }),
1204
+ ];
1205
+ }
1206
+ function inspectClaudeCommandSurface(targetPath, relativePath, content, expectedContent, commandName) {
1207
+ return [
1208
+ createSurfaceStatus({
1209
+ kind: "command_file",
1210
+ scope: "repo",
1211
+ targetPath,
1212
+ relativePath,
1213
+ present: content !== null,
1214
+ state: content === null
1215
+ ? "missing"
1216
+ : content === expectedContent
1217
+ ? "ready"
1218
+ : "misconfigured",
1219
+ summary: content === null
1220
+ ? `Claude \`/${commandName}\` command is missing and should install under .claude/commands/gdh/.`
1221
+ : content === expectedContent
1222
+ ? `Claude can discover the managed \`/${commandName}\` command.`
1223
+ : `Claude \`/${commandName}\` command exists but no longer matches the expected managed GDH command.`,
1224
+ version: null,
1225
+ }),
1226
+ ];
1227
+ }
1228
+ function inspectCursorSkillSurface(targetPath, relativePath, content, expectedContent, skillName) {
1229
+ return [
1230
+ createSurfaceStatus({
1231
+ kind: "skill_file",
1232
+ scope: "repo",
1233
+ targetPath,
1234
+ relativePath,
1235
+ present: content !== null,
1236
+ state: content === null
1237
+ ? "missing"
1238
+ : content === expectedContent
1239
+ ? "ready"
1240
+ : "misconfigured",
1241
+ summary: content === null
1242
+ ? `Cursor \`/${skillName}\` skill is missing and should install under .cursor/skills/.`
1243
+ : content === expectedContent
1244
+ ? `Cursor can discover the managed \`/${skillName}\` skill.`
1245
+ : `Cursor \`/${skillName}\` skill exists but no longer matches the expected managed GDH skill.`,
1246
+ version: null,
1247
+ }),
1248
+ ];
1249
+ }
604
1250
  async function inspectCodexAdapter(targetPath, guidance, projectMcp, options) {
605
1251
  const codexSkillPath = path.join(targetPath, CODEX_ONBOARD_SKILL_RELATIVE_PATH);
606
1252
  const codexSkillContent = await fs.readFile(codexSkillPath, "utf8").catch(() => null);
1253
+ const codexStatusContent = await fs.readFile(path.join(targetPath, CODEX_STATUS_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1254
+ const codexMigrateContent = await fs.readFile(path.join(targetPath, CODEX_MIGRATE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1255
+ const codexCheckContent = await fs.readFile(path.join(targetPath, CODEX_CHECK_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1256
+ const codexPrepareContent = await fs.readFile(path.join(targetPath, CODEX_PREPARE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1257
+ const codexVerifyContent = await fs.readFile(path.join(targetPath, CODEX_VERIFY_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
607
1258
  const surfaces = [
608
1259
  createSurfaceStatus({
609
1260
  kind: "canonical_entrypoint",
@@ -641,6 +1292,11 @@ async function inspectCodexAdapter(targetPath, guidance, projectMcp, options) {
641
1292
  : "Codex onboarding handoff exists but no longer matches the expected managed GDH skill.",
642
1293
  version: null,
643
1294
  }),
1295
+ ...inspectCodexSkillSurface(targetPath, CODEX_STATUS_SKILL_RELATIVE_PATH, codexStatusContent, renderCodexStatusSkill(), "gdh-status"),
1296
+ ...inspectCodexSkillSurface(targetPath, CODEX_MIGRATE_SKILL_RELATIVE_PATH, codexMigrateContent, renderCodexMigrateSkill(), "gdh-migrate"),
1297
+ ...inspectCodexSkillSurface(targetPath, CODEX_CHECK_SKILL_RELATIVE_PATH, codexCheckContent, renderCodexCheckSkill(), "gdh-check"),
1298
+ ...inspectCodexSkillSurface(targetPath, CODEX_PREPARE_SKILL_RELATIVE_PATH, codexPrepareContent, renderCodexPrepareSkill(), "gdh-prepare"),
1299
+ ...inspectCodexSkillSurface(targetPath, CODEX_VERIFY_SKILL_RELATIVE_PATH, codexVerifyContent, renderCodexVerifySkill(), "gdh-verify"),
644
1300
  ];
645
1301
  if (projectMcp.enabled) {
646
1302
  surfaces.push(createSurfaceStatus({
@@ -674,6 +1330,11 @@ async function inspectClaudeAdapter(targetPath, guidance, projectMcp) {
674
1330
  const onboardCommandPath = path.join(targetPath, CLAUDE_ONBOARD_COMMAND_RELATIVE_PATH);
675
1331
  const lstat = await fs.lstat(absolutePath).catch(() => null);
676
1332
  const onboardCommandContent = await fs.readFile(onboardCommandPath, "utf8").catch(() => null);
1333
+ const claudeStatusContent = await fs.readFile(path.join(targetPath, CLAUDE_STATUS_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
1334
+ const claudeMigrateContent = await fs.readFile(path.join(targetPath, CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
1335
+ const claudeCheckContent = await fs.readFile(path.join(targetPath, CLAUDE_CHECK_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
1336
+ const claudePrepareContent = await fs.readFile(path.join(targetPath, CLAUDE_PREPARE_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
1337
+ const claudeVerifyContent = await fs.readFile(path.join(targetPath, CLAUDE_VERIFY_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
677
1338
  let detectedTarget = null;
678
1339
  if (lstat?.isSymbolicLink()) {
679
1340
  detectedTarget = await fs.readlink(absolutePath).catch(() => null);
@@ -717,6 +1378,11 @@ async function inspectClaudeAdapter(targetPath, guidance, projectMcp) {
717
1378
  : "Claude onboarding handoff exists but no longer matches the expected managed GDH command.",
718
1379
  version: null,
719
1380
  }),
1381
+ ...inspectClaudeCommandSurface(targetPath, CLAUDE_STATUS_COMMAND_RELATIVE_PATH, claudeStatusContent, renderClaudeStatusCommand(), "gdh-status"),
1382
+ ...inspectClaudeCommandSurface(targetPath, CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH, claudeMigrateContent, renderClaudeMigrateCommand(), "gdh-migrate"),
1383
+ ...inspectClaudeCommandSurface(targetPath, CLAUDE_CHECK_COMMAND_RELATIVE_PATH, claudeCheckContent, renderClaudeCheckCommand(), "gdh-check"),
1384
+ ...inspectClaudeCommandSurface(targetPath, CLAUDE_PREPARE_COMMAND_RELATIVE_PATH, claudePrepareContent, renderClaudePrepareCommand(), "gdh-prepare"),
1385
+ ...inspectClaudeCommandSurface(targetPath, CLAUDE_VERIFY_COMMAND_RELATIVE_PATH, claudeVerifyContent, renderClaudeVerifyCommand(), "gdh-verify"),
720
1386
  ];
721
1387
  if (projectMcp.enabled) {
722
1388
  surfaces.push(createSurfaceStatus({
@@ -748,6 +1414,11 @@ async function inspectCursorAdapter(targetPath, guidance, projectMcp) {
748
1414
  const onboardSkillPath = path.join(targetPath, CURSOR_ONBOARD_SKILL_RELATIVE_PATH);
749
1415
  const content = await fs.readFile(absolutePath, "utf8").catch(() => null);
750
1416
  const onboardSkillContent = await fs.readFile(onboardSkillPath, "utf8").catch(() => null);
1417
+ const cursorStatusContent = await fs.readFile(path.join(targetPath, CURSOR_STATUS_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1418
+ const cursorMigrateContent = await fs.readFile(path.join(targetPath, CURSOR_MIGRATE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1419
+ const cursorCheckContent = await fs.readFile(path.join(targetPath, CURSOR_CHECK_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1420
+ const cursorPrepareContent = await fs.readFile(path.join(targetPath, CURSOR_PREPARE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1421
+ const cursorVerifyContent = await fs.readFile(path.join(targetPath, CURSOR_VERIFY_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
751
1422
  const expectedContent = renderCursorRule();
752
1423
  const version = readCursorRuleVersion(content);
753
1424
  const surfaces = [
@@ -787,6 +1458,11 @@ async function inspectCursorAdapter(targetPath, guidance, projectMcp) {
787
1458
  : "Cursor onboarding handoff exists but no longer matches the expected managed GDH skill.",
788
1459
  version: null,
789
1460
  }),
1461
+ ...inspectCursorSkillSurface(targetPath, CURSOR_STATUS_SKILL_RELATIVE_PATH, cursorStatusContent, renderCursorStatusSkill(), "gdh-status"),
1462
+ ...inspectCursorSkillSurface(targetPath, CURSOR_MIGRATE_SKILL_RELATIVE_PATH, cursorMigrateContent, renderCursorMigrateSkill(), "gdh-migrate"),
1463
+ ...inspectCursorSkillSurface(targetPath, CURSOR_CHECK_SKILL_RELATIVE_PATH, cursorCheckContent, renderCursorCheckSkill(), "gdh-check"),
1464
+ ...inspectCursorSkillSurface(targetPath, CURSOR_PREPARE_SKILL_RELATIVE_PATH, cursorPrepareContent, renderCursorPrepareSkill(), "gdh-prepare"),
1465
+ ...inspectCursorSkillSurface(targetPath, CURSOR_VERIFY_SKILL_RELATIVE_PATH, cursorVerifyContent, renderCursorVerifySkill(), "gdh-verify"),
790
1466
  ];
791
1467
  if (projectMcp.enabled) {
792
1468
  surfaces.push(createSurfaceStatus({
@@ -991,38 +1667,54 @@ function planSharedRepoInstallActions(targetPath, projectMcp, agent, effectiveDe
991
1667
  }
992
1668
  return actions;
993
1669
  }
994
- function planCodexRepoInstallActions(targetPath, adapter) {
995
- const actions = [];
996
- const codexSkillSurface = adapter.surfaces.find((surface) => surface.relativePath === CODEX_ONBOARD_SKILL_RELATIVE_PATH);
997
- if (!codexSkillSurface || codexSkillSurface.state === "ready") {
998
- actions.push(createInstallAction({
999
- agent: "codex",
1670
+ function planSkillInstallAction(agent, targetPath, adapter, relativePath, renderFn, skillName) {
1671
+ const surface = adapter.surfaces.find((s) => s.relativePath === relativePath);
1672
+ if (!surface || surface.state === "ready") {
1673
+ return createInstallAction({
1674
+ agent,
1000
1675
  kind: "write_file",
1001
1676
  scope: "repo",
1002
1677
  targetPath,
1003
- relativePath: CODEX_ONBOARD_SKILL_RELATIVE_PATH,
1678
+ relativePath,
1004
1679
  state: "unchanged",
1005
1680
  mode: "unchanged",
1006
- summary: "The managed Codex `/gdh-onboard` skill already matches the expected GDH content.",
1007
- content: renderCodexOnboardSkill(),
1008
- }));
1681
+ summary: `The managed ${agentLabel(agent)} \`/${skillName}\` ${agent === "claude" ? "command" : "skill"} already matches the expected GDH content.`,
1682
+ content: renderFn(),
1683
+ });
1009
1684
  }
1010
- else {
1011
- actions.push(createInstallAction({
1012
- agent: "codex",
1013
- kind: "write_file",
1014
- scope: "repo",
1015
- targetPath,
1016
- relativePath: CODEX_ONBOARD_SKILL_RELATIVE_PATH,
1017
- state: "planned",
1018
- mode: codexSkillSurface.present ? "replace" : "create",
1019
- summary: codexSkillSurface.present
1020
- ? "Replace the existing Codex `/gdh-onboard` skill with the managed GDH skill."
1021
- : "Create the managed Codex `/gdh-onboard` skill.",
1022
- content: renderCodexOnboardSkill(),
1023
- }));
1685
+ return createInstallAction({
1686
+ agent,
1687
+ kind: "write_file",
1688
+ scope: "repo",
1689
+ targetPath,
1690
+ relativePath,
1691
+ state: "planned",
1692
+ mode: surface.present ? "replace" : "create",
1693
+ summary: surface.present
1694
+ ? `Replace the existing ${agentLabel(agent)} \`/${skillName}\` ${agent === "claude" ? "command" : "skill"} with the managed GDH ${agent === "claude" ? "command" : "skill"}.`
1695
+ : `Create the managed ${agentLabel(agent)} \`/${skillName}\` ${agent === "claude" ? "command" : "skill"}.`,
1696
+ content: renderFn(),
1697
+ });
1698
+ }
1699
+ function agentLabel(agent) {
1700
+ switch (agent) {
1701
+ case "claude":
1702
+ return "Claude";
1703
+ case "codex":
1704
+ return "Codex";
1705
+ case "cursor":
1706
+ return "Cursor";
1024
1707
  }
1025
- return actions;
1708
+ }
1709
+ function planCodexRepoInstallActions(targetPath, adapter) {
1710
+ return [
1711
+ planSkillInstallAction("codex", targetPath, adapter, CODEX_ONBOARD_SKILL_RELATIVE_PATH, renderCodexOnboardSkill, "gdh-onboard"),
1712
+ planSkillInstallAction("codex", targetPath, adapter, CODEX_STATUS_SKILL_RELATIVE_PATH, renderCodexStatusSkill, "gdh-status"),
1713
+ planSkillInstallAction("codex", targetPath, adapter, CODEX_MIGRATE_SKILL_RELATIVE_PATH, renderCodexMigrateSkill, "gdh-migrate"),
1714
+ planSkillInstallAction("codex", targetPath, adapter, CODEX_CHECK_SKILL_RELATIVE_PATH, renderCodexCheckSkill, "gdh-check"),
1715
+ planSkillInstallAction("codex", targetPath, adapter, CODEX_PREPARE_SKILL_RELATIVE_PATH, renderCodexPrepareSkill, "gdh-prepare"),
1716
+ planSkillInstallAction("codex", targetPath, adapter, CODEX_VERIFY_SKILL_RELATIVE_PATH, renderCodexVerifySkill, "gdh-verify"),
1717
+ ];
1026
1718
  }
1027
1719
  function planCodexUserInstallActions(targetPath, projectMcp, integrationRootPath) {
1028
1720
  if (!projectMcp.enabled || projectMcp.codexServerName === null) {
@@ -1103,35 +1795,7 @@ function planClaudeInstallActions(targetPath, adapter) {
1103
1795
  expectedTarget: "AGENTS.md",
1104
1796
  }));
1105
1797
  }
1106
- const claudeCommandSurface = adapter.surfaces.find((surface) => surface.relativePath === CLAUDE_ONBOARD_COMMAND_RELATIVE_PATH);
1107
- if (!claudeCommandSurface || claudeCommandSurface.state === "ready") {
1108
- actions.push(createInstallAction({
1109
- agent: "claude",
1110
- kind: "write_file",
1111
- scope: "repo",
1112
- targetPath,
1113
- relativePath: CLAUDE_ONBOARD_COMMAND_RELATIVE_PATH,
1114
- state: "unchanged",
1115
- mode: "unchanged",
1116
- summary: "The managed Claude `/gdh-onboard` command already matches the expected GDH content.",
1117
- content: renderClaudeOnboardCommand(),
1118
- }));
1119
- }
1120
- else {
1121
- actions.push(createInstallAction({
1122
- agent: "claude",
1123
- kind: "write_file",
1124
- scope: "repo",
1125
- targetPath,
1126
- relativePath: CLAUDE_ONBOARD_COMMAND_RELATIVE_PATH,
1127
- state: "planned",
1128
- mode: claudeCommandSurface.present ? "replace" : "create",
1129
- summary: claudeCommandSurface.present
1130
- ? "Replace the existing Claude `/gdh-onboard` command with the managed GDH command."
1131
- : "Create the managed Claude `/gdh-onboard` command.",
1132
- content: renderClaudeOnboardCommand(),
1133
- }));
1134
- }
1798
+ actions.push(planSkillInstallAction("claude", targetPath, adapter, CLAUDE_ONBOARD_COMMAND_RELATIVE_PATH, renderClaudeOnboardCommand, "gdh-onboard"), planSkillInstallAction("claude", targetPath, adapter, CLAUDE_STATUS_COMMAND_RELATIVE_PATH, renderClaudeStatusCommand, "gdh-status"), planSkillInstallAction("claude", targetPath, adapter, CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH, renderClaudeMigrateCommand, "gdh-migrate"), planSkillInstallAction("claude", targetPath, adapter, CLAUDE_CHECK_COMMAND_RELATIVE_PATH, renderClaudeCheckCommand, "gdh-check"), planSkillInstallAction("claude", targetPath, adapter, CLAUDE_PREPARE_COMMAND_RELATIVE_PATH, renderClaudePrepareCommand, "gdh-prepare"), planSkillInstallAction("claude", targetPath, adapter, CLAUDE_VERIFY_COMMAND_RELATIVE_PATH, renderClaudeVerifyCommand, "gdh-verify"));
1135
1799
  return actions;
1136
1800
  }
1137
1801
  function planCursorInstallActions(targetPath, adapter) {
@@ -1167,35 +1831,7 @@ function planCursorInstallActions(targetPath, adapter) {
1167
1831
  content: renderCursorRule(),
1168
1832
  }));
1169
1833
  }
1170
- const cursorSkillSurface = adapter.surfaces.find((surface) => surface.relativePath === CURSOR_ONBOARD_SKILL_RELATIVE_PATH);
1171
- if (!cursorSkillSurface || cursorSkillSurface.state === "ready") {
1172
- actions.push(createInstallAction({
1173
- agent: "cursor",
1174
- kind: "write_file",
1175
- scope: "repo",
1176
- targetPath,
1177
- relativePath: CURSOR_ONBOARD_SKILL_RELATIVE_PATH,
1178
- state: "unchanged",
1179
- mode: "unchanged",
1180
- summary: "The managed Cursor `/gdh-onboard` skill already matches the expected GDH content.",
1181
- content: renderCursorOnboardSkill(),
1182
- }));
1183
- }
1184
- else {
1185
- actions.push(createInstallAction({
1186
- agent: "cursor",
1187
- kind: "write_file",
1188
- scope: "repo",
1189
- targetPath,
1190
- relativePath: CURSOR_ONBOARD_SKILL_RELATIVE_PATH,
1191
- state: "planned",
1192
- mode: cursorSkillSurface.present ? "replace" : "create",
1193
- summary: cursorSkillSurface.present
1194
- ? "Replace the existing Cursor `/gdh-onboard` skill with the managed GDH skill."
1195
- : "Create the managed Cursor `/gdh-onboard` skill.",
1196
- content: renderCursorOnboardSkill(),
1197
- }));
1198
- }
1834
+ actions.push(planSkillInstallAction("cursor", targetPath, adapter, CURSOR_ONBOARD_SKILL_RELATIVE_PATH, renderCursorOnboardSkill, "gdh-onboard"), planSkillInstallAction("cursor", targetPath, adapter, CURSOR_STATUS_SKILL_RELATIVE_PATH, renderCursorStatusSkill, "gdh-status"), planSkillInstallAction("cursor", targetPath, adapter, CURSOR_MIGRATE_SKILL_RELATIVE_PATH, renderCursorMigrateSkill, "gdh-migrate"), planSkillInstallAction("cursor", targetPath, adapter, CURSOR_CHECK_SKILL_RELATIVE_PATH, renderCursorCheckSkill, "gdh-check"), planSkillInstallAction("cursor", targetPath, adapter, CURSOR_PREPARE_SKILL_RELATIVE_PATH, renderCursorPrepareSkill, "gdh-prepare"), planSkillInstallAction("cursor", targetPath, adapter, CURSOR_VERIFY_SKILL_RELATIVE_PATH, renderCursorVerifySkill, "gdh-verify"));
1199
1835
  return actions;
1200
1836
  }
1201
1837
  function dedupeInstallActions(actions) {