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