@specforge/cli 0.1.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.
- package/README.md +781 -0
- package/bin/specforge +21 -0
- package/dist/channel.d.ts +27 -0
- package/dist/channel.d.ts.map +1 -0
- package/dist/channel.js +22 -0
- package/dist/channel.js.map +1 -0
- package/dist/cli/commands/configure.d.ts +16 -0
- package/dist/cli/commands/configure.d.ts.map +1 -0
- package/dist/cli/commands/configure.js +186 -0
- package/dist/cli/commands/configure.js.map +1 -0
- package/dist/cli/commands/configure.types.d.ts +110 -0
- package/dist/cli/commands/configure.types.d.ts.map +1 -0
- package/dist/cli/commands/configure.types.js +82 -0
- package/dist/cli/commands/configure.types.js.map +1 -0
- package/dist/cli/commands/debug/call.d.ts +14 -0
- package/dist/cli/commands/debug/call.d.ts.map +1 -0
- package/dist/cli/commands/debug/call.js +96 -0
- package/dist/cli/commands/debug/call.js.map +1 -0
- package/dist/cli/commands/debug/index.d.ts +12 -0
- package/dist/cli/commands/debug/index.d.ts.map +1 -0
- package/dist/cli/commands/debug/index.js +14 -0
- package/dist/cli/commands/debug/index.js.map +1 -0
- package/dist/cli/commands/debug/register.d.ts +11 -0
- package/dist/cli/commands/debug/register.d.ts.map +1 -0
- package/dist/cli/commands/debug/register.js +78 -0
- package/dist/cli/commands/debug/register.js.map +1 -0
- package/dist/cli/commands/debug/test.d.ts +13 -0
- package/dist/cli/commands/debug/test.d.ts.map +1 -0
- package/dist/cli/commands/debug/test.js +91 -0
- package/dist/cli/commands/debug/test.js.map +1 -0
- package/dist/cli/commands/debug/tools.d.ts +13 -0
- package/dist/cli/commands/debug/tools.d.ts.map +1 -0
- package/dist/cli/commands/debug/tools.js +86 -0
- package/dist/cli/commands/debug/tools.js.map +1 -0
- package/dist/cli/commands/debug/types.d.ts +119 -0
- package/dist/cli/commands/debug/types.d.ts.map +1 -0
- package/dist/cli/commands/debug/types.js +36 -0
- package/dist/cli/commands/debug/types.js.map +1 -0
- package/dist/cli/commands/debug/whoami.d.ts +13 -0
- package/dist/cli/commands/debug/whoami.d.ts.map +1 -0
- package/dist/cli/commands/debug/whoami.js +131 -0
- package/dist/cli/commands/debug/whoami.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +16 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +413 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/doctor.types.d.ts +180 -0
- package/dist/cli/commands/doctor.types.d.ts.map +1 -0
- package/dist/cli/commands/doctor.types.js +140 -0
- package/dist/cli/commands/doctor.types.js.map +1 -0
- package/dist/cli/commands/feedback.d.ts +27 -0
- package/dist/cli/commands/feedback.d.ts.map +1 -0
- package/dist/cli/commands/feedback.js +262 -0
- package/dist/cli/commands/feedback.js.map +1 -0
- package/dist/cli/commands/feedback.types.d.ts +116 -0
- package/dist/cli/commands/feedback.types.d.ts.map +1 -0
- package/dist/cli/commands/feedback.types.js +65 -0
- package/dist/cli/commands/feedback.types.js.map +1 -0
- package/dist/cli/commands/index.d.ts +15 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/index.js +21 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/init.d.ts +17 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +773 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/init.types.d.ts +193 -0
- package/dist/cli/commands/init.types.d.ts.map +1 -0
- package/dist/cli/commands/init.types.js +29 -0
- package/dist/cli/commands/init.types.js.map +1 -0
- package/dist/cli/commands/invitations.d.ts +31 -0
- package/dist/cli/commands/invitations.d.ts.map +1 -0
- package/dist/cli/commands/invitations.js +250 -0
- package/dist/cli/commands/invitations.js.map +1 -0
- package/dist/cli/commands/login.d.ts +40 -0
- package/dist/cli/commands/login.d.ts.map +1 -0
- package/dist/cli/commands/login.js +139 -0
- package/dist/cli/commands/login.js.map +1 -0
- package/dist/cli/commands/members.d.ts +55 -0
- package/dist/cli/commands/members.d.ts.map +1 -0
- package/dist/cli/commands/members.js +296 -0
- package/dist/cli/commands/members.js.map +1 -0
- package/dist/cli/commands/scaffold/agent-types.d.ts +54 -0
- package/dist/cli/commands/scaffold/agent-types.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/agent-types.js +22 -0
- package/dist/cli/commands/scaffold/agent-types.js.map +1 -0
- package/dist/cli/commands/scaffold/display.d.ts +56 -0
- package/dist/cli/commands/scaffold/display.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/display.js +217 -0
- package/dist/cli/commands/scaffold/display.js.map +1 -0
- package/dist/cli/commands/scaffold/files.d.ts +99 -0
- package/dist/cli/commands/scaffold/files.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/files.js +122 -0
- package/dist/cli/commands/scaffold/files.js.map +1 -0
- package/dist/cli/commands/scaffold/index.d.ts +13 -0
- package/dist/cli/commands/scaffold/index.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/index.js +12 -0
- package/dist/cli/commands/scaffold/index.js.map +1 -0
- package/dist/cli/commands/scaffold/register.d.ts +11 -0
- package/dist/cli/commands/scaffold/register.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/register.js +11 -0
- package/dist/cli/commands/scaffold/register.js.map +1 -0
- package/dist/cli/commands/scaffold/scaffold.d.ts +11 -0
- package/dist/cli/commands/scaffold/scaffold.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/scaffold.js +728 -0
- package/dist/cli/commands/scaffold/scaffold.js.map +1 -0
- package/dist/cli/commands/scaffold/targets.d.ts +60 -0
- package/dist/cli/commands/scaffold/targets.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/targets.js +251 -0
- package/dist/cli/commands/scaffold/targets.js.map +1 -0
- package/dist/cli/commands/scaffold/types.d.ts +170 -0
- package/dist/cli/commands/scaffold/types.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/types.js +12 -0
- package/dist/cli/commands/scaffold/types.js.map +1 -0
- package/dist/cli/commands/scaffold/utils.d.ts +89 -0
- package/dist/cli/commands/scaffold/utils.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/utils.js +401 -0
- package/dist/cli/commands/scaffold/utils.js.map +1 -0
- package/dist/cli/commands/status.d.ts +19 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +124 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/status.types.d.ts +37 -0
- package/dist/cli/commands/status.types.d.ts.map +1 -0
- package/dist/cli/commands/status.types.js +7 -0
- package/dist/cli/commands/status.types.js.map +1 -0
- package/dist/cli/commands/switch.d.ts +18 -0
- package/dist/cli/commands/switch.d.ts.map +1 -0
- package/dist/cli/commands/switch.js +134 -0
- package/dist/cli/commands/switch.js.map +1 -0
- package/dist/cli/commands/switch.types.d.ts +123 -0
- package/dist/cli/commands/switch.types.d.ts.map +1 -0
- package/dist/cli/commands/switch.types.js +46 -0
- package/dist/cli/commands/switch.types.js.map +1 -0
- package/dist/cli/config/agent-teams.types.d.ts +120 -0
- package/dist/cli/config/agent-teams.types.d.ts.map +1 -0
- package/dist/cli/config/agent-teams.types.js +23 -0
- package/dist/cli/config/agent-teams.types.js.map +1 -0
- package/dist/cli/config/index.d.ts +13 -0
- package/dist/cli/config/index.d.ts.map +1 -0
- package/dist/cli/config/index.js +7 -0
- package/dist/cli/config/index.js.map +1 -0
- package/dist/cli/config/loader.d.ts +114 -0
- package/dist/cli/config/loader.d.ts.map +1 -0
- package/dist/cli/config/loader.js +198 -0
- package/dist/cli/config/loader.js.map +1 -0
- package/dist/cli/config/paths.d.ts +107 -0
- package/dist/cli/config/paths.d.ts.map +1 -0
- package/dist/cli/config/paths.js +79 -0
- package/dist/cli/config/paths.js.map +1 -0
- package/dist/cli/config/planning-sessions-registry.d.ts +52 -0
- package/dist/cli/config/planning-sessions-registry.d.ts.map +1 -0
- package/dist/cli/config/planning-sessions-registry.js +46 -0
- package/dist/cli/config/planning-sessions-registry.js.map +1 -0
- package/dist/cli/config/types.d.ts +186 -0
- package/dist/cli/config/types.d.ts.map +1 -0
- package/dist/cli/config/types.js +27 -0
- package/dist/cli/config/types.js.map +1 -0
- package/dist/cli/config/validation.d.ts +62 -0
- package/dist/cli/config/validation.d.ts.map +1 -0
- package/dist/cli/config/validation.js +133 -0
- package/dist/cli/config/validation.js.map +1 -0
- package/dist/cli/config/writer.d.ts +153 -0
- package/dist/cli/config/writer.d.ts.map +1 -0
- package/dist/cli/config/writer.js +168 -0
- package/dist/cli/config/writer.js.map +1 -0
- package/dist/cli/index.d.ts +30 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +142 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/middleware/auth-guard.d.ts +107 -0
- package/dist/cli/middleware/auth-guard.d.ts.map +1 -0
- package/dist/cli/middleware/auth-guard.js +97 -0
- package/dist/cli/middleware/auth-guard.js.map +1 -0
- package/dist/cli/middleware/error-handler.d.ts +133 -0
- package/dist/cli/middleware/error-handler.d.ts.map +1 -0
- package/dist/cli/middleware/error-handler.js +139 -0
- package/dist/cli/middleware/error-handler.js.map +1 -0
- package/dist/cli/middleware/index.d.ts +6 -0
- package/dist/cli/middleware/index.d.ts.map +1 -0
- package/dist/cli/middleware/index.js +3 -0
- package/dist/cli/middleware/index.js.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-orchestrator.d.ts +9 -0
- package/dist/cli/templates/agents/content/core/sfag-orchestrator.d.ts.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-orchestrator.js +160 -0
- package/dist/cli/templates/agents/content/core/sfag-orchestrator.js.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-spec-creator.d.ts +9 -0
- package/dist/cli/templates/agents/content/core/sfag-spec-creator.d.ts.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-spec-creator.js +343 -0
- package/dist/cli/templates/agents/content/core/sfag-spec-creator.js.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.d.ts +9 -0
- package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.d.ts.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.js +254 -0
- package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.js.map +1 -0
- package/dist/cli/templates/agents/content/research/sfag-package-researcher.d.ts +8 -0
- package/dist/cli/templates/agents/content/research/sfag-package-researcher.d.ts.map +1 -0
- package/dist/cli/templates/agents/content/research/sfag-package-researcher.js +128 -0
- package/dist/cli/templates/agents/content/research/sfag-package-researcher.js.map +1 -0
- package/dist/cli/templates/agents/index.d.ts +23 -0
- package/dist/cli/templates/agents/index.d.ts.map +1 -0
- package/dist/cli/templates/agents/index.js +29 -0
- package/dist/cli/templates/agents/index.js.map +1 -0
- package/dist/cli/templates/commands.d.ts +17 -0
- package/dist/cli/templates/commands.d.ts.map +1 -0
- package/dist/cli/templates/commands.js +78 -0
- package/dist/cli/templates/commands.js.map +1 -0
- package/dist/cli/templates/content/sf-blockers.d.ts +7 -0
- package/dist/cli/templates/content/sf-blockers.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-blockers.js +69 -0
- package/dist/cli/templates/content/sf-blockers.js.map +1 -0
- package/dist/cli/templates/content/sf-commit.d.ts +7 -0
- package/dist/cli/templates/content/sf-commit.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-commit.js +79 -0
- package/dist/cli/templates/content/sf-commit.js.map +1 -0
- package/dist/cli/templates/content/sf-context.d.ts +7 -0
- package/dist/cli/templates/content/sf-context.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-context.js +63 -0
- package/dist/cli/templates/content/sf-context.js.map +1 -0
- package/dist/cli/templates/content/sf-help.d.ts +7 -0
- package/dist/cli/templates/content/sf-help.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-help.js +42 -0
- package/dist/cli/templates/content/sf-help.js.map +1 -0
- package/dist/cli/templates/content/sf-init.d.ts +7 -0
- package/dist/cli/templates/content/sf-init.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-init.js +62 -0
- package/dist/cli/templates/content/sf-init.js.map +1 -0
- package/dist/cli/templates/content/sf-reset.d.ts +7 -0
- package/dist/cli/templates/content/sf-reset.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-reset.js +67 -0
- package/dist/cli/templates/content/sf-reset.js.map +1 -0
- package/dist/cli/templates/content/sf-search.d.ts +7 -0
- package/dist/cli/templates/content/sf-search.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-search.js +63 -0
- package/dist/cli/templates/content/sf-search.js.map +1 -0
- package/dist/cli/templates/content/sf-status.d.ts +7 -0
- package/dist/cli/templates/content/sf-status.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-status.js +62 -0
- package/dist/cli/templates/content/sf-status.js.map +1 -0
- package/dist/cli/templates/index.d.ts +8 -0
- package/dist/cli/templates/index.d.ts.map +1 -0
- package/dist/cli/templates/index.js +17 -0
- package/dist/cli/templates/index.js.map +1 -0
- package/dist/cli/ui/banner.d.ts +38 -0
- package/dist/cli/ui/banner.d.ts.map +1 -0
- package/dist/cli/ui/banner.js +89 -0
- package/dist/cli/ui/banner.js.map +1 -0
- package/dist/cli/ui/colors.d.ts +76 -0
- package/dist/cli/ui/colors.d.ts.map +1 -0
- package/dist/cli/ui/colors.js +67 -0
- package/dist/cli/ui/colors.js.map +1 -0
- package/dist/cli/ui/index.d.ts +7 -0
- package/dist/cli/ui/index.d.ts.map +1 -0
- package/dist/cli/ui/index.js +4 -0
- package/dist/cli/ui/index.js.map +1 -0
- package/dist/cli/ui/output.d.ts +117 -0
- package/dist/cli/ui/output.d.ts.map +1 -0
- package/dist/cli/ui/output.js +83 -0
- package/dist/cli/ui/output.js.map +1 -0
- package/dist/cli/ui/spinner.d.ts +120 -0
- package/dist/cli/ui/spinner.d.ts.map +1 -0
- package/dist/cli/ui/spinner.js +158 -0
- package/dist/cli/ui/spinner.js.map +1 -0
- package/dist/cli/ui/time.d.ts +54 -0
- package/dist/cli/ui/time.d.ts.map +1 -0
- package/dist/cli/ui/time.js +119 -0
- package/dist/cli/ui/time.js.map +1 -0
- package/dist/client/api-client.d.ts +123 -0
- package/dist/client/api-client.d.ts.map +1 -0
- package/dist/client/api-client.js +105 -0
- package/dist/client/api-client.js.map +1 -0
- package/dist/client/cli-client.d.ts +26 -0
- package/dist/client/cli-client.d.ts.map +1 -0
- package/dist/client/cli-client.js +20 -0
- package/dist/client/cli-client.js.map +1 -0
- package/dist/config/index.d.ts +78 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +79 -0
- package/dist/config/index.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +73 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/format.d.ts +126 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/format.js +71 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/index.d.ts +11 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +45 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/monorepo-detector.d.ts +31 -0
- package/dist/lib/monorepo-detector.d.ts.map +1 -0
- package/dist/lib/monorepo-detector.js +188 -0
- package/dist/lib/monorepo-detector.js.map +1 -0
- package/dist/lib/prompt-generator.d.ts +65 -0
- package/dist/lib/prompt-generator.d.ts.map +1 -0
- package/dist/lib/prompt-generator.js +162 -0
- package/dist/lib/prompt-generator.js.map +1 -0
- package/dist/lib/strategy-analyzer.d.ts +59 -0
- package/dist/lib/strategy-analyzer.d.ts.map +1 -0
- package/dist/lib/strategy-analyzer.js +91 -0
- package/dist/lib/strategy-analyzer.js.map +1 -0
- package/dist/lib/workflow-definitions.d.ts +41 -0
- package/dist/lib/workflow-definitions.d.ts.map +1 -0
- package/dist/lib/workflow-definitions.js +497 -0
- package/dist/lib/workflow-definitions.js.map +1 -0
- package/dist/patterns/index.d.ts +9 -0
- package/dist/patterns/index.d.ts.map +1 -0
- package/dist/patterns/index.js +21 -0
- package/dist/patterns/index.js.map +1 -0
- package/dist/patterns/inheritance.d.ts +193 -0
- package/dist/patterns/inheritance.d.ts.map +1 -0
- package/dist/patterns/inheritance.js +125 -0
- package/dist/patterns/inheritance.js.map +1 -0
- package/dist/server.d.ts +44 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +91 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/core/context-helper.d.ts +50 -0
- package/dist/tools/core/context-helper.d.ts.map +1 -0
- package/dist/tools/core/context-helper.js +49 -0
- package/dist/tools/core/context-helper.js.map +1 -0
- package/dist/tools/core/index.d.ts +2 -0
- package/dist/tools/core/index.d.ts.map +1 -0
- package/dist/tools/core/index.js +2 -0
- package/dist/tools/core/index.js.map +1 -0
- package/dist/tools/index.d.ts +58 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +1499 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/transport/__tests__/resolve-endpoint.test.d.ts +6 -0
- package/dist/transport/__tests__/resolve-endpoint.test.d.ts.map +1 -0
- package/dist/transport/index.d.ts +6 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +5 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/interface.d.ts +25 -0
- package/dist/transport/interface.d.ts.map +1 -0
- package/dist/transport/interface.js +1 -0
- package/dist/transport/interface.js.map +1 -0
- package/dist/transport/remote.d.ts +38 -0
- package/dist/transport/remote.d.ts.map +1 -0
- package/dist/transport/remote.js +107 -0
- package/dist/transport/remote.js.map +1 -0
- package/dist/transport/resolve-endpoint.d.ts +58 -0
- package/dist/transport/resolve-endpoint.d.ts.map +1 -0
- package/dist/transport/resolve-endpoint.js +146 -0
- package/dist/transport/resolve-endpoint.js.map +1 -0
- package/dist/types/index.d.ts +212 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +16 -0
- package/dist/types/index.js.map +1 -0
- package/dist/validation/index.d.ts +86 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +392 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/ticket-validation.d.ts +162 -0
- package/dist/validation/ticket-validation.d.ts.map +1 -0
- package/dist/validation/ticket-validation.js +188 -0
- package/dist/validation/ticket-validation.js.map +1 -0
- package/package.json +69 -0
- package/src/cli/templates/agents/content/core/sfag-orchestrator.ts +165 -0
- package/src/cli/templates/agents/content/core/sfag-spec-creator.ts +348 -0
- package/src/cli/templates/agents/content/core/sfag-ticket-implementer.ts +259 -0
- package/src/cli/templates/agents/content/research/sfag-package-researcher.ts +132 -0
- package/src/cli/templates/agents/index.ts +47 -0
- package/src/cli/templates/commands.ts +90 -0
- package/src/cli/templates/content/sf-blockers.ts +71 -0
- package/src/cli/templates/content/sf-commit.ts +81 -0
- package/src/cli/templates/content/sf-context.ts +65 -0
- package/src/cli/templates/content/sf-help.ts +44 -0
- package/src/cli/templates/content/sf-init.ts +64 -0
- package/src/cli/templates/content/sf-reset.ts +69 -0
- package/src/cli/templates/content/sf-search.ts +65 -0
- package/src/cli/templates/content/sf-status.ts +64 -0
- package/src/cli/templates/index.ts +16 -0
- package/src/cli/templates/skills/specforge-conventions.md +114 -0
- package/src/cli/templates/skills/specforge-orchestrator.md +409 -0
- package/src/cli/templates/skills/specforge-validator.md +128 -0
- package/src/cli/templates/skills/specforge-worker.md +412 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/commands/init.ts"],"sourcesContent":["/**\n * Init Command\n *\n * Initializes SpecForge for a project by creating config files\n * and linking to a SpecForge project and specification.\n */\n\nimport { Command } from 'commander';\nimport inquirer from 'inquirer';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport {\n resolveConfig,\n loadGlobalConfig,\n tryLoadProjectConfig,\n saveProjectConfig,\n setAgentTeamsConfig,\n addToGitignore,\n getConfigPaths,\n} from '../config/index.js';\nimport { CONFIG_FILES } from '../config/types.js';\nimport { withErrorHandler, CliError, NetworkError, ValidationError } from '../middleware/error-handler.js';\nimport {\n printSuccess,\n printWarning,\n printBlank,\n printHeader,\n printField,\n printHint,\n printTable,\n} from '../ui/output.js';\nimport { colors } from '../ui/colors.js';\nimport { printBanner } from '../ui/banner.js';\nimport { forgeProgress } from '../ui/spinner.js';\nimport { ApiClient } from '../../client/api-client.js';\nimport { createCliClient } from '../../client/cli-client.js';\nimport {\n InitOptions,\n InitProject as Project,\n InitSpecification as Specification,\n ListProjectsResponse,\n ListSpecificationsResponse,\n ExistingFilesCheck,\n ProjectChoice,\n SpecificationChoice,\n FORMAT_CHOICES,\n DEFAULT_FORMAT,\n AgentTeamsInitOptions,\n STRATEGY_CHOICES,\n SKILL_TEMPLATE_FILES,\n} from './init.types.js';\nimport { TARGETS } from './scaffold/targets.js';\nimport type { ScaffoldTarget } from './scaffold/types.js';\nimport { scaffoldMultiCli, type WriteResult } from './scaffold/files.js';\nimport { detectInstalledTools } from './scaffold/utils.js';\n\n/**\n * Fetch user's projects from API\n */\nasync function fetchProjects(client: ApiClient): Promise<Project[]> {\n const response = await client.call<ListProjectsResponse>('list_projects', {});\n return response.projects || [];\n}\n\n/**\n * Fetch specifications for a project\n */\nasync function fetchSpecifications(\n client: ApiClient,\n projectId: string\n): Promise<Specification[]> {\n const response = await client.call<{ items?: Specification[]; specifications?: Specification[] }>(\n 'list_specifications',\n { projectId }\n );\n // API returns items, but keep specifications for backward compatibility\n return response.items || response.specifications || [];\n}\n\n/**\n * Check if config files already exist\n */\nfunction checkExistingFiles(): ExistingFilesCheck {\n const paths = getConfigPaths();\n const mcpConfig = fs.existsSync(paths.mcpConfig);\n const projectConfig = fs.existsSync(paths.projectConfig);\n\n return {\n mcpConfig,\n projectConfig,\n anyExists: mcpConfig || projectConfig,\n };\n}\n\n/**\n * Build project choices for inquirer\n */\nfunction buildProjectChoices(projects: Project[]): ProjectChoice[] {\n return projects.map((p) => ({\n name: `${p.name}${p.specCount ? ` (${p.specCount} specs)` : ''}`,\n value: p.id,\n short: p.name,\n }));\n}\n\n/**\n * Build specification choices for inquirer\n */\nfunction buildSpecificationChoices(specs: Specification[]): SpecificationChoice[] {\n const choices: SpecificationChoice[] = specs.map((s) => {\n const ticketInfo = s.ticketCount\n ? ` - ${s.completedTicketCount || 0}/${s.ticketCount} tickets`\n : '';\n return {\n name: `${s.title} [${s.status}]${ticketInfo}`,\n value: s.id,\n short: s.title,\n };\n });\n\n // Add \"none\" option\n choices.push({\n name: colors.muted('(skip - select later)'),\n value: undefined,\n });\n\n return choices;\n}\n\n/**\n * Prompt user to select a project\n */\nasync function promptForProject(\n projects: Project[],\n defaultId?: string,\n): Promise<Project> {\n const choices = buildProjectChoices(projects);\n\n const { projectId } = await inquirer.prompt([\n {\n type: 'list',\n name: 'projectId',\n message: 'Select project for this directory:',\n choices,\n pageSize: 10,\n // Resume-aware (M9.8): pre-select the currently-configured project.\n ...(defaultId ? { default: defaultId } : {}),\n },\n ]);\n\n const selected = projects.find((p) => p.id === projectId);\n if (!selected) {\n throw new CliError('Project selection failed');\n }\n\n return selected;\n}\n\n/**\n * Prompt user to select a specification\n */\nasync function promptForSpecification(\n specs: Specification[],\n defaultId?: string,\n): Promise<Specification | undefined> {\n if (specs.length === 0) {\n return undefined;\n }\n\n const choices = buildSpecificationChoices(specs);\n\n const { specificationId } = await inquirer.prompt([\n {\n type: 'list',\n name: 'specificationId',\n message: 'Select default specification (optional):',\n choices,\n pageSize: 10,\n // Resume-aware (M9.8): pre-select the currently-configured spec.\n ...(defaultId ? { default: defaultId } : {}),\n },\n ]);\n\n if (!specificationId) {\n return undefined;\n }\n\n return specs.find((s) => s.id === specificationId);\n}\n\n/**\n * Prompt user to select output format\n */\nasync function promptForFormat(): Promise<'json' | 'toon'> {\n const { format } = await inquirer.prompt([\n {\n type: 'list',\n name: 'format',\n message: 'Default MCP response format (TOON or JSON):',\n choices: FORMAT_CHOICES,\n default: DEFAULT_FORMAT,\n },\n ]);\n\n return format;\n}\n\n/**\n * Validate project ID exists\n */\nfunction validateProjectId(projectId: string, projects: Project[]): Project {\n const project = projects.find((p) => p.id === projectId);\n\n if (!project) {\n const available = projects.map((p) => ` - ${p.id}: ${p.name}`).join('\\n');\n throw new ValidationError(\n `Project not found: ${projectId}`,\n `Available projects:\\n${available}`\n );\n }\n\n return project;\n}\n\n/**\n * Validate specification ID exists\n */\nfunction validateSpecificationId(\n specId: string,\n specs: Specification[]\n): Specification {\n const spec = specs.find((s) => s.id === specId);\n\n if (!spec) {\n const available = specs.map((s) => ` - ${s.id}: ${s.title}`).join('\\n');\n throw new ValidationError(\n `Specification not found: ${specId}`,\n `Available specifications:\\n${available}`\n );\n }\n\n return spec;\n}\n\n/**\n * Display current configuration settings\n */\nfunction showSettings(): void {\n const config = resolveConfig();\n const globalConfig = loadGlobalConfig();\n const projectConfig = tryLoadProjectConfig();\n const paths = getConfigPaths();\n\n printBlank();\n printHeader('Current Configuration');\n\n // Resolved values with sources\n printBlank();\n console.log(colors.bold('Resolved Settings'));\n console.log(colors.muted('Values merged from all sources (env > project > global > default)'));\n printBlank();\n\n const apiKeyDisplay = config.apiKey\n ? `${config.apiKey.slice(0, 12)}...${config.apiKey.slice(-4)}`\n : null;\n const sourceLabel = (source: string | null) =>\n source ? colors.muted(` (from ${source})`) : '';\n\n printField('API Key', apiKeyDisplay\n ? `${apiKeyDisplay}${sourceLabel(config.sources.apiKey)}`\n : undefined);\n printField('Project ID', config.projectId\n ? `${config.projectId}${sourceLabel(config.sources.projectId)}`\n : undefined);\n printField('Specification ID', config.specificationId\n ? `${config.specificationId}${sourceLabel(config.sources.specificationId)}`\n : undefined);\n printField('MCP output format', `${config.mcpOutputFormat}${sourceLabel(config.sources.mcpOutputFormat)}`);\n printField('Auto-context', config.autoSetContext ? 'enabled' : 'disabled');\n printField('Debug', config.debug ? 'enabled' : 'disabled');\n printField('API URL', config.apiUrl);\n\n // Config files\n printBlank();\n printHeader('Config Files');\n printBlank();\n\n const globalExists = fs.existsSync(paths.globalConfig);\n const projectExists = fs.existsSync(paths.projectConfig);\n const mcpExists = fs.existsSync(paths.mcpConfig);\n\n printField('Global config', `${paths.globalConfig} ${globalExists ? colors.success('(exists)') : colors.muted('(not found)')}`);\n printField('Project config', `${paths.projectConfig} ${projectExists ? colors.success('(exists)') : colors.muted('(not found)')}`);\n printField('MCP config', `${paths.mcpConfig} ${mcpExists ? colors.success('(exists)') : colors.muted('(not found)')}`);\n\n // Global config details\n if (globalExists && Object.keys(globalConfig).length > 0) {\n printBlank();\n printHeader('Global Config (~/.specforge/config.json)');\n printBlank();\n\n if (globalConfig.apiKey) {\n printField('apiKey', `${globalConfig.apiKey.slice(0, 12)}...${globalConfig.apiKey.slice(-4)}`);\n }\n if (globalConfig.mcpOutputFormat) {\n printField('mcpOutputFormat', globalConfig.mcpOutputFormat);\n }\n if (globalConfig.defaultProjectId) {\n printField('defaultProjectId', globalConfig.defaultProjectId);\n }\n }\n\n // Project config details\n if (projectExists && projectConfig) {\n printBlank();\n printHeader('Project Config (.specforge/config.json)');\n printBlank();\n\n if (projectConfig.projectId) {\n printField('projectId', projectConfig.projectId);\n }\n if (projectConfig.specificationId) {\n printField('specificationId', projectConfig.specificationId);\n }\n if (projectConfig.mcpOutputFormat) {\n printField('mcpOutputFormat', projectConfig.mcpOutputFormat);\n }\n if (projectConfig.autoSetContext !== undefined) {\n printField('autoSetContext', String(projectConfig.autoSetContext));\n }\n }\n\n printBlank();\n}\n\n// === AGENT TEAMS (Claude Code only) — prompts and scaffolding ===\n\n/**\n * Prompt user for Agent Teams configuration (v2.0.0).\n * Claude Code Agent Teams only.\n */\nasync function promptForAgentTeams(): Promise<AgentTeamsInitOptions | null> {\n const { configure } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'configure',\n message: 'Configure Agent Teams (Claude Code)?',\n default: false,\n },\n ]);\n\n if (!configure) {\n return null;\n }\n\n const answers = await inquirer.prompt([\n {\n type: 'list',\n name: 'strategy',\n message: 'Team strategy:',\n choices: STRATEGY_CHOICES,\n default: 'auto',\n },\n {\n type: 'number',\n name: 'maxTicketsPerTeam',\n message: 'Max tickets per team (1-20):',\n default: 10,\n validate: (val: number) => {\n if (!Number.isInteger(val) || val < 1 || val > 20) {\n return 'Must be an integer between 1 and 20';\n }\n return true;\n },\n },\n {\n type: 'number',\n name: 'maxParallelEpics',\n message: 'Max parallel epics (1-10):',\n default: 3,\n validate: (val: number) => {\n if (!Number.isInteger(val) || val < 1 || val > 10) {\n return 'Must be an integer between 1 and 10';\n }\n return true;\n },\n },\n {\n type: 'list',\n name: 'branchPrefix',\n message: 'Branch prefix:',\n choices: [\n { name: 'ticket/ (Recommended)', value: 'ticket/' },\n { name: 'epic/', value: 'epic/' },\n { name: 'spec/', value: 'spec/' },\n ],\n default: 'ticket/',\n },\n ]);\n\n return {\n enabled: true,\n strategy: answers.strategy,\n maxTicketsPerTeam: answers.maxTicketsPerTeam,\n maxParallelEpics: answers.maxParallelEpics,\n branchPrefix: answers.branchPrefix,\n };\n}\n\n// === END AGENT TEAMS ===\n\n/**\n * Get the path to the skill templates directory bundled with the CLI.\n *\n * Templates live in src/cli/templates/skills/ (not compiled by tsc).\n * We resolve from the current file's location to the package root,\n * then navigate into the source templates directory.\n */\nfunction getTemplatesDir(): string {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n // From dist/cli/commands/ or src/cli/commands/ -> package root -> src/cli/templates/skills/\n const packageRoot = path.resolve(__dirname, '..', '..', '..');\n return path.join(packageRoot, 'src', 'cli', 'templates', 'skills');\n}\n\n/**\n * Scaffold Agent Teams protocol skills into the project in the Claude Code\n * skill directory form: `.claude/skills/<name>/SKILL.md`. Source templates\n * at `templates/skills/<name>.md` each carry proper YAML frontmatter.\n */\nasync function scaffoldSkillFiles(\n projectName: string | undefined,\n skipPrompts: boolean\n): Promise<void> {\n const templatesDir = getTemplatesDir();\n const skillsRoot = path.resolve(process.cwd(), '.claude', 'skills');\n\n if (!fs.existsSync(templatesDir)) {\n printWarning('Skill templates not found. Skipping scaffolding.');\n return;\n }\n\n try {\n fs.mkdirSync(skillsRoot, { recursive: true });\n } catch {\n printWarning('Could not create .claude/skills/ directory. Skipping skill scaffolding.');\n return;\n }\n\n const targetFor = (skill: string) => path.join(skillsRoot, skill, 'SKILL.md');\n\n const existingSkills = SKILL_TEMPLATE_FILES.filter((skill) =>\n fs.existsSync(targetFor(skill)),\n );\n\n type OverwritePolicy = 'skip' | 'overwrite' | 'ask';\n let overwritePolicy: OverwritePolicy = 'ask';\n\n if (existingSkills.length > 0 && !skipPrompts) {\n const { policy } = await inquirer.prompt([\n {\n type: 'list',\n name: 'policy',\n message: `${existingSkills.length} skill(s) already exist. How should we proceed?`,\n choices: [\n { name: 'Skip all existing', value: 'skip' },\n { name: 'Overwrite all', value: 'overwrite' },\n { name: 'Ask for each', value: 'ask' },\n ],\n default: 'ask',\n },\n ]);\n overwritePolicy = policy;\n } else if (skipPrompts) {\n overwritePolicy = 'skip';\n }\n\n const scaffolded: string[] = [];\n\n for (const skill of SKILL_TEMPLATE_FILES) {\n const sourcePath = path.join(templatesDir, `${skill}.md`);\n const targetPath = targetFor(skill);\n\n if (!fs.existsSync(sourcePath)) {\n continue;\n }\n\n if (fs.existsSync(targetPath)) {\n if (overwritePolicy === 'skip') {\n continue;\n }\n if (overwritePolicy === 'ask') {\n const { overwrite } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'overwrite',\n message: `Skill ${skill}/SKILL.md already exists. Overwrite?`,\n default: false,\n },\n ]);\n if (!overwrite) continue;\n }\n }\n\n try {\n let content = fs.readFileSync(sourcePath, 'utf-8');\n if (projectName) {\n content = content.replace(/\\{\\{PROJECT_NAME\\}\\}/g, projectName);\n }\n\n fs.mkdirSync(path.dirname(targetPath), { recursive: true });\n fs.writeFileSync(targetPath, content);\n scaffolded.push(skill);\n } catch {\n continue;\n }\n }\n\n if (scaffolded.length > 0) {\n printBlank();\n printSuccess(`Scaffolded ${scaffolded.length} skill(s) to .claude/skills/`);\n for (const skill of scaffolded) {\n console.log(` ${colors.muted('•')} ${skill}/SKILL.md`);\n }\n }\n}\n\n// Multi-CLI scaffolding (AGENTS.md, per-CLI instruction files, MCP configs,\n// conventions skills) is implemented in scaffold/files.ts and called from\n// initAction below.\n\n/**\n * Refuse to run when a legacy `.specforge.json` is present.\n *\n * The migration path is manual and destructive-looking to the user, so we\n * stop and make them delete the legacy file themselves instead of\n * silently upgrading the layout.\n */\nfunction refuseIfLegacyConfig(): void {\n const legacyPath = path.resolve(CONFIG_FILES.LEGACY_PROJECT_CONFIG);\n if (!fs.existsSync(legacyPath)) {\n return;\n }\n throw new CliError(\n 'Legacy .specforge.json detected',\n 1,\n `Delete ${legacyPath} before running \\`specforge init\\`. The config layout changed to .specforge/config.json in the first production release; no automatic migration is performed.`\n );\n}\n\n/**\n * Init command implementation\n */\nexport async function initAction(options: InitOptions): Promise<void> {\n // Show current settings and exit\n if (options.show) {\n showSettings();\n return;\n }\n\n refuseIfLegacyConfig();\n\n // Check authentication\n const config = resolveConfig();\n\n if (!config.apiKey) {\n throw new CliError(\n 'Not authenticated',\n 1,\n 'Run `specforge login` to authenticate first'\n );\n }\n\n // --spec without ID: select specification from current project\n if (options.spec === true) {\n const existing = tryLoadProjectConfig();\n if (existing?.projectId) {\n const client = createCliClient({ apiKey: config.apiKey, apiUrl: config.apiUrl, debug: config.debug });\n const specs = await fetchSpecifications(client, existing.projectId);\n const selectedSpec = await promptForSpecification(specs);\n if (selectedSpec) {\n saveProjectConfig({\n ...existing,\n specificationId: selectedSpec.id,\n // Switching spec abandons the previous spec's planning session (M9.8).\n planningSessionId:\n selectedSpec.id === existing.specificationId\n ? existing.planningSessionId\n : undefined,\n });\n printSuccess(`Switched to: ${selectedSpec.title}`);\n }\n return;\n }\n // No project config, fall through to full init\n printWarning('No project configured. Running full init...');\n printBlank();\n }\n\n // Spec-only mode: switch specification without re-initializing\n if (options.specOnly) {\n const existing = tryLoadProjectConfig();\n if (!existing?.projectId) {\n throw new CliError('No .specforge/config.json found — run `specforge init` first');\n }\n\n const client = createCliClient({ apiKey: config.apiKey, apiUrl: config.apiUrl, debug: config.debug });\n const specs = await fetchSpecifications(client, existing.projectId);\n\n let selectedSpec: Specification;\n if (typeof options.spec === 'string') {\n selectedSpec = validateSpecificationId(options.spec, specs);\n } else {\n const { specId } = await inquirer.prompt([{\n type: 'list',\n name: 'specId',\n message: 'Select specification:',\n choices: specs.map(s => ({ name: `${s.title} (${s.status})`, value: s.id })),\n }]);\n selectedSpec = specs.find(s => s.id === specId)!;\n }\n\n saveProjectConfig({\n ...existing,\n specificationId: selectedSpec.id,\n // Switching spec abandons the previous spec's planning session (M9.8).\n planningSessionId:\n selectedSpec.id === existing.specificationId\n ? existing.planningSessionId\n : undefined,\n });\n printSuccess(`Switched to: ${selectedSpec.title}`);\n return;\n }\n\n // Header\n printBlank();\n printBanner('figlet');\n printBlank();\n\n // Existing-config handling (M9.8). `priorConfig` is the parsed project config;\n // `existing` is the raw file presence (covers a stray .mcp.json / unparsable\n // config). A resumable config (has projectId, no --force) routes through the\n // resume-aware menu below; everything else keeps the block-with-warning.\n const existing = checkExistingFiles();\n const priorConfig = tryLoadProjectConfig();\n const canResume = !!priorConfig?.projectId && !options.force;\n\n if (existing.anyExists && !options.force && !canResume) {\n printWarning('Configuration files already exist:');\n if (existing.mcpConfig) {\n console.log(` ${colors.muted('•')} .mcp.json`);\n }\n if (existing.projectConfig) {\n console.log(` ${colors.muted('•')} ${CONFIG_FILES.PROJECT_CONFIG}`);\n }\n printBlank();\n console.log(`Use ${colors.primary('--force')} to overwrite existing files.`);\n printBlank();\n return;\n }\n\n // Create the `/cli` client — list_projects / list_specifications are\n // guidance-free human reads served by the mcp-handler `/cli` route (M9.8),\n // not the agent `/local` dispatch.\n const client = createCliClient({\n apiKey: config.apiKey,\n apiUrl: config.apiUrl,\n debug: config.debug,\n });\n\n // Fetch projects\n const spinner = ora({\n text: 'Connecting to SpecForge...',\n color: 'cyan',\n }).start();\n\n let projects: Project[];\n\n try {\n projects = await fetchProjects(client);\n spinner.succeed('Connected to SpecForge');\n } catch (error) {\n spinner.fail('Connection failed');\n const message = error instanceof Error ? error.message : String(error);\n\n if (message.includes('401') || message.includes('Unauthorized')) {\n throw new CliError(\n 'Authentication failed',\n 1,\n 'Your API key may be invalid. Run `specforge login` to re-authenticate'\n );\n }\n\n throw new NetworkError(`Failed to fetch projects: ${message}`);\n }\n\n // Handle no projects\n if (projects.length === 0) {\n printBlank();\n printWarning('No projects found in your account.');\n console.log(\n `Create a project at ${colors.primary.underline('https://specforge.com.br')} first.`\n );\n printBlank();\n return;\n }\n\n // Resume-aware menu (M9.8): when a resumable config exists, show the current\n // binding (always re-fetched for fresh labels) and let the user resume (keep\n // config, just refresh scaffolding) or reconfigure (full flow, current\n // project/spec pre-selected). `--force` skips this and goes straight to a\n // full reconfigure.\n let resumeMode = false;\n let defaultProjectId: string | undefined;\n let defaultSpecId: string | undefined;\n let resumeSelectedSpec: Specification | undefined;\n\n if (canResume) {\n const currentProject = projects.find((p) => p.id === priorConfig!.projectId);\n if (currentProject) {\n let currentSpecs: Specification[] = [];\n try {\n currentSpecs = await fetchSpecifications(client, currentProject.id);\n } catch {\n // Non-fatal: the summary just omits the spec label; a reconfigure path\n // re-fetches specs after project selection anyway.\n }\n const currentSpec = priorConfig!.specificationId\n ? currentSpecs.find((s) => s.id === priorConfig!.specificationId)\n : undefined;\n\n printBlank();\n printHeader('Configuration already exists');\n printBlank();\n printField('Project', currentProject.name);\n printField(\n 'Specification',\n currentSpec ? `${currentSpec.title} [${currentSpec.status}]` : colors.muted('(none)'),\n );\n if (priorConfig!.planningSessionId) {\n printField('Planning session', `${priorConfig!.planningSessionId} ${colors.muted('(active)')}`);\n }\n printBlank();\n\n const { choice } = await inquirer.prompt([\n {\n type: 'list',\n name: 'choice',\n message: 'How do you want to proceed?',\n choices: [\n { name: 'Resume — keep config, refresh scaffolding', value: 'resume' },\n { name: 'Reconfigure — pick project/spec again (current pre-selected)', value: 'reconfigure' },\n { name: 'Cancel', value: 'cancel' },\n ],\n default: 'resume',\n },\n ]);\n\n if (choice === 'cancel') {\n printBlank();\n console.log(colors.muted('Cancelled — no changes made.'));\n printBlank();\n return;\n }\n if (choice === 'resume') {\n resumeMode = true;\n resumeSelectedSpec = currentSpec;\n } else {\n defaultProjectId = currentProject.id;\n defaultSpecId = currentSpec?.id;\n }\n }\n }\n\n // Select project / specification / format. On resume we reuse the stored\n // binding verbatim and skip the prompts.\n let selectedProject: Project;\n let selectedSpec: Specification | undefined;\n let selectedFormat: 'json' | 'toon';\n\n if (resumeMode) {\n selectedProject = projects.find((p) => p.id === priorConfig!.projectId)!;\n selectedSpec = resumeSelectedSpec;\n selectedFormat = (priorConfig!.mcpOutputFormat as 'json' | 'toon') ?? DEFAULT_FORMAT;\n } else {\n // Select project (reconfigure pre-selects the current one).\n if (options.project) {\n selectedProject = validateProjectId(options.project, projects);\n console.log(colors.muted(`Using project: ${selectedProject.name}`));\n } else {\n selectedProject = await promptForProject(projects, defaultProjectId);\n }\n\n // Fetch specifications for selected project\n const specsSpinner = ora({\n text: 'Fetching specifications...',\n color: 'cyan',\n }).start();\n\n let specs: Specification[];\n\n try {\n specs = await fetchSpecifications(client, selectedProject.id);\n specsSpinner.succeed(`Found ${specs.length} specification(s)`);\n } catch (error) {\n specsSpinner.fail('Failed to fetch specifications');\n throw new NetworkError(\n `Failed to fetch specifications: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n // Select specification (reconfigure pre-selects the current one).\n if (typeof options.spec === 'string') {\n if (specs.length === 0) {\n printWarning(`No specifications found. Ignoring --spec flag.`);\n } else {\n selectedSpec = validateSpecificationId(options.spec, specs);\n console.log(colors.muted(`Using specification: ${selectedSpec.title}`));\n }\n } else if (specs.length > 0) {\n selectedSpec = await promptForSpecification(specs, defaultSpecId);\n }\n\n // Select format\n if (options.format) {\n if (options.format !== 'json' && options.format !== 'toon') {\n throw new ValidationError(\n `Invalid format: ${options.format}`,\n 'Valid formats are: json, toon'\n );\n }\n selectedFormat = options.format;\n console.log(colors.muted(`Using format: ${selectedFormat}`));\n } else {\n selectedFormat = await promptForFormat();\n }\n }\n\n // Detect installed AI CLIs and — if more than one — prompt the user to choose.\n // Non-interactive runs (--yes or full flag set) keep the existing auto-detect-all behavior.\n const isNonInteractive = !!(options.yes || (options.project && typeof options.spec === 'string' && options.format));\n const detectedCLIs = detectInstalledTools();\n let chosenTargets: ScaffoldTarget[] | undefined;\n\n if (detectedCLIs.length > 1 && !isNonInteractive) {\n const ordered: ScaffoldTarget[] = [\n ...(detectedCLIs.includes('claude') ? (['claude'] as ScaffoldTarget[]) : []),\n ...detectedCLIs.filter((t) => t !== 'claude'),\n ];\n const choices = ordered.map((t) => ({\n name: t === 'claude'\n ? `${TARGETS[t].name} ${colors.dim('* Recommended')}`\n : TARGETS[t].name,\n value: t,\n }));\n printBlank();\n const { chosen } = await inquirer.prompt([{\n type: 'list',\n name: 'chosen',\n message: 'Multiple AI CLIs detected — which one should SpecForge configure?',\n choices,\n default: detectedCLIs.includes('claude') ? 'claude' : ordered[0],\n }]);\n chosenTargets = [chosen as ScaffoldTarget];\n }\n\n // Generate and save config files + multi-CLI scaffolding via gradient progress\n printBlank();\n\n let addedSpecforge = false;\n let addedMcp = false;\n let scaffoldResult: { writes: WriteResult[]; detected: ScaffoldTarget[] } = { writes: [], detected: [] };\n\n // A re-init (`--force`) onto a different spec must not carry the prior spec's\n // planning session forward (M9.8); same-spec re-init / resume keeps it so the\n // agent can resume. saveProjectConfig merges with the on-disk config, so clear\n // explicitly. (`priorConfig` was loaded above for the resume-aware menu.)\n const keepPlanningSession =\n !!selectedSpec?.id && selectedSpec.id === priorConfig?.specificationId;\n\n await forgeProgress('Forging spec', [\n {\n label: 'save config',\n fn: async () => {\n saveProjectConfig({\n projectId: selectedProject.id,\n specificationId: selectedSpec?.id,\n mcpOutputFormat: selectedFormat,\n autoSetContext: true,\n planningSessionId: keepPlanningSession\n ? priorConfig?.planningSessionId\n : undefined,\n });\n // Ignore BOTH channel config dirs (M9.8) — a repo may be touched by the\n // stable (`.specforge/`) and canary (`.specforge-canary/`) binaries; both\n // hold local-only config, so neither should be committed.\n const addedStable = addToGitignore('.specforge/');\n const addedCanary = addToGitignore('.specforge-canary/');\n addedSpecforge = addedStable || addedCanary;\n addedMcp = addToGitignore('.mcp.json');\n },\n },\n {\n label: 'scaffold files',\n fn: async () => {\n scaffoldResult = scaffoldMultiCli({\n projectName: selectedProject.name,\n apiKey: config.apiKey ?? undefined,\n force: options.force,\n targets: chosenTargets,\n });\n },\n },\n ]);\n\n printBlank();\n printSuccess('Created .specforge/config.json');\n if (addedSpecforge) {\n printSuccess('Added .specforge/ + .specforge-canary/ to .gitignore');\n }\n if (addedMcp) {\n printSuccess('Added .mcp.json to .gitignore');\n }\n\n const { writes, detected } = scaffoldResult;\n const changedWrites = writes.filter(w => w.changed);\n if (changedWrites.length > 0) {\n printBlank();\n printSuccess(`Multi-CLI scaffolding (${detected.length} CLI(s) detected):`);\n for (const w of changedWrites) {\n console.log(` ${colors.muted('•')} ${w.relPath}`);\n }\n if (detected.length > 0) {\n console.log(colors.dim(` Detected: ${detected.map(t => TARGETS[t].name).join(', ')}`));\n }\n }\n\n // === AGENT TEAMS (Claude Code only) — config and scaffolding ===\n // isNonInteractive computed above (used by the CLI chooser too)\n let agentTeamsConfig: AgentTeamsInitOptions | null = null;\n\n if (isNonInteractive) {\n // Skip Agent Teams prompts entirely in non-interactive mode\n agentTeamsConfig = {\n enabled: false,\n strategy: 'auto',\n maxTicketsPerTeam: 10,\n maxParallelEpics: 3,\n branchPrefix: 'ticket/',\n };\n } else {\n printBlank();\n agentTeamsConfig = await promptForAgentTeams();\n }\n\n if (agentTeamsConfig?.enabled) {\n setAgentTeamsConfig({\n enabled: agentTeamsConfig.enabled,\n strategy: agentTeamsConfig.strategy,\n maxTicketsPerTeam: agentTeamsConfig.maxTicketsPerTeam,\n maxParallelEpics: agentTeamsConfig.maxParallelEpics,\n branchPrefix: agentTeamsConfig.branchPrefix,\n });\n printSuccess('Saved Agent Teams configuration to .specforge/config.json');\n }\n\n // Success summary\n printBlank();\n printHeader('Configuration Complete');\n printBlank();\n\n printField('Project', selectedProject.name);\n if (selectedSpec) {\n printField('Specification', selectedSpec.title);\n }\n printField('Format', selectedFormat);\n printField('Auto-context', 'enabled');\n if (agentTeamsConfig?.enabled) {\n printField('Agent Teams', 'enabled');\n printField('Strategy', agentTeamsConfig.strategy);\n }\n\n // Consolidated scaffold prompt: commands + agents + skills (Claude Code)\n if (!isNonInteractive) {\n printBlank();\n const { scaffoldNow } = await inquirer.prompt([{\n type: 'list',\n name: 'scaffoldNow',\n message: 'Scaffold SpecForge commands, agents, and skills for Claude Code?\\n Generates 8 slash commands (/sf-status, /sf-context, ...), 4 agent\\n definitions, and 4 skills for deeper AI integration.',\n choices: [\n { name: 'Yes, scaffold now', value: true },\n { name: \"No, I'll run `specforge scaffold` later\", value: false },\n ],\n default: true,\n }]);\n\n if (scaffoldNow) {\n const { scaffoldCommand } = await import('./scaffold/scaffold.js');\n await scaffoldSkillFiles(selectedProject.name, isNonInteractive);\n // Scaffold commands and agents into `.claude/` in the project, not the\n // user's global `~/.claude/`. init always targets the current project.\n await scaffoldCommand({ target: 'claude', update: true, project: true });\n await scaffoldCommand({ agents: true, target: 'claude', update: true, project: true });\n } else {\n printBlank();\n console.log(\n `Run ${colors.primary('specforge scaffold')} when ready.`\n );\n }\n }\n\n printBlank();\n if (detected.length > 0) {\n console.log(colors.warning(`Restart ${detected.map(t => TARGETS[t].name).join(' / ')} to activate SpecForge MCP.`));\n } else {\n console.log(colors.warning('Restart your AI CLI tool to activate SpecForge MCP.'));\n }\n printBlank();\n\n // === END AGENT TEAMS ===\n\n // Next steps\n console.log(colors.bold('Next steps:'));\n printHint('specforge status', 'verify your configuration');\n printHint('specforge doctor', 'check MCP server connectivity');\n printBlank();\n}\n\n/**\n * Register init command with Commander\n */\nexport function registerInitCommand(program: Command): void {\n program\n .command('init')\n .description('Initialize SpecForge for this project')\n .option('--project <id>', 'Project ID (non-interactive)')\n .option('--spec [id]', 'Specification ID, or omit ID to pick from current project')\n .option('--format <format>', 'MCP response format: json or toon (default: toon)')\n .option('-f, --force', 'Overwrite existing configuration files')\n .option('-s, --show', 'Display current configuration settings')\n .option('-y, --yes', 'Skip interactive prompts, use defaults')\n .option('--spec-only', 'Switch active specification (quick switch)')\n .addHelpText('after', `\nExamples:\n $ specforge init # Interactive setup (resume-aware if already configured)\n $ specforge init --show # Display current settings\n $ specforge init --project proj_abc123 # Set project non-interactively\n $ specforge init --project proj_abc --spec spec_xyz --format toon\n $ specforge init --force # Overwrite existing config\n $ specforge init --yes # Use defaults, skip prompts\n $ specforge init --spec # Pick specification from current project\n $ specforge init --spec-only # Switch specification (alias)\n\nThis command creates:\n .specforge/config.json - Project-specific SpecForge settings\n Per-CLI MCP config - .mcp.json (Claude Code / Copilot / Cursor),\n .gemini/settings.json, .codex/config.toml, opencode.json\n Per-CLI instruction file - CLAUDE.md, GEMINI.md, .github/copilot-instructions.md,\n or AGENTS.md (Codex / OpenCode / Cursor fallback)\n Per-CLI skill files - specforge-conventions\n\nAfter running init, restart your AI CLI tool to activate the MCP server.\n`)\n .action(withErrorHandler(initAction));\n}\n"],"mappings":"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","names":["existing","client","selectedSpec"]}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Init Command Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for the init command including options,
|
|
5
|
+
* API responses, and selection interfaces.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Command line options for init command
|
|
9
|
+
*/
|
|
10
|
+
export interface InitOptions {
|
|
11
|
+
/** Project ID for non-interactive mode */
|
|
12
|
+
project?: string;
|
|
13
|
+
/** Specification ID for non-interactive mode, or true when --spec is used without an ID */
|
|
14
|
+
spec?: string | true;
|
|
15
|
+
/** Output format preference */
|
|
16
|
+
format?: 'json' | 'toon';
|
|
17
|
+
/** Force overwrite existing config files */
|
|
18
|
+
force?: boolean;
|
|
19
|
+
/** Show current configuration settings */
|
|
20
|
+
show?: boolean;
|
|
21
|
+
/** Skip all interactive prompts, use defaults */
|
|
22
|
+
yes?: boolean;
|
|
23
|
+
/** Switch active specification (quick switch) */
|
|
24
|
+
specOnly?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Agent Teams configuration collected during init (v2.0.0).
|
|
28
|
+
* Claude Code Agent Teams only.
|
|
29
|
+
*/
|
|
30
|
+
export interface AgentTeamsInitOptions {
|
|
31
|
+
/** Whether to configure Agent Teams */
|
|
32
|
+
enabled: boolean;
|
|
33
|
+
/** Execution strategy */
|
|
34
|
+
strategy: 'auto' | 'single' | 'parallel' | 'phased';
|
|
35
|
+
/** Max tickets per team (1-20) */
|
|
36
|
+
maxTicketsPerTeam: number;
|
|
37
|
+
/** Max parallel epics (1-10) */
|
|
38
|
+
maxParallelEpics: number;
|
|
39
|
+
/** Branch prefix for ticket branches */
|
|
40
|
+
branchPrefix: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Strategy choices for Agent Teams init prompt
|
|
44
|
+
*/
|
|
45
|
+
export declare const STRATEGY_CHOICES: ({
|
|
46
|
+
name: string;
|
|
47
|
+
value: "auto";
|
|
48
|
+
} | {
|
|
49
|
+
name: string;
|
|
50
|
+
value: "single";
|
|
51
|
+
} | {
|
|
52
|
+
name: string;
|
|
53
|
+
value: "parallel";
|
|
54
|
+
} | {
|
|
55
|
+
name: string;
|
|
56
|
+
value: "phased";
|
|
57
|
+
})[];
|
|
58
|
+
/**
|
|
59
|
+
* Skill names scaffolded into `.claude/skills/<name>/SKILL.md` (the directory
|
|
60
|
+
* form required by Claude Code — see https://code.claude.com/docs/en/skills).
|
|
61
|
+
*
|
|
62
|
+
* The source template lives at `templates/skills/<name>.md` and is written
|
|
63
|
+
* to `<name>/SKILL.md` under the project's `.claude/skills/` directory.
|
|
64
|
+
*
|
|
65
|
+
* `specforge-conventions` is handled by scaffoldMultiCli's writeSkillForTarget
|
|
66
|
+
* and is intentionally excluded here to avoid a duplicate write.
|
|
67
|
+
*/
|
|
68
|
+
export declare const SKILL_TEMPLATE_FILES: readonly ["specforge-orchestrator", "specforge-worker", "specforge-validator"];
|
|
69
|
+
import type { SpecificationStatus } from '@specforge/types/schema';
|
|
70
|
+
/**
|
|
71
|
+
* Lightweight project shape used by the init command's list/selection flow.
|
|
72
|
+
*
|
|
73
|
+
* Distinct from the canonical runtime `Project` in `@specforge/types/runtime`
|
|
74
|
+
* — init only needs a subset of fields (name, description, specCount,
|
|
75
|
+
* timestamps) to render chooser UI, so this local shape stays narrow.
|
|
76
|
+
*/
|
|
77
|
+
export interface InitProject {
|
|
78
|
+
/** Unique project identifier */
|
|
79
|
+
id: string;
|
|
80
|
+
/** Human-readable project name */
|
|
81
|
+
name: string;
|
|
82
|
+
/** Optional description */
|
|
83
|
+
description?: string;
|
|
84
|
+
/** Number of specifications in this project */
|
|
85
|
+
specCount?: number;
|
|
86
|
+
/** Creation timestamp */
|
|
87
|
+
createdAt?: string;
|
|
88
|
+
/** Last update timestamp */
|
|
89
|
+
updatedAt?: string;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Lightweight specification shape used by the init command's list/selection
|
|
93
|
+
* flow. Distinct from the canonical runtime `Specification` in
|
|
94
|
+
* `@specforge/types/runtime` — init only needs a subset.
|
|
95
|
+
*/
|
|
96
|
+
export interface InitSpecification {
|
|
97
|
+
/** Unique specification identifier */
|
|
98
|
+
id: string;
|
|
99
|
+
/** Specification title */
|
|
100
|
+
title: string;
|
|
101
|
+
/** Current status */
|
|
102
|
+
status: SpecificationStatus;
|
|
103
|
+
/** Number of tickets in this specification */
|
|
104
|
+
ticketCount?: number;
|
|
105
|
+
/** Number of completed tickets */
|
|
106
|
+
completedTicketCount?: number;
|
|
107
|
+
/** Optional description */
|
|
108
|
+
description?: string;
|
|
109
|
+
/** Creation timestamp */
|
|
110
|
+
createdAt?: string;
|
|
111
|
+
/** Last update timestamp */
|
|
112
|
+
updatedAt?: string;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* API response for list_projects call
|
|
116
|
+
*/
|
|
117
|
+
export interface ListProjectsResponse {
|
|
118
|
+
/** List of user's projects */
|
|
119
|
+
projects: InitProject[];
|
|
120
|
+
/** Total count (for pagination) */
|
|
121
|
+
total?: number;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* API response for list_specifications call
|
|
125
|
+
*/
|
|
126
|
+
export interface ListSpecificationsResponse {
|
|
127
|
+
/** List of specifications for the project */
|
|
128
|
+
specifications: InitSpecification[];
|
|
129
|
+
/** Total count (for pagination) */
|
|
130
|
+
total?: number;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* User's selections during init flow
|
|
134
|
+
*/
|
|
135
|
+
export interface InitSelections {
|
|
136
|
+
/** Selected project */
|
|
137
|
+
project: InitProject;
|
|
138
|
+
/** Selected specification (optional) */
|
|
139
|
+
specification?: InitSpecification;
|
|
140
|
+
/** Selected output format */
|
|
141
|
+
format: 'json' | 'toon';
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Result of checking existing config files
|
|
145
|
+
*/
|
|
146
|
+
export interface ExistingFilesCheck {
|
|
147
|
+
/** Whether .mcp.json exists */
|
|
148
|
+
mcpConfig: boolean;
|
|
149
|
+
/** Whether .specforge.json exists */
|
|
150
|
+
projectConfig: boolean;
|
|
151
|
+
/** Whether any file exists */
|
|
152
|
+
anyExists: boolean;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Inquirer choice format for project selection
|
|
156
|
+
*/
|
|
157
|
+
export interface ProjectChoice {
|
|
158
|
+
/** Display name */
|
|
159
|
+
name: string;
|
|
160
|
+
/** Project ID value */
|
|
161
|
+
value: string;
|
|
162
|
+
/** Short name (optional) */
|
|
163
|
+
short?: string;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Inquirer choice format for specification selection
|
|
167
|
+
*/
|
|
168
|
+
export interface SpecificationChoice {
|
|
169
|
+
/** Display name */
|
|
170
|
+
name: string;
|
|
171
|
+
/** Specification ID value (undefined for "none" option) */
|
|
172
|
+
value: string | undefined;
|
|
173
|
+
/** Short name (optional) */
|
|
174
|
+
short?: string;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Inquirer choice format for format selection
|
|
178
|
+
*/
|
|
179
|
+
export interface FormatChoice {
|
|
180
|
+
/** Display name */
|
|
181
|
+
name: string;
|
|
182
|
+
/** Format value */
|
|
183
|
+
value: 'json' | 'toon';
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Format display names with descriptions
|
|
187
|
+
*/
|
|
188
|
+
export declare const FORMAT_CHOICES: FormatChoice[];
|
|
189
|
+
/**
|
|
190
|
+
* Default format selection
|
|
191
|
+
*/
|
|
192
|
+
export declare const DEFAULT_FORMAT: 'json' | 'toon';
|
|
193
|
+
//# sourceMappingURL=init.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.types.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const STRATEGY_CHOICES = [
|
|
2
|
+
{ name: "auto (Recommended)", value: "auto" },
|
|
3
|
+
{ name: "single - Sequential, one worker", value: "single" },
|
|
4
|
+
{ name: "parallel - All epic teams run concurrently", value: "parallel" },
|
|
5
|
+
{ name: "phased - Dependency-ordered phases", value: "phased" }
|
|
6
|
+
];
|
|
7
|
+
const SKILL_TEMPLATE_FILES = [
|
|
8
|
+
"specforge-orchestrator",
|
|
9
|
+
"specforge-worker",
|
|
10
|
+
"specforge-validator"
|
|
11
|
+
];
|
|
12
|
+
const FORMAT_CHOICES = [
|
|
13
|
+
{
|
|
14
|
+
name: "toon (recommended - 44% fewer tokens)",
|
|
15
|
+
value: "toon"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: "json (standard JSON format)",
|
|
19
|
+
value: "json"
|
|
20
|
+
}
|
|
21
|
+
];
|
|
22
|
+
const DEFAULT_FORMAT = "toon";
|
|
23
|
+
export {
|
|
24
|
+
DEFAULT_FORMAT,
|
|
25
|
+
FORMAT_CHOICES,
|
|
26
|
+
SKILL_TEMPLATE_FILES,
|
|
27
|
+
STRATEGY_CHOICES
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=init.types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/commands/init.types.ts"],"sourcesContent":["/**\n * Init Command Types\n *\n * Type definitions for the init command including options,\n * API responses, and selection interfaces.\n */\n\n/**\n * Command line options for init command\n */\nexport interface InitOptions {\n /** Project ID for non-interactive mode */\n project?: string;\n\n /** Specification ID for non-interactive mode, or true when --spec is used without an ID */\n spec?: string | true;\n\n /** Output format preference */\n format?: 'json' | 'toon';\n\n /** Force overwrite existing config files */\n force?: boolean;\n\n /** Show current configuration settings */\n show?: boolean;\n\n /** Skip all interactive prompts, use defaults */\n yes?: boolean;\n\n /** Switch active specification (quick switch) */\n specOnly?: boolean;\n}\n\n/**\n * Agent Teams configuration collected during init (v2.0.0).\n * Claude Code Agent Teams only.\n */\nexport interface AgentTeamsInitOptions {\n /** Whether to configure Agent Teams */\n enabled: boolean;\n\n /** Execution strategy */\n strategy: 'auto' | 'single' | 'parallel' | 'phased';\n\n /** Max tickets per team (1-20) */\n maxTicketsPerTeam: number;\n\n /** Max parallel epics (1-10) */\n maxParallelEpics: number;\n\n /** Branch prefix for ticket branches */\n branchPrefix: string;\n}\n\n/**\n * Strategy choices for Agent Teams init prompt\n */\nexport const STRATEGY_CHOICES = [\n { name: 'auto (Recommended)', value: 'auto' as const },\n { name: 'single - Sequential, one worker', value: 'single' as const },\n { name: 'parallel - All epic teams run concurrently', value: 'parallel' as const },\n { name: 'phased - Dependency-ordered phases', value: 'phased' as const },\n];\n\n/**\n * Skill names scaffolded into `.claude/skills/<name>/SKILL.md` (the directory\n * form required by Claude Code — see https://code.claude.com/docs/en/skills).\n *\n * The source template lives at `templates/skills/<name>.md` and is written\n * to `<name>/SKILL.md` under the project's `.claude/skills/` directory.\n *\n * `specforge-conventions` is handled by scaffoldMultiCli's writeSkillForTarget\n * and is intentionally excluded here to avoid a duplicate write.\n */\nexport const SKILL_TEMPLATE_FILES = [\n 'specforge-orchestrator',\n 'specforge-worker',\n 'specforge-validator',\n] as const;\n\nimport type { SpecificationStatus } from '@specforge/types/schema';\n\n/**\n * Lightweight project shape used by the init command's list/selection flow.\n *\n * Distinct from the canonical runtime `Project` in `@specforge/types/runtime`\n * — init only needs a subset of fields (name, description, specCount,\n * timestamps) to render chooser UI, so this local shape stays narrow.\n */\nexport interface InitProject {\n /** Unique project identifier */\n id: string;\n\n /** Human-readable project name */\n name: string;\n\n /** Optional description */\n description?: string;\n\n /** Number of specifications in this project */\n specCount?: number;\n\n /** Creation timestamp */\n createdAt?: string;\n\n /** Last update timestamp */\n updatedAt?: string;\n}\n\n/**\n * Lightweight specification shape used by the init command's list/selection\n * flow. Distinct from the canonical runtime `Specification` in\n * `@specforge/types/runtime` — init only needs a subset.\n */\nexport interface InitSpecification {\n /** Unique specification identifier */\n id: string;\n\n /** Specification title */\n title: string;\n\n /** Current status */\n status: SpecificationStatus;\n\n /** Number of tickets in this specification */\n ticketCount?: number;\n\n /** Number of completed tickets */\n completedTicketCount?: number;\n\n /** Optional description */\n description?: string;\n\n /** Creation timestamp */\n createdAt?: string;\n\n /** Last update timestamp */\n updatedAt?: string;\n}\n\n/**\n * API response for list_projects call\n */\nexport interface ListProjectsResponse {\n /** List of user's projects */\n projects: InitProject[];\n\n /** Total count (for pagination) */\n total?: number;\n}\n\n/**\n * API response for list_specifications call\n */\nexport interface ListSpecificationsResponse {\n /** List of specifications for the project */\n specifications: InitSpecification[];\n\n /** Total count (for pagination) */\n total?: number;\n}\n\n/**\n * User's selections during init flow\n */\nexport interface InitSelections {\n /** Selected project */\n project: InitProject;\n\n /** Selected specification (optional) */\n specification?: InitSpecification;\n\n /** Selected output format */\n format: 'json' | 'toon';\n}\n\n/**\n * Result of checking existing config files\n */\nexport interface ExistingFilesCheck {\n /** Whether .mcp.json exists */\n mcpConfig: boolean;\n\n /** Whether .specforge.json exists */\n projectConfig: boolean;\n\n /** Whether any file exists */\n anyExists: boolean;\n}\n\n/**\n * Inquirer choice format for project selection\n */\nexport interface ProjectChoice {\n /** Display name */\n name: string;\n\n /** Project ID value */\n value: string;\n\n /** Short name (optional) */\n short?: string;\n}\n\n/**\n * Inquirer choice format for specification selection\n */\nexport interface SpecificationChoice {\n /** Display name */\n name: string;\n\n /** Specification ID value (undefined for \"none\" option) */\n value: string | undefined;\n\n /** Short name (optional) */\n short?: string;\n}\n\n/**\n * Inquirer choice format for format selection\n */\nexport interface FormatChoice {\n /** Display name */\n name: string;\n\n /** Format value */\n value: 'json' | 'toon';\n}\n\n/**\n * Format display names with descriptions\n */\nexport const FORMAT_CHOICES: FormatChoice[] = [\n {\n name: 'toon (recommended - 44% fewer tokens)',\n value: 'toon',\n },\n {\n name: 'json (standard JSON format)',\n value: 'json',\n },\n];\n\n/**\n * Default format selection\n */\nexport const DEFAULT_FORMAT: 'json' | 'toon' = 'toon';\n"],"mappings":"AAyDO,MAAM,mBAAmB;AAAA,EAC9B,EAAE,MAAM,sBAAsB,OAAO,OAAgB;AAAA,EACrD,EAAE,MAAM,mCAAmC,OAAO,SAAkB;AAAA,EACpE,EAAE,MAAM,8CAA8C,OAAO,WAAoB;AAAA,EACjF,EAAE,MAAM,sCAAsC,OAAO,SAAkB;AACzE;AAYO,MAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AACF;AA0JO,MAAM,iBAAiC;AAAA,EAC5C;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AACF;AAKO,MAAM,iBAAkC;","names":[]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Invitations Command
|
|
3
|
+
*
|
|
4
|
+
* Manage project invitations - view received, accept, decline.
|
|
5
|
+
*/
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
/**
|
|
8
|
+
* Options for invitations command
|
|
9
|
+
*/
|
|
10
|
+
interface InvitationsOptions {
|
|
11
|
+
sent?: boolean;
|
|
12
|
+
json?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* List invitations action handler
|
|
16
|
+
*/
|
|
17
|
+
export declare function invitationsListAction(options: InvitationsOptions): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Accept invitation action handler
|
|
20
|
+
*/
|
|
21
|
+
export declare function invitationsAcceptAction(idOrToken: string): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Decline invitation action handler
|
|
24
|
+
*/
|
|
25
|
+
export declare function invitationsDeclineAction(idOrToken: string): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Register invitations command with Commander
|
|
28
|
+
*/
|
|
29
|
+
export declare function registerInvitationsCommand(program: Command): void;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=invitations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invitations.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/invitations.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8CpC;;GAEG;AACH,UAAU,kBAAkB;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AA0HD;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+CtF;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgD9E;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2C/E;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmBjE"}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import ora from "ora";
|
|
2
|
+
import Table from "cli-table3";
|
|
3
|
+
import { resolveConfig } from "../config/index.js";
|
|
4
|
+
import { withErrorHandler, CliError, NetworkError } from "../middleware/error-handler.js";
|
|
5
|
+
import { printBlank, printHeader } from "../ui/output.js";
|
|
6
|
+
import { colors } from "../ui/colors.js";
|
|
7
|
+
import { formatRelativeTime } from "../ui/time.js";
|
|
8
|
+
import { createCliClient } from "../../client/cli-client.js";
|
|
9
|
+
function getRoleBadge(role) {
|
|
10
|
+
switch (role) {
|
|
11
|
+
case "owner":
|
|
12
|
+
return colors.warning("owner");
|
|
13
|
+
case "editor":
|
|
14
|
+
return colors.primary("editor");
|
|
15
|
+
case "viewer":
|
|
16
|
+
return colors.muted("viewer");
|
|
17
|
+
default:
|
|
18
|
+
return role;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function displayReceivedInvitations(invitations) {
|
|
22
|
+
if (invitations.length === 0) {
|
|
23
|
+
console.log(colors.muted("No pending invitations."));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
printHeader("Received Invitations");
|
|
27
|
+
printBlank();
|
|
28
|
+
const table = new Table({
|
|
29
|
+
head: [
|
|
30
|
+
colors.muted("PROJECT"),
|
|
31
|
+
colors.muted("ROLE"),
|
|
32
|
+
colors.muted("INVITED"),
|
|
33
|
+
colors.muted("ID")
|
|
34
|
+
],
|
|
35
|
+
style: { head: [], border: [] },
|
|
36
|
+
chars: {
|
|
37
|
+
"top": "",
|
|
38
|
+
"top-mid": "",
|
|
39
|
+
"top-left": "",
|
|
40
|
+
"top-right": "",
|
|
41
|
+
"bottom": "",
|
|
42
|
+
"bottom-mid": "",
|
|
43
|
+
"bottom-left": "",
|
|
44
|
+
"bottom-right": "",
|
|
45
|
+
"left": "",
|
|
46
|
+
"left-mid": "",
|
|
47
|
+
"mid": "",
|
|
48
|
+
"mid-mid": "",
|
|
49
|
+
"right": "",
|
|
50
|
+
"right-mid": "",
|
|
51
|
+
"middle": " "
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
for (const inv of invitations) {
|
|
55
|
+
table.push([
|
|
56
|
+
inv.projectName || inv.projectId,
|
|
57
|
+
getRoleBadge(inv.role),
|
|
58
|
+
formatRelativeTime(inv.invitedAt),
|
|
59
|
+
colors.muted(inv.id.substring(0, 12) + "...")
|
|
60
|
+
]);
|
|
61
|
+
}
|
|
62
|
+
console.log(table.toString());
|
|
63
|
+
printBlank();
|
|
64
|
+
console.log(colors.muted("Accept: specforge invitations accept <id>"));
|
|
65
|
+
console.log(colors.muted("Decline: specforge invitations decline <id>"));
|
|
66
|
+
}
|
|
67
|
+
function displaySentInvitations(invitations) {
|
|
68
|
+
if (invitations.length === 0) {
|
|
69
|
+
console.log(colors.muted("No sent invitations."));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
printBlank();
|
|
73
|
+
printHeader("Sent Invitations");
|
|
74
|
+
printBlank();
|
|
75
|
+
const table = new Table({
|
|
76
|
+
head: [
|
|
77
|
+
colors.muted("EMAIL"),
|
|
78
|
+
colors.muted("PROJECT"),
|
|
79
|
+
colors.muted("ROLE"),
|
|
80
|
+
colors.muted("STATUS"),
|
|
81
|
+
colors.muted("SENT")
|
|
82
|
+
],
|
|
83
|
+
style: { head: [], border: [] },
|
|
84
|
+
chars: {
|
|
85
|
+
"top": "",
|
|
86
|
+
"top-mid": "",
|
|
87
|
+
"top-left": "",
|
|
88
|
+
"top-right": "",
|
|
89
|
+
"bottom": "",
|
|
90
|
+
"bottom-mid": "",
|
|
91
|
+
"bottom-left": "",
|
|
92
|
+
"bottom-right": "",
|
|
93
|
+
"left": "",
|
|
94
|
+
"left-mid": "",
|
|
95
|
+
"mid": "",
|
|
96
|
+
"mid-mid": "",
|
|
97
|
+
"right": "",
|
|
98
|
+
"right-mid": "",
|
|
99
|
+
"middle": " "
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
for (const inv of invitations) {
|
|
103
|
+
let statusBadge;
|
|
104
|
+
switch (inv.status) {
|
|
105
|
+
case "pending":
|
|
106
|
+
statusBadge = colors.warning("pending");
|
|
107
|
+
break;
|
|
108
|
+
case "accepted":
|
|
109
|
+
statusBadge = colors.success("accepted");
|
|
110
|
+
break;
|
|
111
|
+
case "expired":
|
|
112
|
+
statusBadge = colors.error("expired");
|
|
113
|
+
break;
|
|
114
|
+
case "cancelled":
|
|
115
|
+
statusBadge = colors.muted("cancelled");
|
|
116
|
+
break;
|
|
117
|
+
default:
|
|
118
|
+
statusBadge = inv.status;
|
|
119
|
+
}
|
|
120
|
+
table.push([
|
|
121
|
+
inv.email,
|
|
122
|
+
inv.projectName || inv.projectId.substring(0, 12) + "...",
|
|
123
|
+
getRoleBadge(inv.role),
|
|
124
|
+
statusBadge,
|
|
125
|
+
formatRelativeTime(inv.createdAt)
|
|
126
|
+
]);
|
|
127
|
+
}
|
|
128
|
+
console.log(table.toString());
|
|
129
|
+
}
|
|
130
|
+
async function invitationsListAction(options) {
|
|
131
|
+
const config = resolveConfig();
|
|
132
|
+
if (!config.apiKey) {
|
|
133
|
+
throw new CliError(
|
|
134
|
+
"Not authenticated",
|
|
135
|
+
1,
|
|
136
|
+
"Run `specforge login` to authenticate first"
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
const spinner = ora({
|
|
140
|
+
text: "Fetching invitations...",
|
|
141
|
+
color: "cyan"
|
|
142
|
+
}).start();
|
|
143
|
+
try {
|
|
144
|
+
const client = createCliClient({
|
|
145
|
+
apiKey: config.apiKey,
|
|
146
|
+
apiUrl: config.apiUrl,
|
|
147
|
+
debug: config.debug
|
|
148
|
+
});
|
|
149
|
+
const response = await client.call("list_invitations", {
|
|
150
|
+
includeSent: options.sent
|
|
151
|
+
});
|
|
152
|
+
spinner.stop();
|
|
153
|
+
if (options.json) {
|
|
154
|
+
console.log(JSON.stringify(response, null, 2));
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
printBlank();
|
|
158
|
+
displayReceivedInvitations(response.received);
|
|
159
|
+
if (options.sent && response.sent) {
|
|
160
|
+
displaySentInvitations(response.sent);
|
|
161
|
+
}
|
|
162
|
+
printBlank();
|
|
163
|
+
} catch (error) {
|
|
164
|
+
spinner.fail("Failed to fetch invitations");
|
|
165
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
166
|
+
throw new NetworkError(`Failed to fetch invitations: ${message}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async function invitationsAcceptAction(idOrToken) {
|
|
170
|
+
const config = resolveConfig();
|
|
171
|
+
if (!config.apiKey) {
|
|
172
|
+
throw new CliError(
|
|
173
|
+
"Not authenticated",
|
|
174
|
+
1,
|
|
175
|
+
"Run `specforge login` to authenticate first"
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
const spinner = ora({
|
|
179
|
+
text: "Accepting invitation...",
|
|
180
|
+
color: "cyan"
|
|
181
|
+
}).start();
|
|
182
|
+
try {
|
|
183
|
+
const client = createCliClient({
|
|
184
|
+
apiKey: config.apiKey,
|
|
185
|
+
apiUrl: config.apiUrl,
|
|
186
|
+
debug: config.debug
|
|
187
|
+
});
|
|
188
|
+
const args = {};
|
|
189
|
+
if (idOrToken.startsWith("proj_inv_")) {
|
|
190
|
+
args.token = idOrToken;
|
|
191
|
+
} else {
|
|
192
|
+
args.invitationId = idOrToken;
|
|
193
|
+
}
|
|
194
|
+
const response = await client.call("accept_project_invitation", args);
|
|
195
|
+
spinner.succeed(`Joined ${response.projectName} as ${response.role}`);
|
|
196
|
+
printBlank();
|
|
197
|
+
console.log(colors.muted(response.message));
|
|
198
|
+
printBlank();
|
|
199
|
+
} catch (error) {
|
|
200
|
+
spinner.fail("Failed to accept invitation");
|
|
201
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
202
|
+
throw new NetworkError(`Failed to accept invitation: ${message}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
async function invitationsDeclineAction(idOrToken) {
|
|
206
|
+
const config = resolveConfig();
|
|
207
|
+
if (!config.apiKey) {
|
|
208
|
+
throw new CliError(
|
|
209
|
+
"Not authenticated",
|
|
210
|
+
1,
|
|
211
|
+
"Run `specforge login` to authenticate first"
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
const spinner = ora({
|
|
215
|
+
text: "Declining invitation...",
|
|
216
|
+
color: "cyan"
|
|
217
|
+
}).start();
|
|
218
|
+
try {
|
|
219
|
+
const client = createCliClient({
|
|
220
|
+
apiKey: config.apiKey,
|
|
221
|
+
apiUrl: config.apiUrl,
|
|
222
|
+
debug: config.debug
|
|
223
|
+
});
|
|
224
|
+
const args = {};
|
|
225
|
+
if (idOrToken.startsWith("proj_inv_")) {
|
|
226
|
+
args.token = idOrToken;
|
|
227
|
+
} else {
|
|
228
|
+
args.invitationId = idOrToken;
|
|
229
|
+
}
|
|
230
|
+
const response = await client.call("decline_project_invitation", args);
|
|
231
|
+
spinner.succeed("Invitation declined");
|
|
232
|
+
printBlank();
|
|
233
|
+
} catch (error) {
|
|
234
|
+
spinner.fail("Failed to decline invitation");
|
|
235
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
236
|
+
throw new NetworkError(`Failed to decline invitation: ${message}`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function registerInvitationsCommand(program) {
|
|
240
|
+
const invitationsCmd = program.command("invitations").description("Manage project invitations").option("--sent", "Include sent invitations").option("--json", "Output as JSON").action(withErrorHandler(invitationsListAction));
|
|
241
|
+
invitationsCmd.command("accept <id-or-token>").description("Accept a project invitation").action(withErrorHandler(invitationsAcceptAction));
|
|
242
|
+
invitationsCmd.command("decline <id-or-token>").description("Decline a project invitation").action(withErrorHandler(invitationsDeclineAction));
|
|
243
|
+
}
|
|
244
|
+
export {
|
|
245
|
+
invitationsAcceptAction,
|
|
246
|
+
invitationsDeclineAction,
|
|
247
|
+
invitationsListAction,
|
|
248
|
+
registerInvitationsCommand
|
|
249
|
+
};
|
|
250
|
+
//# sourceMappingURL=invitations.js.map
|