@sun-asterisk/sungen 3.2.2 → 3.2.3-beta.3
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/dist/capabilities/discover.d.ts.map +1 -1
- package/dist/capabilities/discover.js +26 -3
- package/dist/capabilities/discover.js.map +1 -1
- package/dist/cli/commands/add-flow.d.ts.map +1 -1
- package/dist/cli/commands/add-flow.js +2 -0
- package/dist/cli/commands/add-flow.js.map +1 -1
- package/dist/cli/commands/add.d.ts.map +1 -1
- package/dist/cli/commands/add.js +4 -0
- package/dist/cli/commands/add.js.map +1 -1
- package/dist/cli/commands/capability.d.ts.map +1 -1
- package/dist/cli/commands/capability.js +61 -0
- package/dist/cli/commands/capability.js.map +1 -1
- package/dist/cli/commands/delivery.d.ts.map +1 -1
- package/dist/cli/commands/delivery.js +89 -2
- package/dist/cli/commands/delivery.js.map +1 -1
- package/dist/cli/commands/eval.js +3 -3
- package/dist/cli/commands/eval.js.map +1 -1
- package/dist/cli/commands/gate.d.ts +3 -0
- package/dist/cli/commands/gate.d.ts.map +1 -0
- package/dist/cli/commands/gate.js +83 -0
- package/dist/cli/commands/gate.js.map +1 -0
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +2 -1
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +32 -2
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/journey.d.ts +3 -0
- package/dist/cli/commands/journey.d.ts.map +1 -0
- package/dist/cli/commands/journey.js +114 -0
- package/dist/cli/commands/journey.js.map +1 -0
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +10 -3
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/snapshot-builder.d.ts.map +1 -1
- package/dist/dashboard/snapshot-builder.js +10 -1
- package/dist/dashboard/snapshot-builder.js.map +1 -1
- package/dist/exporters/csv-exporter.d.ts.map +1 -1
- package/dist/exporters/csv-exporter.js +3 -1
- package/dist/exporters/csv-exporter.js.map +1 -1
- package/dist/exporters/json-exporter.js +3 -1
- package/dist/exporters/json-exporter.js.map +1 -1
- package/dist/exporters/mobile-app-id.d.ts +22 -0
- package/dist/exporters/mobile-app-id.d.ts.map +1 -0
- package/dist/exporters/mobile-app-id.js +37 -0
- package/dist/exporters/mobile-app-id.js.map +1 -0
- package/dist/exporters/spec-parser.d.ts.map +1 -1
- package/dist/exporters/spec-parser.js +6 -2
- package/dist/exporters/spec-parser.js.map +1 -1
- package/dist/generators/test-generator/adapters/adapter-interface.d.ts +3 -0
- package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
- package/dist/generators/test-generator/adapters/appium/templates/steps/actions/scroll-action.hbs +7 -4
- package/dist/generators/test-generator/adapters/appium/templates/steps/actions/toggle-action.hbs +20 -3
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/checked-assertion.hbs +4 -1
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/not-checked-assertion.hbs +4 -1
- package/dist/generators/test-generator/adapters/appium/templates/test-file.hbs +3 -0
- package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.js +48 -9
- package/dist/generators/test-generator/code-generator.js.map +1 -1
- package/dist/generators/test-generator/template-engine.d.ts +3 -0
- package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
- package/dist/generators/test-generator/template-engine.js +11 -1
- package/dist/generators/test-generator/template-engine.js.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.d.ts +11 -1
- package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.js +33 -0
- package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
- package/dist/harness/audit.d.ts.map +1 -1
- package/dist/harness/audit.js +8 -1
- package/dist/harness/audit.js.map +1 -1
- package/dist/harness/catalog/universal-viewpoints.yaml +15 -0
- package/dist/harness/eval/skill-lint.d.ts +3 -3
- package/dist/harness/eval/skill-lint.d.ts.map +1 -1
- package/dist/harness/eval/skill-lint.js +88 -68
- package/dist/harness/eval/skill-lint.js.map +1 -1
- package/dist/harness/journey.d.ts +88 -0
- package/dist/harness/journey.d.ts.map +1 -0
- package/dist/harness/journey.js +414 -0
- package/dist/harness/journey.js.map +1 -0
- package/dist/harness/quality-gates.d.ts +13 -0
- package/dist/harness/quality-gates.d.ts.map +1 -1
- package/dist/harness/quality-gates.js +23 -0
- package/dist/harness/quality-gates.js.map +1 -1
- package/dist/harness/sensors.d.ts +1 -1
- package/dist/harness/sensors.d.ts.map +1 -1
- package/dist/harness/sensors.js +32 -9
- package/dist/harness/sensors.js.map +1 -1
- package/dist/orchestrator/ai-rules-updater.d.ts +11 -3
- package/dist/orchestrator/ai-rules-updater.d.ts.map +1 -1
- package/dist/orchestrator/ai-rules-updater.js +44 -180
- package/dist/orchestrator/ai-rules-updater.js.map +1 -1
- package/dist/orchestrator/ai-skills/adapters.d.ts +28 -0
- package/dist/orchestrator/ai-skills/adapters.d.ts.map +1 -0
- package/dist/orchestrator/ai-skills/adapters.js +34 -0
- package/dist/orchestrator/ai-skills/adapters.js.map +1 -0
- package/dist/orchestrator/ai-skills/build.d.ts +10 -0
- package/dist/orchestrator/ai-skills/build.d.ts.map +1 -0
- package/dist/orchestrator/ai-skills/build.js +128 -0
- package/dist/orchestrator/ai-skills/build.js.map +1 -0
- package/dist/orchestrator/ai-skills/cap-stripper.d.ts +27 -0
- package/dist/orchestrator/ai-skills/cap-stripper.d.ts.map +1 -0
- package/dist/orchestrator/ai-skills/cap-stripper.js +78 -0
- package/dist/orchestrator/ai-skills/cap-stripper.js.map +1 -0
- package/dist/orchestrator/ai-skills/commands.d.ts +22 -0
- package/dist/orchestrator/ai-skills/commands.d.ts.map +1 -0
- package/dist/orchestrator/ai-skills/commands.js +109 -0
- package/dist/orchestrator/ai-skills/commands.js.map +1 -0
- package/dist/orchestrator/ai-skills/generator.d.ts +23 -0
- package/dist/orchestrator/ai-skills/generator.d.ts.map +1 -0
- package/dist/orchestrator/ai-skills/generator.js +79 -0
- package/dist/orchestrator/ai-skills/generator.js.map +1 -0
- package/dist/orchestrator/ai-skills/golden-skills.test.d.ts +2 -0
- package/dist/orchestrator/ai-skills/golden-skills.test.d.ts.map +1 -0
- package/dist/orchestrator/ai-skills/golden-skills.test.js +183 -0
- package/dist/orchestrator/ai-skills/golden-skills.test.js.map +1 -0
- package/dist/orchestrator/ai-skills/resolve-assistants.d.ts +8 -0
- package/dist/orchestrator/ai-skills/resolve-assistants.d.ts.map +1 -0
- package/dist/orchestrator/ai-skills/resolve-assistants.js +28 -0
- package/dist/orchestrator/ai-skills/resolve-assistants.js.map +1 -0
- package/dist/orchestrator/ai-skills/writer.d.ts +15 -0
- package/dist/orchestrator/ai-skills/writer.d.ts.map +1 -0
- package/dist/orchestrator/ai-skills/writer.js +129 -0
- package/dist/orchestrator/ai-skills/writer.js.map +1 -0
- package/dist/orchestrator/flow-manager.d.ts +11 -0
- package/dist/orchestrator/flow-manager.d.ts.map +1 -1
- package/dist/orchestrator/flow-manager.js +147 -29
- package/dist/orchestrator/flow-manager.js.map +1 -1
- package/dist/orchestrator/mobile-runtime-scaffolder.d.ts +59 -0
- package/dist/orchestrator/mobile-runtime-scaffolder.d.ts.map +1 -0
- package/dist/orchestrator/mobile-runtime-scaffolder.js +298 -0
- package/dist/orchestrator/mobile-runtime-scaffolder.js.map +1 -0
- package/dist/orchestrator/project-initializer.d.ts +44 -7
- package/dist/orchestrator/project-initializer.d.ts.map +1 -1
- package/dist/orchestrator/project-initializer.js +147 -79
- package/dist/orchestrator/project-initializer.js.map +1 -1
- package/dist/orchestrator/screen-manager.d.ts +30 -0
- package/dist/orchestrator/screen-manager.d.ts.map +1 -1
- package/dist/orchestrator/screen-manager.js +205 -22
- package/dist/orchestrator/screen-manager.js.map +1 -1
- package/dist/orchestrator/templates/ai-src/README.md +58 -0
- package/dist/orchestrator/templates/{ai-instructions/claude-cmd-add-flow.md → ai-src/commands/add-flow.md} +63 -2
- package/dist/orchestrator/templates/{ai-instructions/claude-cmd-add-screen.md → ai-src/commands/add-screen.md} +171 -6
- package/dist/orchestrator/templates/{ai-instructions/claude-cmd-create-test.md → ai-src/commands/create-test.md} +118 -4
- package/{src/orchestrator/templates/ai-instructions/claude-cmd-dashboard.md → dist/orchestrator/templates/ai-src/commands/dashboard.md} +25 -3
- package/{src/orchestrator/templates/ai-instructions/claude-cmd-delivery.md → dist/orchestrator/templates/ai-src/commands/delivery.md} +67 -3
- package/dist/orchestrator/templates/ai-src/commands/design.md +29 -0
- package/{src/orchestrator/templates/ai-instructions/claude-cmd-feedback.md → dist/orchestrator/templates/ai-src/commands/feedback.md} +34 -3
- package/dist/orchestrator/templates/{ai-instructions/claude-cmd-locale.md → ai-src/commands/locale.md} +56 -4
- package/{src/orchestrator/templates/ai-instructions/claude-cmd-review.md → dist/orchestrator/templates/ai-src/commands/review.md} +57 -2
- package/{src/orchestrator/templates/ai-instructions/claude-cmd-run-test.md → dist/orchestrator/templates/ai-src/commands/run-test.md} +116 -5
- package/dist/orchestrator/templates/ai-src/config/codex.md +8 -0
- package/{src/orchestrator/templates/ai-instructions/claude-skill-capture-mobile.md → dist/orchestrator/templates/ai-src/skills/sungen-capture-mobile/SKILL.md} +11 -0
- package/dist/orchestrator/templates/{ai-instructions/github-skill-sungen-error-mapping.md → ai-src/skills/sungen-error-mapping/SKILL.md} +49 -9
- package/{src/orchestrator/templates/ai-instructions/claude-skill-harness-audit.md → dist/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md} +5 -5
- package/{src/orchestrator/templates/ai-instructions/claude-skill-locale.md → dist/orchestrator/templates/ai-src/skills/sungen-locale/SKILL.md} +275 -3
- package/{src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md → dist/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md} +17 -0
- package/dist/orchestrator/templates/{ai-instructions/claude-skill-selector-fix-mobile.md → ai-src/skills/sungen-selector-fix-mobile/SKILL.md} +5 -0
- package/dist/orchestrator/templates/{ai-instructions/claude-skill-tc-generation.md → ai-src/skills/sungen-tc-generation/SKILL.md} +5 -0
- package/dist/orchestrator/templates/playwright.config.ts +7 -4
- package/package.json +3 -3
- package/src/capabilities/discover.ts +29 -3
- package/src/cli/commands/add-flow.ts +2 -0
- package/src/cli/commands/add.ts +4 -0
- package/src/cli/commands/capability.ts +64 -1
- package/src/cli/commands/delivery.ts +89 -2
- package/src/cli/commands/eval.ts +3 -3
- package/src/cli/commands/gate.ts +44 -0
- package/src/cli/commands/generate.ts +2 -1
- package/src/cli/commands/init.ts +50 -3
- package/src/cli/commands/journey.ts +72 -0
- package/src/cli/commands/update.ts +14 -4
- package/src/cli/index.ts +4 -0
- package/src/dashboard/snapshot-builder.ts +10 -1
- package/src/exporters/csv-exporter.ts +3 -1
- package/src/exporters/json-exporter.ts +3 -1
- package/src/exporters/mobile-app-id.ts +34 -0
- package/src/exporters/spec-parser.ts +6 -2
- package/src/generators/test-generator/adapters/adapter-interface.ts +3 -0
- package/src/generators/test-generator/adapters/appium/templates/steps/actions/scroll-action.hbs +7 -4
- package/src/generators/test-generator/adapters/appium/templates/steps/actions/toggle-action.hbs +20 -3
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/checked-assertion.hbs +4 -1
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/not-checked-assertion.hbs +4 -1
- package/src/generators/test-generator/adapters/appium/templates/test-file.hbs +3 -0
- package/src/generators/test-generator/code-generator.ts +49 -9
- package/src/generators/test-generator/template-engine.ts +14 -1
- package/src/generators/test-generator/utils/selector-resolver.ts +51 -1
- package/src/harness/audit.ts +9 -2
- package/src/harness/catalog/universal-viewpoints.yaml +15 -0
- package/src/harness/eval/skill-lint.ts +71 -60
- package/src/harness/journey.ts +434 -0
- package/src/harness/quality-gates.ts +20 -0
- package/src/harness/sensors.ts +25 -8
- package/src/orchestrator/ai-rules-updater.ts +35 -197
- package/src/orchestrator/ai-skills/adapters.ts +52 -0
- package/src/orchestrator/ai-skills/build.ts +103 -0
- package/src/orchestrator/ai-skills/cap-stripper.ts +85 -0
- package/src/orchestrator/ai-skills/commands.ts +112 -0
- package/src/orchestrator/ai-skills/generator.ts +47 -0
- package/src/orchestrator/ai-skills/golden-skills.test.ts +124 -0
- package/src/orchestrator/ai-skills/resolve-assistants.ts +18 -0
- package/src/orchestrator/ai-skills/writer.ts +92 -0
- package/src/orchestrator/flow-manager.ts +165 -29
- package/src/orchestrator/mobile-runtime-scaffolder.ts +277 -0
- package/src/orchestrator/project-initializer.ts +159 -86
- package/src/orchestrator/screen-manager.ts +237 -22
- package/src/orchestrator/templates/ai-src/README.md +58 -0
- package/src/orchestrator/templates/{ai-instructions/claude-cmd-add-flow.md → ai-src/commands/add-flow.md} +63 -2
- package/src/orchestrator/templates/{ai-instructions/claude-cmd-add-screen.md → ai-src/commands/add-screen.md} +171 -6
- package/src/orchestrator/templates/{ai-instructions/claude-cmd-create-test.md → ai-src/commands/create-test.md} +118 -4
- package/{dist/orchestrator/templates/ai-instructions/claude-cmd-dashboard.md → src/orchestrator/templates/ai-src/commands/dashboard.md} +25 -3
- package/{dist/orchestrator/templates/ai-instructions/claude-cmd-delivery.md → src/orchestrator/templates/ai-src/commands/delivery.md} +67 -3
- package/src/orchestrator/templates/ai-src/commands/design.md +29 -0
- package/{dist/orchestrator/templates/ai-instructions/claude-cmd-feedback.md → src/orchestrator/templates/ai-src/commands/feedback.md} +34 -3
- package/src/orchestrator/templates/{ai-instructions/claude-cmd-locale.md → ai-src/commands/locale.md} +56 -4
- package/{dist/orchestrator/templates/ai-instructions/claude-cmd-review.md → src/orchestrator/templates/ai-src/commands/review.md} +57 -2
- package/{dist/orchestrator/templates/ai-instructions/claude-cmd-run-test.md → src/orchestrator/templates/ai-src/commands/run-test.md} +116 -5
- package/src/orchestrator/templates/ai-src/config/codex.md +8 -0
- package/{dist/orchestrator/templates/ai-instructions/claude-skill-capture-mobile.md → src/orchestrator/templates/ai-src/skills/sungen-capture-mobile/SKILL.md} +11 -0
- package/{dist/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md → src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md} +49 -9
- package/{dist/orchestrator/templates/ai-instructions/claude-skill-harness-audit.md → src/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md} +5 -5
- package/{dist/orchestrator/templates/ai-instructions/claude-skill-locale.md → src/orchestrator/templates/ai-src/skills/sungen-locale/SKILL.md} +275 -3
- package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md → src/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md} +17 -0
- package/src/orchestrator/templates/{ai-instructions/claude-skill-selector-fix-mobile.md → ai-src/skills/sungen-selector-fix-mobile/SKILL.md} +5 -0
- package/src/orchestrator/templates/{ai-instructions/claude-skill-tc-generation.md → ai-src/skills/sungen-tc-generation/SKILL.md} +5 -0
- package/src/orchestrator/templates/playwright.config.ts +7 -4
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-design.md +0 -12
- package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +0 -347
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-add-flow.md +0 -86
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +0 -131
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +0 -93
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-dashboard.md +0 -65
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-delivery.md +0 -83
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-design.md +0 -13
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-feedback.md +0 -24
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-locale.md +0 -70
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-review.md +0 -38
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +0 -155
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-capture-mobile.md +0 -184
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-harness-audit.md +0 -85
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-locale.md +0 -291
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix-mobile.md +0 -316
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-keys.md +0 -221
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +0 -617
- package/src/orchestrator/templates/ai-instructions/claude-cmd-design.md +0 -12
- package/src/orchestrator/templates/ai-instructions/claude-skill-api-design.md +0 -62
- package/src/orchestrator/templates/ai-instructions/claude-skill-capture-mode-figma-mcp.md +0 -82
- package/src/orchestrator/templates/ai-instructions/claude-skill-capture-mode-figma-pat.md +0 -117
- package/src/orchestrator/templates/ai-instructions/claude-skill-capture-mode-live.md +0 -60
- package/src/orchestrator/templates/ai-instructions/claude-skill-capture-mode-local.md +0 -38
- package/src/orchestrator/templates/ai-instructions/claude-skill-capture.md +0 -35
- package/src/orchestrator/templates/ai-instructions/claude-skill-dashboard.md +0 -121
- package/src/orchestrator/templates/ai-instructions/claude-skill-delivery.md +0 -141
- package/src/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +0 -157
- package/src/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +0 -446
- package/src/orchestrator/templates/ai-instructions/claude-skill-ingest-legacy.md +0 -79
- package/src/orchestrator/templates/ai-instructions/claude-skill-mobile-gestures.md +0 -109
- package/src/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +0 -347
- package/src/orchestrator/templates/ai-instructions/claude-skill-tc-review.md +0 -320
- package/src/orchestrator/templates/ai-instructions/claude-skill-test-design-techniques.md +0 -118
- package/src/orchestrator/templates/ai-instructions/claude-skill-viewpoint-group-a-data-entry.md +0 -203
- package/src/orchestrator/templates/ai-instructions/claude-skill-viewpoint-group-b-data-ops.md +0 -179
- package/src/orchestrator/templates/ai-instructions/claude-skill-viewpoint-group-c-data-explore.md +0 -233
- package/src/orchestrator/templates/ai-instructions/claude-skill-viewpoint-group-d-display.md +0 -226
- package/src/orchestrator/templates/ai-instructions/claude-skill-viewpoint-group-e-identity.md +0 -177
- package/src/orchestrator/templates/ai-instructions/claude-skill-viewpoint.md +0 -118
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-add-flow.md +0 -86
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +0 -131
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +0 -93
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-dashboard.md +0 -65
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-delivery.md +0 -83
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-design.md +0 -13
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-feedback.md +0 -24
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-locale.md +0 -70
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-review.md +0 -38
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +0 -155
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-api-design.md +0 -62
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-capture-mobile.md +0 -184
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-capture-mode-figma-mcp.md +0 -82
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-capture-mode-figma-pat.md +0 -117
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-capture-mode-live.md +0 -60
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-capture-mode-local.md +0 -38
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-capture.md +0 -35
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-dashboard.md +0 -121
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-delivery.md +0 -141
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +0 -157
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +0 -446
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-harness-audit.md +0 -85
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-ingest-legacy.md +0 -79
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-locale.md +0 -291
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-mobile-gestures.md +0 -109
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix-mobile.md +0 -316
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-keys.md +0 -221
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +0 -617
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-review.md +0 -320
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-test-design-techniques.md +0 -118
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint-group-a-data-entry.md +0 -203
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint-group-b-data-ops.md +0 -179
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint-group-c-data-explore.md +0 -233
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint-group-d-display.md +0 -226
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint-group-e-identity.md +0 -177
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint.md +0 -118
- /package/dist/orchestrator/templates/{ai-instructions/claude-agent-challenge.md → ai-src/agents/challenge.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-agent-discovery.md → ai-src/agents/discovery.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-agent-generator.md → ai-src/agents/generator.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-agent-reviewer.md → ai-src/agents/reviewer.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-config.md → ai-src/config/claude.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/copilot-config.md → ai-src/config/copilot.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-api-design.md → ai-src/skills/sungen-api-design/SKILL.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-capture.md → ai-src/skills/sungen-capture/SKILL.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-capture-mode-figma-mcp.md → ai-src/skills/sungen-capture/mode-figma-mcp.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-capture-mode-figma-pat.md → ai-src/skills/sungen-capture/mode-figma-pat.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-capture-mode-live.md → ai-src/skills/sungen-capture/mode-live.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-capture-mode-local.md → ai-src/skills/sungen-capture/mode-local.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-dashboard.md → ai-src/skills/sungen-dashboard/SKILL.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-delivery.md → ai-src/skills/sungen-delivery/SKILL.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-gherkin-syntax.md → ai-src/skills/sungen-gherkin-syntax/SKILL.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-ingest-legacy.md → ai-src/skills/sungen-ingest-legacy/SKILL.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-mobile-gestures.md → ai-src/skills/sungen-mobile-gestures/SKILL.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-selector-keys.md → ai-src/skills/sungen-selector-keys/SKILL.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-tc-review.md → ai-src/skills/sungen-tc-review/SKILL.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-test-design-techniques.md → ai-src/skills/sungen-test-design-techniques/SKILL.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-viewpoint.md → ai-src/skills/sungen-viewpoint/SKILL.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-viewpoint-group-a-data-entry.md → ai-src/skills/sungen-viewpoint/group-a-data-entry.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-viewpoint-group-b-data-ops.md → ai-src/skills/sungen-viewpoint/group-b-data-ops.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-viewpoint-group-c-data-explore.md → ai-src/skills/sungen-viewpoint/group-c-data-explore.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-viewpoint-group-d-display.md → ai-src/skills/sungen-viewpoint/group-d-display.md} +0 -0
- /package/dist/orchestrator/templates/{ai-instructions/claude-skill-viewpoint-group-e-identity.md → ai-src/skills/sungen-viewpoint/group-e-identity.md} +0 -0
- /package/src/orchestrator/templates/{ai-instructions/claude-agent-challenge.md → ai-src/agents/challenge.md} +0 -0
- /package/src/orchestrator/templates/{ai-instructions/claude-agent-discovery.md → ai-src/agents/discovery.md} +0 -0
- /package/src/orchestrator/templates/{ai-instructions/claude-agent-generator.md → ai-src/agents/generator.md} +0 -0
- /package/src/orchestrator/templates/{ai-instructions/claude-agent-reviewer.md → ai-src/agents/reviewer.md} +0 -0
- /package/src/orchestrator/templates/{ai-instructions/claude-config.md → ai-src/config/claude.md} +0 -0
- /package/src/orchestrator/templates/{ai-instructions/copilot-config.md → ai-src/config/copilot.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-api-design.md → src/orchestrator/templates/ai-src/skills/sungen-api-design/SKILL.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-capture.md → src/orchestrator/templates/ai-src/skills/sungen-capture/SKILL.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-capture-mode-figma-mcp.md → src/orchestrator/templates/ai-src/skills/sungen-capture/mode-figma-mcp.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-capture-mode-figma-pat.md → src/orchestrator/templates/ai-src/skills/sungen-capture/mode-figma-pat.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-capture-mode-live.md → src/orchestrator/templates/ai-src/skills/sungen-capture/mode-live.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-capture-mode-local.md → src/orchestrator/templates/ai-src/skills/sungen-capture/mode-local.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-dashboard.md → src/orchestrator/templates/ai-src/skills/sungen-dashboard/SKILL.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-delivery.md → src/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md → src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-ingest-legacy.md → src/orchestrator/templates/ai-src/skills/sungen-ingest-legacy/SKILL.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-mobile-gestures.md → src/orchestrator/templates/ai-src/skills/sungen-mobile-gestures/SKILL.md} +0 -0
- /package/src/orchestrator/templates/{ai-instructions/claude-skill-selector-keys.md → ai-src/skills/sungen-selector-keys/SKILL.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-review.md → src/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-test-design-techniques.md → src/orchestrator/templates/ai-src/skills/sungen-test-design-techniques/SKILL.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint.md → src/orchestrator/templates/ai-src/skills/sungen-viewpoint/SKILL.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint-group-a-data-entry.md → src/orchestrator/templates/ai-src/skills/sungen-viewpoint/group-a-data-entry.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint-group-b-data-ops.md → src/orchestrator/templates/ai-src/skills/sungen-viewpoint/group-b-data-ops.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint-group-c-data-explore.md → src/orchestrator/templates/ai-src/skills/sungen-viewpoint/group-c-data-explore.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint-group-d-display.md → src/orchestrator/templates/ai-src/skills/sungen-viewpoint/group-d-display.md} +0 -0
- /package/{dist/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint-group-e-identity.md → src/orchestrator/templates/ai-src/skills/sungen-viewpoint/group-e-identity.md} +0 -0
|
@@ -6,106 +6,15 @@
|
|
|
6
6
|
|
|
7
7
|
import * as fs from 'fs';
|
|
8
8
|
import * as path from 'path';
|
|
9
|
+
import { buildOutputs } from './ai-skills/build';
|
|
10
|
+
import { applyOutputs } from './ai-skills/writer';
|
|
11
|
+
import { AdapterKey } from './ai-skills/adapters';
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
['claude-config.md', 'CLAUDE.md'],
|
|
15
|
-
['copilot-config.md', '.github/copilot-instructions.md'],
|
|
16
|
-
|
|
17
|
-
// Commands — Claude Code
|
|
18
|
-
['claude-cmd-add-screen.md', '.claude/commands/sungen/add-screen.md'],
|
|
19
|
-
['claude-cmd-add-flow.md', '.claude/commands/sungen/add-flow.md'],
|
|
20
|
-
['claude-cmd-create-test.md', '.claude/commands/sungen/create-test.md'],
|
|
21
|
-
['claude-cmd-design.md', '.claude/commands/sungen/design.md'],
|
|
22
|
-
['claude-cmd-run-test.md', '.claude/commands/sungen/run-test.md'],
|
|
23
|
-
['claude-cmd-review.md', '.claude/commands/sungen/review.md'],
|
|
24
|
-
['claude-cmd-delivery.md', '.claude/commands/sungen/delivery.md'],
|
|
25
|
-
['claude-cmd-dashboard.md', '.claude/commands/sungen/dashboard.md'],
|
|
26
|
-
['claude-cmd-locale.md', '.claude/commands/sungen/locale.md'],
|
|
27
|
-
['claude-cmd-feedback.md', '.claude/commands/sungen/feedback.md'],
|
|
28
|
-
|
|
29
|
-
// Commands — GitHub Copilot
|
|
30
|
-
['copilot-cmd-add-screen.md', '.github/prompts/sungen-add-screen.prompt.md'],
|
|
31
|
-
['copilot-cmd-add-flow.md', '.github/prompts/sungen-add-flow.prompt.md'],
|
|
32
|
-
['copilot-cmd-create-test.md', '.github/prompts/sungen-create-test.prompt.md'],
|
|
33
|
-
['copilot-cmd-design.md', '.github/prompts/sungen-design.prompt.md'],
|
|
34
|
-
['copilot-cmd-run-test.md', '.github/prompts/sungen-run-test.prompt.md'],
|
|
35
|
-
['copilot-cmd-review.md', '.github/prompts/sungen-review.prompt.md'],
|
|
36
|
-
['copilot-cmd-delivery.md', '.github/prompts/sungen-delivery.prompt.md'],
|
|
37
|
-
['copilot-cmd-dashboard.md', '.github/prompts/sungen-dashboard.prompt.md'],
|
|
38
|
-
['copilot-cmd-locale.md', '.github/prompts/sungen-locale.prompt.md'],
|
|
39
|
-
['copilot-cmd-feedback.md', '.github/prompts/sungen-feedback.prompt.md'],
|
|
40
|
-
|
|
41
|
-
// Skills — Claude Code
|
|
42
|
-
['claude-skill-gherkin-syntax.md', '.claude/skills/sungen-gherkin-syntax/SKILL.md'],
|
|
43
|
-
['claude-skill-selector-keys.md', '.claude/skills/sungen-selector-keys/SKILL.md'],
|
|
44
|
-
['claude-skill-error-mapping.md', '.claude/skills/sungen-error-mapping/SKILL.md'],
|
|
45
|
-
['claude-skill-tc-generation.md', '.claude/skills/sungen-tc-generation/SKILL.md'],
|
|
46
|
-
['claude-skill-test-design-techniques.md', '.claude/skills/sungen-test-design-techniques/SKILL.md'],
|
|
47
|
-
['claude-skill-selector-fix.md', '.claude/skills/sungen-selector-fix/SKILL.md'],
|
|
48
|
-
['claude-skill-tc-review.md', '.claude/skills/sungen-tc-review/SKILL.md'],
|
|
49
|
-
['claude-skill-harness-audit.md', '.claude/skills/sungen-harness-audit/SKILL.md'],
|
|
50
|
-
['claude-skill-api-design.md', '.claude/skills/sungen-api-design/SKILL.md'],
|
|
51
|
-
['claude-skill-ingest-legacy.md', '.claude/skills/sungen-ingest-legacy/SKILL.md'],
|
|
52
|
-
['claude-skill-viewpoint.md', '.claude/skills/sungen-viewpoint/SKILL.md'],
|
|
53
|
-
['claude-skill-viewpoint-group-a-data-entry.md', '.claude/skills/sungen-viewpoint/group-a-data-entry.md'],
|
|
54
|
-
['claude-skill-viewpoint-group-b-data-ops.md', '.claude/skills/sungen-viewpoint/group-b-data-ops.md'],
|
|
55
|
-
['claude-skill-viewpoint-group-c-data-explore.md', '.claude/skills/sungen-viewpoint/group-c-data-explore.md'],
|
|
56
|
-
['claude-skill-viewpoint-group-d-display.md', '.claude/skills/sungen-viewpoint/group-d-display.md'],
|
|
57
|
-
['claude-skill-viewpoint-group-e-identity.md', '.claude/skills/sungen-viewpoint/group-e-identity.md'],
|
|
58
|
-
['claude-skill-delivery.md', '.claude/skills/sungen-delivery/SKILL.md'],
|
|
59
|
-
['claude-skill-dashboard.md', '.claude/skills/sungen-dashboard/SKILL.md'],
|
|
60
|
-
// sungen-capture — router skill (1 SKILL.md + 4 mode files). Replaces the former
|
|
61
|
-
// capture-figma / capture-live / capture-local / figma-source standalone skills.
|
|
62
|
-
['claude-skill-capture.md', '.claude/skills/sungen-capture/SKILL.md'],
|
|
63
|
-
['claude-skill-capture-mode-figma-mcp.md', '.claude/skills/sungen-capture/mode-figma-mcp.md'],
|
|
64
|
-
['claude-skill-capture-mode-figma-pat.md', '.claude/skills/sungen-capture/mode-figma-pat.md'],
|
|
65
|
-
['claude-skill-capture-mode-live.md', '.claude/skills/sungen-capture/mode-live.md'],
|
|
66
|
-
['claude-skill-capture-mode-local.md', '.claude/skills/sungen-capture/mode-local.md'],
|
|
67
|
-
['claude-skill-locale.md', '.claude/skills/sungen-locale/SKILL.md'],
|
|
68
|
-
// Mobile (Appium) skills — relevant for platform: mobile (MOB-5).
|
|
69
|
-
['claude-skill-mobile-gestures.md', '.claude/skills/sungen-mobile-gestures/SKILL.md'],
|
|
70
|
-
['claude-skill-capture-mobile.md', '.claude/skills/sungen-capture-mobile/SKILL.md'],
|
|
71
|
-
['claude-skill-selector-fix-mobile.md', '.claude/skills/sungen-selector-fix-mobile/SKILL.md'],
|
|
72
|
-
|
|
73
|
-
// Agents — Claude Code sub-agents (isolated context). Copilot runs these inline.
|
|
74
|
-
['claude-agent-reviewer.md', '.claude/agents/sungen-reviewer.md'],
|
|
75
|
-
['claude-agent-discovery.md', '.claude/agents/sungen-discovery.md'],
|
|
76
|
-
['claude-agent-challenge.md', '.claude/agents/sungen-challenge.md'],
|
|
77
|
-
['claude-agent-generator.md', '.claude/agents/sungen-generator.md'],
|
|
13
|
+
function sungenVersion(): string {
|
|
14
|
+
try { return require(path.join(__dirname, '..', '..', 'package.json')).version || '0.0.0'; }
|
|
15
|
+
catch { return '0.0.0'; }
|
|
16
|
+
}
|
|
78
17
|
|
|
79
|
-
// Skills — GitHub Copilot
|
|
80
|
-
['github-skill-sungen-gherkin-syntax.md', '.github/skills/sungen-gherkin-syntax/SKILL.md'],
|
|
81
|
-
['github-skill-sungen-selector-keys.md', '.github/skills/sungen-selector-keys/SKILL.md'],
|
|
82
|
-
['github-skill-sungen-error-mapping.md', '.github/skills/sungen-error-mapping/SKILL.md'],
|
|
83
|
-
['github-skill-sungen-tc-generation.md', '.github/skills/sungen-tc-generation/SKILL.md'],
|
|
84
|
-
['github-skill-sungen-test-design-techniques.md', '.github/skills/sungen-test-design-techniques/SKILL.md'],
|
|
85
|
-
['github-skill-sungen-selector-fix.md', '.github/skills/sungen-selector-fix/SKILL.md'],
|
|
86
|
-
['github-skill-sungen-tc-review.md', '.github/skills/sungen-tc-review/SKILL.md'],
|
|
87
|
-
['github-skill-sungen-harness-audit.md', '.github/skills/sungen-harness-audit/SKILL.md'],
|
|
88
|
-
['github-skill-sungen-api-design.md', '.github/skills/sungen-api-design/SKILL.md'],
|
|
89
|
-
['github-skill-sungen-ingest-legacy.md', '.github/skills/sungen-ingest-legacy/SKILL.md'],
|
|
90
|
-
['github-skill-sungen-viewpoint.md', '.github/skills/sungen-viewpoint/SKILL.md'],
|
|
91
|
-
['github-skill-sungen-viewpoint-group-a-data-entry.md', '.github/skills/sungen-viewpoint/group-a-data-entry.md'],
|
|
92
|
-
['github-skill-sungen-viewpoint-group-b-data-ops.md', '.github/skills/sungen-viewpoint/group-b-data-ops.md'],
|
|
93
|
-
['github-skill-sungen-viewpoint-group-c-data-explore.md', '.github/skills/sungen-viewpoint/group-c-data-explore.md'],
|
|
94
|
-
['github-skill-sungen-viewpoint-group-d-display.md', '.github/skills/sungen-viewpoint/group-d-display.md'],
|
|
95
|
-
['github-skill-sungen-viewpoint-group-e-identity.md', '.github/skills/sungen-viewpoint/group-e-identity.md'],
|
|
96
|
-
['github-skill-sungen-delivery.md', '.github/skills/sungen-delivery/SKILL.md'],
|
|
97
|
-
['github-skill-sungen-dashboard.md', '.github/skills/sungen-dashboard/SKILL.md'],
|
|
98
|
-
['github-skill-sungen-capture.md', '.github/skills/sungen-capture/SKILL.md'],
|
|
99
|
-
['github-skill-sungen-capture-mode-figma-mcp.md', '.github/skills/sungen-capture/mode-figma-mcp.md'],
|
|
100
|
-
['github-skill-sungen-capture-mode-figma-pat.md', '.github/skills/sungen-capture/mode-figma-pat.md'],
|
|
101
|
-
['github-skill-sungen-capture-mode-live.md', '.github/skills/sungen-capture/mode-live.md'],
|
|
102
|
-
['github-skill-sungen-capture-mode-local.md', '.github/skills/sungen-capture/mode-local.md'],
|
|
103
|
-
['github-skill-sungen-locale.md', '.github/skills/sungen-locale/SKILL.md'],
|
|
104
|
-
// Mobile (Appium) skills — relevant for platform: mobile (MOB-5).
|
|
105
|
-
['github-skill-sungen-mobile-gestures.md', '.github/skills/sungen-mobile-gestures/SKILL.md'],
|
|
106
|
-
['github-skill-sungen-capture-mobile.md', '.github/skills/sungen-capture-mobile/SKILL.md'],
|
|
107
|
-
['github-skill-sungen-selector-fix-mobile.md', '.github/skills/sungen-selector-fix-mobile/SKILL.md'],
|
|
108
|
-
];
|
|
109
18
|
|
|
110
19
|
// Skill/asset directories retired in a previous refactor. `sungen update` removes
|
|
111
20
|
// these so already-initialized projects don't keep loading stale skill descriptions.
|
|
@@ -124,119 +33,48 @@ export const STALE_AI_RULES_PATHS: string[] = [
|
|
|
124
33
|
|
|
125
34
|
export class AIRulesUpdater {
|
|
126
35
|
private cwd: string;
|
|
127
|
-
private aiTemplateDir: string;
|
|
128
36
|
|
|
129
37
|
constructor(cwd: string) {
|
|
130
38
|
this.cwd = cwd;
|
|
131
|
-
this.aiTemplateDir = path.join(__dirname, 'templates', 'ai-instructions');
|
|
132
39
|
}
|
|
133
40
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
for (
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (!fs.existsSync(templatePath)) {
|
|
147
|
-
missing.push(templateFile);
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const newContent = fs.readFileSync(templatePath, 'utf-8');
|
|
152
|
-
|
|
153
|
-
if (fs.existsSync(outputPath)) {
|
|
154
|
-
const currentContent = fs.readFileSync(outputPath, 'utf-8');
|
|
155
|
-
if (currentContent === newContent) {
|
|
156
|
-
unchanged.push(outputRelPath);
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (!dryRun) {
|
|
161
|
-
fs.writeFileSync(outputPath, newContent, 'utf-8');
|
|
162
|
-
}
|
|
163
|
-
updated.push(outputRelPath);
|
|
164
|
-
} else {
|
|
165
|
-
if (!dryRun) {
|
|
166
|
-
const outputDir = path.dirname(outputPath);
|
|
167
|
-
if (!fs.existsSync(outputDir)) {
|
|
168
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
169
|
-
}
|
|
170
|
-
fs.writeFileSync(outputPath, newContent, 'utf-8');
|
|
171
|
-
}
|
|
172
|
-
created.push(outputRelPath);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Remove retired skills/assets so stale descriptions stop loading.
|
|
41
|
+
/**
|
|
42
|
+
* Refresh AI rules/commands/skills from the single-source generator.
|
|
43
|
+
* @param dryRun show changes without writing
|
|
44
|
+
* @param opts.agents which assistants to install (default: claude — decision T5)
|
|
45
|
+
* @param opts.force overwrite user config files (CLAUDE.md/AGENTS.md/copilot-instructions)
|
|
46
|
+
*/
|
|
47
|
+
async update(dryRun: boolean, opts: { agents?: AdapterKey[]; force?: boolean } = {}): Promise<void> {
|
|
48
|
+
const agents = opts.agents && opts.agents.length ? opts.agents : (['claude'] as AdapterKey[]);
|
|
49
|
+
console.log(`🔄 Updating AI rules for: ${agents.join(', ')}${dryRun ? ' (dry-run)' : ''}\n`);
|
|
50
|
+
|
|
51
|
+
// One-time legacy cleanup for projects created before the manifest existed.
|
|
177
52
|
const removed: string[] = [];
|
|
178
53
|
for (const staleRelPath of STALE_AI_RULES_PATHS) {
|
|
179
54
|
const stalePath = path.join(this.cwd, staleRelPath);
|
|
180
55
|
if (fs.existsSync(stalePath)) {
|
|
181
|
-
if (!dryRun) {
|
|
182
|
-
fs.rmSync(stalePath, { recursive: true, force: true });
|
|
183
|
-
}
|
|
56
|
+
if (!dryRun) fs.rmSync(stalePath, { recursive: true, force: true });
|
|
184
57
|
removed.push(staleRelPath);
|
|
185
58
|
}
|
|
186
59
|
}
|
|
187
60
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
61
|
+
const outputs = buildOutputs(agents);
|
|
62
|
+
const r = applyOutputs(this.cwd, outputs, { version: sungenVersion(), dryRun, force: opts.force });
|
|
63
|
+
|
|
64
|
+
if (dryRun) console.log('📋 Dry run — no files changed\n');
|
|
65
|
+
if (removed.length) console.log(`🗑️ Removed retired assets (${removed.length})`);
|
|
66
|
+
if (r.deletedOrphans.length) console.log(`🗑️ Removed orphans (${r.deletedOrphans.length}): ${r.deletedOrphans.join(', ')}`);
|
|
67
|
+
if (r.created.length) console.log(`✨ Created (${r.created.length})`);
|
|
68
|
+
if (r.overwritten.length) console.log(`✏️ Updated (${r.overwritten.length})`);
|
|
69
|
+
if (r.skippedConfig.length) console.log(`⏭️ Config preserved (use --force to overwrite): ${r.skippedConfig.join(', ')}`);
|
|
70
|
+
if (r.handEditWarnings.length) {
|
|
71
|
+
console.log(`\n⚠️ Overwrote files that look hand-edited (sungen owns these — version-managed):`);
|
|
72
|
+
for (const f of r.handEditWarnings) console.log(` ${f}`);
|
|
191
73
|
}
|
|
192
74
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
198
|
-
console.log();
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (updated.length > 0) {
|
|
202
|
-
console.log(`✏️ Updated (${updated.length}):`);
|
|
203
|
-
for (const f of updated) {
|
|
204
|
-
console.log(` ${f}`);
|
|
205
|
-
}
|
|
206
|
-
console.log();
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (created.length > 0) {
|
|
210
|
-
console.log(`✨ Created (${created.length}):`);
|
|
211
|
-
for (const f of created) {
|
|
212
|
-
console.log(` ${f}`);
|
|
213
|
-
}
|
|
214
|
-
console.log();
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
if (unchanged.length > 0) {
|
|
218
|
-
console.log(`✅ Already up to date (${unchanged.length}):`);
|
|
219
|
-
for (const f of unchanged) {
|
|
220
|
-
console.log(` ${f}`);
|
|
221
|
-
}
|
|
222
|
-
console.log();
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (missing.length > 0) {
|
|
226
|
-
console.log(`⚠️ Template not found (${missing.length}):`);
|
|
227
|
-
for (const f of missing) {
|
|
228
|
-
console.log(` ${f}`);
|
|
229
|
-
}
|
|
230
|
-
console.log();
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const totalChanges = updated.length + created.length;
|
|
234
|
-
if (totalChanges === 0) {
|
|
235
|
-
console.log('All AI rules are up to date. No changes needed.');
|
|
236
|
-
} else if (dryRun) {
|
|
237
|
-
console.log(`${totalChanges} file(s) would be changed. Run without --dry-run to apply.`);
|
|
238
|
-
} else {
|
|
239
|
-
console.log(`${totalChanges} file(s) updated successfully.`);
|
|
240
|
-
}
|
|
75
|
+
const total = r.created.length + r.overwritten.length;
|
|
76
|
+
if (total === 0 && !removed.length && !r.deletedOrphans.length) console.log('All AI rules are up to date. No changes needed.');
|
|
77
|
+
else if (dryRun) console.log(`\n${total} file(s) would change. Run without --dry-run to apply.`);
|
|
78
|
+
else console.log(`\n${total} file(s) updated for ${agents.join(', ')}.`);
|
|
241
79
|
}
|
|
242
80
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter table — one row per assistant. Adding a new assistant = one row here,
|
|
3
|
+
* zero new content files (the whole point of the single-source migration).
|
|
4
|
+
*
|
|
5
|
+
* Output paths preserve the EXACT existing Claude/Copilot conventions (decision 4A) so the
|
|
6
|
+
* golden-regression net stays byte-identical for Claude. Codex is additive (`.agents/skills/`).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export type AdapterKey = 'claude' | 'copilot' | 'codex';
|
|
10
|
+
|
|
11
|
+
export interface Adapter {
|
|
12
|
+
key: AdapterKey;
|
|
13
|
+
/** capability tags this adapter owns; cap-fences resolve against this */
|
|
14
|
+
caps: string[];
|
|
15
|
+
/** output path for a `kind: skill` unit, given the skill dir name + relative file */
|
|
16
|
+
skillPath: (skillDir: string, file: string) => string;
|
|
17
|
+
/** output path for a `kind: command` unit; null => commands render as skills */
|
|
18
|
+
commandPath: ((name: string) => string) | null;
|
|
19
|
+
/**
|
|
20
|
+
* When commandPath is null (Codex), a command renders into the skill tree. This computes
|
|
21
|
+
* the skill dir for a command, and a backing skill whose name collides gets a `-guide`
|
|
22
|
+
* suffix (the flat-namespace collision found during spike prep: delivery/dashboard/locale).
|
|
23
|
+
*/
|
|
24
|
+
commandAsSkillDir?: (name: string) => string;
|
|
25
|
+
/** Codex needs an explicit trigger prefixed onto the command-skill description */
|
|
26
|
+
commandTriggerPrefix?: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const ADAPTERS: Record<AdapterKey, Adapter> = {
|
|
30
|
+
claude: {
|
|
31
|
+
key: 'claude',
|
|
32
|
+
caps: ['parallel-subagents'],
|
|
33
|
+
skillPath: (dir, file) => `.claude/skills/${dir}/${file}`,
|
|
34
|
+
commandPath: (name) => `.claude/commands/sungen/${name}.md`,
|
|
35
|
+
},
|
|
36
|
+
copilot: {
|
|
37
|
+
key: 'copilot',
|
|
38
|
+
caps: [],
|
|
39
|
+
skillPath: (dir, file) => `.github/skills/${dir}/${file}`,
|
|
40
|
+
commandPath: (name) => `.github/prompts/sungen-${name}.prompt.md`,
|
|
41
|
+
},
|
|
42
|
+
codex: {
|
|
43
|
+
key: 'codex',
|
|
44
|
+
caps: [],
|
|
45
|
+
skillPath: (dir, file) => `.agents/skills/${dir}/${file}`,
|
|
46
|
+
commandPath: null, // commands become skills
|
|
47
|
+
commandAsSkillDir: (name) => `.agents/skills/sungen-${name}`,
|
|
48
|
+
commandTriggerPrefix: true,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const ALL_ADAPTERS: AdapterKey[] = ['claude', 'copilot', 'codex'];
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* buildOutputs — the single entry point init/update call (decision 1A).
|
|
3
|
+
* Produces the full [outputPath, content, class] set for the selected adapters from the
|
|
4
|
+
* canonical source. Pure: never touches disk.
|
|
5
|
+
*
|
|
6
|
+
* class:
|
|
7
|
+
* 'managed' — skill/command files; sungen owns them, always overwritten (version-managed)
|
|
8
|
+
* 'config' — CLAUDE.md / copilot-instructions.md / AGENTS.md; user-customizable,
|
|
9
|
+
* skip-if-exists unless --force (decision 2)
|
|
10
|
+
*/
|
|
11
|
+
import * as fs from 'fs';
|
|
12
|
+
import * as path from 'path';
|
|
13
|
+
import { stripCaps } from './cap-stripper';
|
|
14
|
+
import { ADAPTERS, AdapterKey } from './adapters';
|
|
15
|
+
import { parseCommandSource, generateCommand } from './commands';
|
|
16
|
+
|
|
17
|
+
export type FileClass = 'managed' | 'config';
|
|
18
|
+
export interface BuiltFile {
|
|
19
|
+
outputPath: string;
|
|
20
|
+
content: string;
|
|
21
|
+
cls: FileClass;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const SRC_SKILLS = path.resolve(__dirname, '..', 'templates', 'ai-src', 'skills');
|
|
25
|
+
const SRC_CMDS = path.resolve(__dirname, '..', 'templates', 'ai-src', 'commands');
|
|
26
|
+
const SRC_AGENTS = path.resolve(__dirname, '..', 'templates', 'ai-src', 'agents');
|
|
27
|
+
const SRC_CONFIG = path.resolve(__dirname, '..', 'templates', 'ai-src', 'config');
|
|
28
|
+
|
|
29
|
+
// Config files per adapter: [source file under ai-src/config, outputPath].
|
|
30
|
+
const CONFIG: Record<AdapterKey, { src: string; out: string }> = {
|
|
31
|
+
claude: { src: 'claude.md', out: 'CLAUDE.md' },
|
|
32
|
+
copilot: { src: 'copilot.md', out: '.github/copilot-instructions.md' },
|
|
33
|
+
codex: { src: 'codex.md', out: 'AGENTS.md' },
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
function commandIds(): Set<string> {
|
|
37
|
+
if (!fs.existsSync(SRC_CMDS)) return new Set();
|
|
38
|
+
return new Set(fs.readdirSync(SRC_CMDS).filter((f) => f.endsWith('.md')).map((f) => f.replace(/\.md$/, '')));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Build every output file for the given adapters. */
|
|
42
|
+
export function buildOutputs(adapters: AdapterKey[]): BuiltFile[] {
|
|
43
|
+
const out: BuiltFile[] = [];
|
|
44
|
+
const cmdIds = commandIds();
|
|
45
|
+
|
|
46
|
+
for (const key of adapters) {
|
|
47
|
+
const adapter = ADAPTERS[key];
|
|
48
|
+
|
|
49
|
+
// --- Skills ---
|
|
50
|
+
if (fs.existsSync(SRC_SKILLS)) {
|
|
51
|
+
for (const skillDir of fs.readdirSync(SRC_SKILLS)) {
|
|
52
|
+
const dirPath = path.join(SRC_SKILLS, skillDir);
|
|
53
|
+
if (!fs.statSync(dirPath).isDirectory()) continue;
|
|
54
|
+
// Codex flat namespace: a skill whose name collides with a command becomes <dir>-guide.
|
|
55
|
+
// Both the output dir AND the SKILL.md `name:` frontmatter must change, or Codex would
|
|
56
|
+
// discover two skills with the same `name` (breaking $name + description selection).
|
|
57
|
+
const bare = skillDir.replace(/^sungen-/, '');
|
|
58
|
+
const collide = key === 'codex' && cmdIds.has(bare);
|
|
59
|
+
const outDir = collide ? `${skillDir}-guide` : skillDir;
|
|
60
|
+
for (const file of fs.readdirSync(dirPath)) {
|
|
61
|
+
if (!file.endsWith('.md')) continue;
|
|
62
|
+
let raw = fs.readFileSync(path.join(dirPath, file), 'utf8');
|
|
63
|
+
if (collide && file === 'SKILL.md') {
|
|
64
|
+
raw = raw.replace(/^(name:\s*)sungen-[^\n]*/m, `$1sungen-${bare}-guide`);
|
|
65
|
+
}
|
|
66
|
+
out.push({
|
|
67
|
+
outputPath: adapter.skillPath(outDir, file),
|
|
68
|
+
content: stripCaps(raw, adapter.caps, `${skillDir}/${file}`),
|
|
69
|
+
cls: 'managed',
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// --- Commands ---
|
|
76
|
+
if (fs.existsSync(SRC_CMDS)) {
|
|
77
|
+
for (const f of fs.readdirSync(SRC_CMDS)) {
|
|
78
|
+
if (!f.endsWith('.md')) continue;
|
|
79
|
+
const id = f.replace(/\.md$/, '');
|
|
80
|
+
const src = parseCommandSource(fs.readFileSync(path.join(SRC_CMDS, f), 'utf8'), id);
|
|
81
|
+
const g = generateCommand(src, key);
|
|
82
|
+
out.push({ outputPath: g.outputPath, content: g.content, cls: 'managed' });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// --- Agents (Claude-only sub-agents; Copilot runs them inline, Codex has no equivalent) ---
|
|
87
|
+
if (key === 'claude' && fs.existsSync(SRC_AGENTS)) {
|
|
88
|
+
for (const f of fs.readdirSync(SRC_AGENTS)) {
|
|
89
|
+
if (!f.endsWith('.md')) continue;
|
|
90
|
+
const role = f.replace(/\.md$/, '');
|
|
91
|
+
const raw = fs.readFileSync(path.join(SRC_AGENTS, f), 'utf8');
|
|
92
|
+
out.push({ outputPath: `.claude/agents/sungen-${role}.md`, content: stripCaps(raw, adapter.caps, `agents/${f}`), cls: 'managed' });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// --- Config (skip-unless-force) ---
|
|
97
|
+
const cfg = CONFIG[key];
|
|
98
|
+
const content = fs.readFileSync(path.join(SRC_CONFIG, cfg.src), 'utf8');
|
|
99
|
+
out.push({ outputPath: cfg.out, content, cls: 'config' });
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cap-fence stripper for single-source AI skill templates.
|
|
3
|
+
*
|
|
4
|
+
* A single source body may contain capability-fenced blocks that are kept or dropped
|
|
5
|
+
* per target adapter:
|
|
6
|
+
*
|
|
7
|
+
* {{#cap parallel-subagents}} ... kept only if the adapter HAS the cap ... {{/cap}}
|
|
8
|
+
* {{^cap parallel-subagents}} ... kept only if the adapter LACKS the cap ... {{/cap}}
|
|
9
|
+
*
|
|
10
|
+
* Fence lines must be on their own line. Nesting is forbidden. Unknown cap tags and
|
|
11
|
+
* unclosed fences FAIL LOUD (decision 5A) so a typo can never silently delete content.
|
|
12
|
+
*
|
|
13
|
+
* Blank lines left where a block is removed are normalized (no run of 3+ blank lines),
|
|
14
|
+
* so the diff-regression golden net stays quiet (decision 3A).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// Central list of valid capability tags. Adding a capability = adding it here.
|
|
18
|
+
// Measured divergence (2026-06-27) shows essentially one axis today.
|
|
19
|
+
export const VALID_CAPS = ['parallel-subagents'] as const;
|
|
20
|
+
export type Cap = (typeof VALID_CAPS)[number];
|
|
21
|
+
|
|
22
|
+
const OPEN_POS = /^\s*\{\{#cap\s+([a-z0-9-]+)\s*\}\}\s*$/;
|
|
23
|
+
const OPEN_NEG = /^\s*\{\{\^cap\s+([a-z0-9-]+)\s*\}\}\s*$/;
|
|
24
|
+
const CLOSE = /^\s*\{\{\/cap\}\}\s*$/;
|
|
25
|
+
|
|
26
|
+
export class CapFenceError extends Error {}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Render `body` for an adapter that owns `caps`.
|
|
30
|
+
* @param body raw single-source body (frontmatter already removed)
|
|
31
|
+
* @param caps capability tags the target adapter has
|
|
32
|
+
* @param skillName for error messages
|
|
33
|
+
*/
|
|
34
|
+
export function stripCaps(body: string, caps: readonly string[], skillName = '<unknown>'): string {
|
|
35
|
+
const has = (tag: string) => caps.includes(tag);
|
|
36
|
+
const out: string[] = [];
|
|
37
|
+
let open: { tag: string; keep: boolean; line: number } | null = null;
|
|
38
|
+
|
|
39
|
+
const lines = body.split('\n');
|
|
40
|
+
for (let i = 0; i < lines.length; i++) {
|
|
41
|
+
const line = lines[i];
|
|
42
|
+
const mPos = line.match(OPEN_POS);
|
|
43
|
+
const mNeg = line.match(OPEN_NEG);
|
|
44
|
+
const mClose = CLOSE.test(line);
|
|
45
|
+
|
|
46
|
+
if (mPos || mNeg) {
|
|
47
|
+
if (open) {
|
|
48
|
+
throw new CapFenceError(
|
|
49
|
+
`${skillName}: nested cap fence at line ${i + 1} (already inside {{#cap ${open.tag}}} from line ${open.line}); nesting is forbidden`,
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
const tag = (mPos ? mPos[1] : mNeg![1]);
|
|
53
|
+
if (!VALID_CAPS.includes(tag as Cap)) {
|
|
54
|
+
throw new CapFenceError(
|
|
55
|
+
`${skillName}: unknown cap tag "${tag}" at line ${i + 1} (valid: ${VALID_CAPS.join(', ')})`,
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
// positive: keep when adapter HAS cap; negative: keep when adapter LACKS cap
|
|
59
|
+
open = { tag, keep: mPos ? has(tag) : !has(tag), line: i + 1 };
|
|
60
|
+
continue; // fence line itself is never emitted
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (mClose) {
|
|
64
|
+
if (!open) {
|
|
65
|
+
throw new CapFenceError(`${skillName}: stray {{/cap}} at line ${i + 1} with no open fence`);
|
|
66
|
+
}
|
|
67
|
+
open = null;
|
|
68
|
+
continue; // fence line itself is never emitted
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (open) {
|
|
72
|
+
if (open.keep) out.push(line);
|
|
73
|
+
// dropped block: skip the line
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
out.push(line);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (open) {
|
|
80
|
+
throw new CapFenceError(`${skillName}: unclosed {{#cap ${open.tag}}} opened at line ${open.line}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Normalize: collapse 3+ consecutive blank lines (left by removed blocks) to one.
|
|
84
|
+
return out.join('\n').replace(/\n{3,}/g, '\n\n');
|
|
85
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command generator. Commands diverge per-adapter in BOTH frontmatter shape and body
|
|
3
|
+
* (measured 2026-06-27: all 10 pairs differ, create-test by 123 lines). Claude output must
|
|
4
|
+
* be byte-identical (gate); Copilot/Codex are re-derived from the canonical source (lenient).
|
|
5
|
+
*
|
|
6
|
+
* Source: templates/ai-src/commands/<name>.md
|
|
7
|
+
* ---
|
|
8
|
+
* name: create-test
|
|
9
|
+
* description: "<canonical Claude description>"
|
|
10
|
+
* argument-hint: "[screen-name]"
|
|
11
|
+
* order: 20
|
|
12
|
+
* claude-tools: "Read, Grep, ..." # verbatim allowed-tools line for Claude
|
|
13
|
+
* codex-trigger: "Run when the user asks to ..." # explicit trigger for Codex (P2 mitigation)
|
|
14
|
+
* copilot-tools: "[vscode, execute, ...]" # optional; default used if absent
|
|
15
|
+
* ---
|
|
16
|
+
* <body with cap-fences>
|
|
17
|
+
*/
|
|
18
|
+
import { stripCaps } from './cap-stripper';
|
|
19
|
+
import { GenFile } from './generator';
|
|
20
|
+
|
|
21
|
+
export interface CommandSource {
|
|
22
|
+
id: string; // command identity (from source filename) — drives output paths
|
|
23
|
+
name: string; // frontmatter `name:` value; '' means the original had no name line
|
|
24
|
+
description: string;
|
|
25
|
+
argumentHint: string; // raw, e.g. "[screen-name]"
|
|
26
|
+
order?: number;
|
|
27
|
+
claudeTools: string;
|
|
28
|
+
copilotTools: string;
|
|
29
|
+
codexTrigger: string;
|
|
30
|
+
body: string; // with cap-fences
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const DEFAULT_COPILOT_TOOLS = '[vscode, execute, read, edit, search, todo]';
|
|
34
|
+
|
|
35
|
+
/** Parse a source command file into a CommandSource. */
|
|
36
|
+
export function parseCommandSource(text: string, id: string): CommandSource {
|
|
37
|
+
const end = text.indexOf('\n---', 3);
|
|
38
|
+
const raw: Record<string, string> = {};
|
|
39
|
+
for (const line of text.slice(3, end).trim().split('\n')) {
|
|
40
|
+
const m = line.match(/^([a-zA-Z_-]+):\s*(.*)$/);
|
|
41
|
+
if (m) raw[m[1]] = m[2];
|
|
42
|
+
}
|
|
43
|
+
// JSON-encoded fields decode losslessly; argument-hint is kept VERBATIM so Claude output
|
|
44
|
+
// reproduces the original quoting (some commands quote it, some don't).
|
|
45
|
+
const dec = (k: string): string => {
|
|
46
|
+
const v = raw[k];
|
|
47
|
+
if (v == null) return '';
|
|
48
|
+
if (v.startsWith('"')) { try { return JSON.parse(v); } catch { /* fall through */ } }
|
|
49
|
+
return v.replace(/^['"]|['"]$/g, '');
|
|
50
|
+
};
|
|
51
|
+
const body = text.slice(end + 4).replace(/^\n+/, '');
|
|
52
|
+
return {
|
|
53
|
+
id,
|
|
54
|
+
name: raw['name'] != null ? dec('name') : '',
|
|
55
|
+
description: dec('description'),
|
|
56
|
+
argumentHint: raw['argument-hint'] || '', // verbatim
|
|
57
|
+
order: raw.order ? Number(raw.order) : undefined,
|
|
58
|
+
claudeTools: dec('claude-tools'),
|
|
59
|
+
copilotTools: raw['copilot-tools'] ? dec('copilot-tools') : DEFAULT_COPILOT_TOOLS,
|
|
60
|
+
codexTrigger: dec('codex-trigger'),
|
|
61
|
+
body,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const unquote = (s: string) => s.replace(/^['"]|['"]$/g, '');
|
|
66
|
+
|
|
67
|
+
/** Claude command file — MUST reproduce the exact existing format (byte-identical gate). */
|
|
68
|
+
export function renderClaudeCommand(c: CommandSource): string {
|
|
69
|
+
const fm = [
|
|
70
|
+
'---',
|
|
71
|
+
...(c.name ? [`name: ${c.name}`] : []), // some commands (locale) omit name
|
|
72
|
+
`description: '${c.description}'`,
|
|
73
|
+
`argument-hint: ${c.argumentHint}`,
|
|
74
|
+
`allowed-tools: ${c.claudeTools}`,
|
|
75
|
+
'---',
|
|
76
|
+
].join('\n');
|
|
77
|
+
return fm + '\n\n' + stripCaps(c.body, ['parallel-subagents'], `cmd:${c.id}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Copilot prompt file — re-derived (lenient). */
|
|
81
|
+
export function renderCopilotCommand(c: CommandSource): string {
|
|
82
|
+
const fm = [
|
|
83
|
+
'---',
|
|
84
|
+
`name: sungen-${c.id}`,
|
|
85
|
+
`description: '${c.description}'`,
|
|
86
|
+
`argument-hint: '${unquote(c.argumentHint)}'`,
|
|
87
|
+
`agent: 'agent'`,
|
|
88
|
+
`tools: ${c.copilotTools}`,
|
|
89
|
+
'---',
|
|
90
|
+
].join('\n');
|
|
91
|
+
return fm + '\n\n' + stripCaps(c.body, [], `cmd:${c.id}`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Codex command-skill — command folds into a skill with an explicit trigger (decision P2). */
|
|
95
|
+
export function renderCodexCommand(c: CommandSource): string {
|
|
96
|
+
const desc = c.codexTrigger ? `${c.codexTrigger}` : c.description;
|
|
97
|
+
const fm = [
|
|
98
|
+
'---',
|
|
99
|
+
`name: sungen-${c.id}`,
|
|
100
|
+
`description: ${JSON.stringify(desc)}`,
|
|
101
|
+
`kind: command`,
|
|
102
|
+
...(c.order != null ? [`order: ${c.order}`] : []),
|
|
103
|
+
'---',
|
|
104
|
+
].join('\n');
|
|
105
|
+
return fm + '\n\n' + stripCaps(c.body, [], `cmd:${c.id}`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function generateCommand(c: CommandSource, adapter: 'claude' | 'copilot' | 'codex'): GenFile {
|
|
109
|
+
if (adapter === 'claude') return { outputPath: `.claude/commands/sungen/${c.id}.md`, content: renderClaudeCommand(c) };
|
|
110
|
+
if (adapter === 'copilot') return { outputPath: `.github/prompts/sungen-${c.id}.prompt.md`, content: renderCopilotCommand(c) };
|
|
111
|
+
return { outputPath: `.agents/skills/sungen-${c.id}/SKILL.md`, content: renderCodexCommand(c) };
|
|
112
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-source generator (decision 1A).
|
|
3
|
+
*
|
|
4
|
+
* Produces an in-memory list of [outputPath, content] pairs from canonical source skill
|
|
5
|
+
* files, for the selected adapters. `init` and `update` consume this list and keep their own
|
|
6
|
+
* write semantics — this module never touches disk.
|
|
7
|
+
*
|
|
8
|
+
* Source layout (canonical = Claude content, decision 2):
|
|
9
|
+
* templates/ai-src/skills/<skillDir>/<file>.md (kind: skill, possibly multi-file)
|
|
10
|
+
* templates/ai-src/commands/<name>.md (kind: command) [wired in a later step]
|
|
11
|
+
*
|
|
12
|
+
* Each source file may contain cap-fences ({{#cap}} / {{^cap}}) for per-adapter deltas.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import * as fs from 'fs';
|
|
16
|
+
import * as path from 'path';
|
|
17
|
+
import { stripCaps } from './cap-stripper';
|
|
18
|
+
import { ADAPTERS, AdapterKey } from './adapters';
|
|
19
|
+
|
|
20
|
+
export interface GenFile {
|
|
21
|
+
outputPath: string; // repo-relative
|
|
22
|
+
content: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Render all skill units under `srcSkillsDir` for one adapter. */
|
|
26
|
+
export function generateSkills(srcSkillsDir: string, adapterKey: AdapterKey): GenFile[] {
|
|
27
|
+
const adapter = ADAPTERS[adapterKey];
|
|
28
|
+
const out: GenFile[] = [];
|
|
29
|
+
if (!fs.existsSync(srcSkillsDir)) return out;
|
|
30
|
+
|
|
31
|
+
for (const skillDir of fs.readdirSync(srcSkillsDir)) {
|
|
32
|
+
const dirPath = path.join(srcSkillsDir, skillDir);
|
|
33
|
+
if (!fs.statSync(dirPath).isDirectory()) continue;
|
|
34
|
+
for (const file of fs.readdirSync(dirPath)) {
|
|
35
|
+
if (!file.endsWith('.md')) continue;
|
|
36
|
+
const raw = fs.readFileSync(path.join(dirPath, file), 'utf8');
|
|
37
|
+
const content = stripCaps(raw, adapter.caps, `${skillDir}/${file}`);
|
|
38
|
+
out.push({ outputPath: adapter.skillPath(skillDir, file), content });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Render for several adapters at once. */
|
|
45
|
+
export function generate(srcSkillsDir: string, adapters: AdapterKey[]): GenFile[] {
|
|
46
|
+
return adapters.flatMap((a) => generateSkills(srcSkillsDir, a));
|
|
47
|
+
}
|