hub-launch 1.27.0 → 1.29.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +2 -1
  3. package/dist/commands/init.d.ts.map +1 -1
  4. package/dist/commands/init.js +2 -0
  5. package/dist/commands/init.js.map +1 -1
  6. package/dist/commands/launch.d.ts +6 -0
  7. package/dist/commands/launch.d.ts.map +1 -1
  8. package/dist/commands/launch.js +47 -54
  9. package/dist/commands/launch.js.map +1 -1
  10. package/dist/commands/schedule.d.ts.map +1 -1
  11. package/dist/commands/schedule.js +20 -2
  12. package/dist/commands/schedule.js.map +1 -1
  13. package/dist/commands/upload.d.ts +10 -0
  14. package/dist/commands/upload.d.ts.map +1 -1
  15. package/dist/commands/upload.js +58 -2
  16. package/dist/commands/upload.js.map +1 -1
  17. package/dist/services/git/FilePublishService.d.ts +7 -0
  18. package/dist/services/git/FilePublishService.d.ts.map +1 -1
  19. package/dist/services/git/FilePublishService.js +10 -4
  20. package/dist/services/git/FilePublishService.js.map +1 -1
  21. package/dist/services/plan/PlanBranchService.d.ts +38 -0
  22. package/dist/services/plan/PlanBranchService.d.ts.map +1 -0
  23. package/dist/services/plan/PlanBranchService.js +95 -0
  24. package/dist/services/plan/PlanBranchService.js.map +1 -0
  25. package/dist/templates/proceed-instructions.md +3 -2
  26. package/dist/templates/skills/hula-help/SKILL.md +1 -1
  27. package/dist/templates/skills/hula-launch/SKILL.md +2 -2
  28. package/dist/templates/skills/hula-plan/SKILL.md +18 -2
  29. package/dist/templates/skills/hula-research/SKILL.md +162 -0
  30. package/dist/templates/skills/hula-upload/SKILL.md +2 -2
  31. package/dist/utils/validators.d.ts +8 -0
  32. package/dist/utils/validators.d.ts.map +1 -1
  33. package/dist/utils/validators.js +10 -0
  34. package/dist/utils/validators.js.map +1 -1
  35. package/package.json +1 -1
  36. package/scripts/postinstall.mjs +1 -0
@@ -115,8 +115,11 @@ export class FilePublishService {
115
115
  * commit (with `commitMessage`) if it produced changes, push to the branch,
116
116
  * and always remove the worktree afterward.
117
117
  */
118
- async withWorktree(type, branch, commitMessage, operation) {
118
+ async withWorktree(type, branch, commitMessage, operation, createFromRef) {
119
119
  this.validateBranch(branch);
120
+ if (createFromRef !== undefined) {
121
+ this.validateBranch(createFromRef);
122
+ }
120
123
  const worktreeBasePath = await this.resolveWorktreeBasePath();
121
124
  const repoInfo = await getRepoInfo(this.cwd);
122
125
  const worktreeService = new WorktreeService({
@@ -129,7 +132,7 @@ export class FilePublishService {
129
132
  const worktreePath = worktreeService.getWorktreeDir(type, identifier);
130
133
  let worktreeCreated = false;
131
134
  try {
132
- await worktreeService.createWorktreeAt(worktreePath, `origin/${branch}`, true);
135
+ await worktreeService.createWorktreeAt(worktreePath, createFromRef ?? `origin/${branch}`, true);
133
136
  worktreeCreated = true;
134
137
  operation(worktreePath);
135
138
  const hasChanges = await worktreeService.hasChangesAt(worktreePath);
@@ -149,7 +152,10 @@ export class FilePublishService {
149
152
  let lastError;
150
153
  for (let attempt = 1; attempt <= MAX_PUSH_ATTEMPTS; attempt++) {
151
154
  try {
152
- await worktreeService.pushAt(worktreePath, `HEAD:${branch}`);
155
+ // Fully-qualified destination so the push also CREATES the branch on
156
+ // origin when it does not exist yet (an unqualified `HEAD:<branch>`
157
+ // is rejected for a nonexistent destination ref).
158
+ await worktreeService.pushAt(worktreePath, `HEAD:refs/heads/${branch}`);
153
159
  lastError = undefined;
154
160
  break; // pushed successfully
155
161
  }
@@ -206,7 +212,7 @@ export class FilePublishService {
206
212
  const filePath = join(worktreePath, relativePath);
207
213
  mkdirSync(dirname(filePath), { recursive: true });
208
214
  writeFileSync(filePath, content, 'utf-8');
209
- });
215
+ }, opts?.createFromRef);
210
216
  }
211
217
  /**
212
218
  * Delete a file from the target branch.
@@ -1 +1 @@
1
- {"version":3,"file":"FilePublishService.js","sourceRoot":"","sources":["../../../src/services/git/FilePublishService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD;;;GAGG;AACH,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAE5B;;;;GAIG;AACH,MAAM,eAAe,GAAG,GAAG,CAAC;AAE5B;;;;;GAKG;AACH,MAAM,eAAe,GAAG;IACtB,iBAAiB;IACjB,0BAA0B;IAC1B,mBAAmB;IACnB,aAAa;IACb,kBAAkB;CACnB,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,MAAM,CAAC,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAChC,OAAO,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;AACpE,CAAC;AAED;;GAEG;AACH,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC;AAYD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,kBAAkB;IACZ,MAAM,CAAS;IACf,GAAG,CAAU;IAE9B;;;;;;OAMG;IACH,YAAY,MAAc,EAAE,GAAY;QACtC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;IAED;;OAEG;IACK,aAAa;QACnB,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC;IAC5C,CAAC;IAED;;;OAGG;IACK,cAAc,CAAC,MAAc;QACnC,IACE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;YACpB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;YACpB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;YACpB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;YACpB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;YACpB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;YACrB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;YACrB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;YACrB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;YACrB,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EACpB,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,0BAA0B,MAAM,GAAG,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,uBAAuB;QACnC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,gBAAgB,IAAI,iBAAiB,CAAC;QACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,WAAW,EAAE,CAAC,CAAC;QACnD,OAAO,UAAU,CAAC,WAAW,CAAC;YAC5B,CAAC,CAAC,WAAW;YACb,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IACrC,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,YAAY,CACxB,IAAY,EACZ,MAAc,EACd,aAAqB,EACrB,SAAyC;QAEzC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAE5B,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAC9D,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7C,MAAM,eAAe,GAAG,IAAI,eAAe,CAAC;YAC1C,QAAQ,EAAE,gBAAgB;YAC1B,QAAQ,EAAE,QAAQ,CAAC,IAAI;YACvB,GAAG,EAAE,IAAI,CAAC,GAAG;SACd,CAAC,CAAC;QAEH,+EAA+E;QAC/E,MAAM,UAAU,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QACnC,MAAM,YAAY,GAAG,eAAe,CAAC,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAEtE,IAAI,eAAe,GAAG,KAAK,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,eAAe,CAAC,gBAAgB,CACpC,YAAY,EACZ,UAAU,MAAM,EAAE,EAClB,IAAI,CACL,CAAC;YACF,eAAe,GAAG,IAAI,CAAC;YAEvB,SAAS,CAAC,YAAY,CAAC,CAAC;YAExB,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;YACpE,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,eAAe,CAAC,eAAe,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;YACrE,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;YAC7D,CAAC;YAED,mEAAmE;YACnE,kEAAkE;YAClE,gEAAgE;YAChE,uEAAuE;YACvE,sEAAsE;YACtE,oEAAoE;YACpE,2EAA2E;YAC3E,IAAI,SAAkB,CAAC;YACvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,iBAAiB,EAAE,OAAO,EAAE,EAAE,CAAC;gBAC9D,IAAI,CAAC;oBACH,MAAM,eAAe,CAAC,MAAM,CAAC,YAAY,EAAE,QAAQ,MAAM,EAAE,CAAC,CAAC;oBAC7D,SAAS,GAAG,SAAS,CAAC;oBACtB,MAAM,CAAC,sBAAsB;gBAC/B,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,SAAS,GAAG,KAAK,CAAC;oBAClB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBAEvE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;wBAC1B,MAAM,KAAK,CAAC,CAAC,yCAAyC;oBACxD,CAAC;oBAED,IAAI,OAAO,KAAK,iBAAiB,EAAE,CAAC;wBAClC,MAAM,CAAC,sDAAsD;oBAC/D,CAAC;oBAED,MAAM,OAAO,GAAG,eAAe,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;oBACrD,MAAM,CAAC,IAAI,CACT,UAAU,MAAM,gDAAgD;wBAC9D,iBAAiB,OAAO,GAAG,CAAC,IAAI,iBAAiB,MAAM,CAC1D,CAAC;oBACF,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;oBAErB,iEAAiE;oBACjE,qEAAqE;oBACrE,oDAAoD;oBACpD,MAAM,eAAe,CAAC,gBAAgB,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;gBAC/D,CAAC;YACH,CAAC;YAED,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CACb,4BAA4B,MAAM,UAAU,iBAAiB,GAAG;oBAC9D,oBAAoB,MAAM,gCAAgC;oBAC1D,+DAA+D;oBAC/D,kBAAkB;oBAClB,CAAC,SAAS,YAAY,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CACvE,CAAC;YACJ,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,IAAI,eAAe,EAAE,CAAC;gBACpB,IAAI,CAAC;oBACH,MAAM,eAAe,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;gBACvD,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,OAAO,CACZ,gCAAgC,YAAY,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAC1G,CAAC;oBACF,MAAM,CAAC,IAAI,CACT,yDAAyD,YAAY,WAAW,CACjF,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,WAAW,CACf,YAAoB,EACpB,OAAe,EACf,IAAyB;QAEzB,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACpD,MAAM,aAAa,GAAG,IAAI,EAAE,aAAa,IAAI,8BAA8B,CAAC;QAE5E,MAAM,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,YAAY,EAAE,EAAE;YACzE,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;YAClD,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAClD,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,UAAU,CACd,YAAoB,EACpB,IAAyB;QAEzB,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACpD,MAAM,aAAa,GAAG,IAAI,EAAE,aAAa,IAAI,6BAA6B,CAAC;QAE3E,MAAM,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,YAAY,EAAE,EAAE;YACzE,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;YAClD,yEAAyE;YACzE,wCAAwC;YACxC,MAAM,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
1
+ {"version":3,"file":"FilePublishService.js","sourceRoot":"","sources":["../../../src/services/git/FilePublishService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { Config } from '../../types/index.js';
2
+ /**
3
+ * Outcome of {@link ensurePlanBranch}.
4
+ */
5
+ export interface EnsurePlanBranchResult {
6
+ /** The git branch name the plan lives on (sanitized issue name). */
7
+ branch: string;
8
+ /** True when the branch was created on origin by this call. */
9
+ created: boolean;
10
+ /** True when the plan file on the branch was written/refreshed by this call. */
11
+ updated: boolean;
12
+ }
13
+ /**
14
+ * Thrown when the plan file cannot be found anywhere — not on disk, not on
15
+ * the feature branch, not on the base branch. Callers translate this into the
16
+ * historical "Plan not found locally or on origin/main" error handling.
17
+ */
18
+ export declare class PlanNotFoundError extends Error {
19
+ constructor(planPath: string);
20
+ }
21
+ /**
22
+ * Ensure the feature branch for `issueName` exists on origin and carries the
23
+ * current plan file — the core of the plan-branch flow.
24
+ *
25
+ * - Branch missing on origin → create it from `origin/<uploadBranch ?? main>`
26
+ * with the plan committed (one worktree publish, one push).
27
+ * - Branch exists but the plan file on it is missing or stale → publish the
28
+ * fresh content to the branch.
29
+ * - Branch exists with identical content → no-op.
30
+ *
31
+ * This runs BEFORE the beforeLaunch hook in `hula launch`, so hooks (e.g.
32
+ * Vercel branch-scoped env vars) can rely on the git branch existing on the
33
+ * remote. It is also invoked at plan time via `hula upload --branch`.
34
+ *
35
+ * @throws PlanNotFoundError when the plan content cannot be resolved anywhere.
36
+ */
37
+ export declare function ensurePlanBranch(config: Config, planPath: string, issueName: string, repoRoot?: string): Promise<EnsurePlanBranchResult>;
38
+ //# sourceMappingURL=PlanBranchService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlanBranchService.d.ts","sourceRoot":"","sources":["../../../src/services/plan/PlanBranchService.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAMnD;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,OAAO,EAAE,OAAO,CAAC;IACjB,gFAAgF;IAChF,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,QAAQ,EAAE,MAAM;CAI7B;AAmCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,sBAAsB,CAAC,CAsDjC"}
@@ -0,0 +1,95 @@
1
+ import { existsSync, readFileSync } from 'fs';
2
+ import { isAbsolute, join } from 'path';
3
+ import { sanitizePlanName } from '../../utils/validators.js';
4
+ import { GitService } from '../git/GitService.js';
5
+ import { FilePublishService } from '../git/FilePublishService.js';
6
+ import { PlanService } from './PlanService.js';
7
+ /**
8
+ * Thrown when the plan file cannot be found anywhere — not on disk, not on
9
+ * the feature branch, not on the base branch. Callers translate this into the
10
+ * historical "Plan not found locally or on origin/main" error handling.
11
+ */
12
+ export class PlanNotFoundError extends Error {
13
+ constructor(planPath) {
14
+ super(`Plan not found locally or on any git ref: ${planPath}`);
15
+ this.name = 'PlanNotFoundError';
16
+ }
17
+ }
18
+ /**
19
+ * Resolve the plan's content, preferring the freshest source:
20
+ * 1. the working tree (where /hula-plan writes and validation edits it)
21
+ * 2. the feature branch on origin (plan-branch flow, plan already pushed)
22
+ * 3. the base branch on origin, then local base (legacy plans, relaunches)
23
+ *
24
+ * Returns `null` when the plan exists nowhere.
25
+ */
26
+ async function resolvePlanContent(gitService, relativePath, planFsPath, branch, branchOnOrigin, baseBranch) {
27
+ if (existsSync(planFsPath)) {
28
+ return readFileSync(planFsPath, 'utf-8');
29
+ }
30
+ if (branchOnOrigin &&
31
+ (await gitService.fileExistsOnRef(`origin/${branch}`, relativePath))) {
32
+ return gitService.showFile(`origin/${branch}`, relativePath);
33
+ }
34
+ for (const ref of [`origin/${baseBranch}`, baseBranch]) {
35
+ if (await gitService.fileExistsOnRef(ref, relativePath)) {
36
+ return gitService.showFile(ref, relativePath);
37
+ }
38
+ }
39
+ return null;
40
+ }
41
+ /**
42
+ * Ensure the feature branch for `issueName` exists on origin and carries the
43
+ * current plan file — the core of the plan-branch flow.
44
+ *
45
+ * - Branch missing on origin → create it from `origin/<uploadBranch ?? main>`
46
+ * with the plan committed (one worktree publish, one push).
47
+ * - Branch exists but the plan file on it is missing or stale → publish the
48
+ * fresh content to the branch.
49
+ * - Branch exists with identical content → no-op.
50
+ *
51
+ * This runs BEFORE the beforeLaunch hook in `hula launch`, so hooks (e.g.
52
+ * Vercel branch-scoped env vars) can rely on the git branch existing on the
53
+ * remote. It is also invoked at plan time via `hula upload --branch`.
54
+ *
55
+ * @throws PlanNotFoundError when the plan content cannot be resolved anywhere.
56
+ */
57
+ export async function ensurePlanBranch(config, planPath, issueName, repoRoot) {
58
+ const branch = sanitizePlanName(issueName);
59
+ const baseBranch = config.uploadBranch ?? 'main';
60
+ const gitService = new GitService(repoRoot);
61
+ const planService = new PlanService(config.planPath);
62
+ const relativePath = planService.getRelativePath(planPath);
63
+ const planFsPath = isAbsolute(planPath) || !repoRoot ? planPath : join(repoRoot, planPath);
64
+ // One fetch up front so every origin/<ref> read below is current.
65
+ await gitService.fetch('origin');
66
+ const branchOnOrigin = await gitService.remoteBranchExists(branch);
67
+ const content = await resolvePlanContent(gitService, relativePath, planFsPath, branch, branchOnOrigin, baseBranch);
68
+ if (content === null) {
69
+ throw new PlanNotFoundError(planPath);
70
+ }
71
+ if (branchOnOrigin) {
72
+ // Skip the publish when the branch already holds this exact content.
73
+ // `git show` output matches committed bytes, so string equality is exact.
74
+ if (await gitService.fileExistsOnRef(`origin/${branch}`, relativePath)) {
75
+ const onBranch = await gitService.showFile(`origin/${branch}`, relativePath);
76
+ if (onBranch === content) {
77
+ return { branch, created: false, updated: false };
78
+ }
79
+ }
80
+ const publisher = new FilePublishService(config, repoRoot);
81
+ await publisher.publishFile(relativePath, content, {
82
+ commitMessage: 'chore: update plan via hula',
83
+ branch,
84
+ });
85
+ return { branch, created: false, updated: true };
86
+ }
87
+ const publisher = new FilePublishService(config, repoRoot);
88
+ await publisher.publishFile(relativePath, content, {
89
+ commitMessage: 'chore: create plan branch via hula',
90
+ branch,
91
+ createFromRef: `origin/${baseBranch}`,
92
+ });
93
+ return { branch, created: true, updated: true };
94
+ }
95
+ //# sourceMappingURL=PlanBranchService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlanBranchService.js","sourceRoot":"","sources":["../../../src/services/plan/PlanBranchService.ts"],"names":[],"mappings":"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"}
@@ -378,8 +378,9 @@ After the Completion Format block is printed, offer to launch the plan for the u
378
378
 
379
379
  Determine `<issueName>` before asking the question:
380
380
 
381
- 1. **Look for a name the user specified** anywhere in this conversation — e.g. "use the branch name `foo`", "call the issue `bar`", or a name passed in the original `/hula-plan` arguments. If more than one was mentioned, **the most recent wins**. Use that name verbatim (kebab-case it if needed).
382
- 2. **Otherwise derive the default from the plan file's basename** (the subfolder is never part of the name):
381
+ 1. **Look for a plan-branch created earlier in this session** — a `<!-- hula-branch: <name> -->` comment in the chat history (emitted by `/hula-plan` when it created the feature branch at plan time). If present, that name is the default: the branch already exists on origin with the plan on it.
382
+ 2. **Look for a name the user specified** anywhere in this conversation — e.g. "use the branch name `foo`", "call the issue `bar`", or a name passed in the original `/hula-plan` arguments. If more than one was mentioned, **the most recent wins**, and a user-specified name overrides the plan-branch default. Use that name verbatim (kebab-case it if needed). (Launching under a different name than the plan branch is fine — `hula launch` creates the new branch automatically; the unused plan branch can be deleted later.)
383
+ 3. **Otherwise derive the default from the plan file's basename** (the subfolder is never part of the name):
383
384
  - Strip the leading timestamp prefix matching `YYYY-MM-DD-HH:MM-` and the trailing `.md`.
384
385
  - The remaining text is the title slug (e.g. `auto-launch-offer-after-plan`).
385
386
  - If the slug is **longer than 3 words**, shorten it to the 2–3 most distinctive words (e.g. `auto-launch-offer-after-plan` → `auto-launch`). Otherwise keep it as-is.
@@ -86,7 +86,7 @@ Read `README.md`'s "Quick Start" and "Requirements" sections (and the "Core Work
86
86
  Read the "Core Workflow" section of `README.md` live. Explain each step in plain language — one at a time if the user wants depth, or as a compact list if they want the overview:
87
87
 
88
88
  - `/hula-plan <description>` — writes a plan file to `.hublaunch/plans/`, validates it automatically.
89
- - `/hula-upload` — syncs the plan to `origin/main` (usually automatic as part of `/hula-launch`, rarely needed standalone).
89
+ - `/hula-upload` — publishes the plan to its feature branch (`hula upload --branch <name>`) or to `origin/main` (usually automatic as part of `/hula-plan` and `/hula-launch`, rarely needed standalone).
90
90
  - `/hula-launch <name>` — creates the GitHub issue, runs the AI coding session in an isolated cloud container, opens a PR.
91
91
  - `/hula-verify` — checks the PR against the plan's acceptance criteria.
92
92
  - `/hula-fix <instructions>` — addresses gaps found by verify, or anything else you want changed on the PR branch.
@@ -153,6 +153,6 @@ The `cliOutput` already contains the per-repo roster, ✓/✗ summary, and any r
153
153
 
154
154
  ## Important Notes
155
155
 
156
- - Do NOT call the `Read` tool to check if the plan file exists. The `hula launch` CLI validates file existence (locally and on `origin/main`) and reports errors clearly.
157
- - Do NOT run `hula upload` separately. `hula launch` handles upload automatically.
156
+ - Do NOT call the `Read` tool to check if the plan file exists. The `hula launch` CLI validates file existence (locally, on the plan's feature branch, and on `origin/main`) and reports errors clearly.
157
+ - Do NOT run `hula upload` separately. `hula launch` publishes the plan to its feature branch automatically (creating the branch from the base branch if `/hula-plan` didn't already, and refreshing it after validation edits or a rename).
158
158
  - This command is typically run after `/hula-plan` and `/hula-confirm`.
@@ -122,17 +122,33 @@ The plan should be immediately actionable by a developer familiar with the codeb
122
122
 
123
123
  **⚠️ NEVER create plan files in the project root directory.** The plan file MUST always be inside the `.hublaunch/plans/` directory (or a subfolder of it). If you cannot read the config file, use the default path `.hublaunch/plans/`.
124
124
 
125
- ### Step 2: Output the Plan Path and Next Steps
125
+ ### Step 2: Create the Plan Branch
126
+
127
+ Right after saving the plan file, create the feature branch on origin with the plan committed to it. This is the **plan-branch flow**: the git branch exists from plan time onward, so branch-scoped infrastructure (Vercel Preview env vars, per-branch databases, beforeLaunch hooks) can rely on it well before the launch.
128
+
129
+ 1. **Resolve `<issueName>`** using the same rules as the Launch Offer's "Resolve the issue name" step in `hula instructions proceed`: a name the user specified anywhere in this conversation wins (most recent first); otherwise derive the default from the plan file's basename (strip the `YYYY-MM-DD-HH:MM-` prefix and `.md`, shorten a >3-word slug to its 2–3 most distinctive words, always kebab-case).
130
+ 2. **Create the branch** by running:
131
+
132
+ `hula upload <planPath> --branch <issueName>`
133
+
134
+ This creates branch `<issueName>` (sanitized) on origin from the base branch with the plan file committed, or refreshes the plan on the branch if it already exists.
135
+ 3. If the command fails (e.g. no network, no push permission), print a warning and continue — `hula launch` re-runs the same step as a safety net at launch time, so a plan-time failure is not fatal.
136
+
137
+ ### Step 3: Output the Plan Path and Next Steps
126
138
 
127
139
  **Output Format:**
128
140
 
129
141
  ```
130
142
  ✅ Plan created: `.hublaunch/plans/2025-12-29-14:30-feature-name.md`
143
+ 🌿 Branch created: `feature-name` (plan pushed to origin)
131
144
  <!-- hula-plan: .hublaunch/plans/2025-12-29-14:30-feature-name.md -->
145
+ <!-- hula-branch: feature-name -->
132
146
 
133
147
  📋 **Proceeding to validation now…**
134
148
  ```
135
149
 
150
+ (Substitute the actual resolved `<issueName>` in the branch line and the `hula-branch` comment. If branch creation failed in Step 2, replace the 🌿 line with `⚠️ Branch creation deferred to launch time` and omit the `hula-branch` comment.)
151
+
136
152
  Now proceed directly to plan validation **without waiting for the user**. The plan file was just created in this session — the path is already known.
137
153
 
138
154
  Read `hula instructions proceed` and execute the full validation workflow against the plan at `<path>` (substitute `<path>` with the actual plan file path you just created, e.g. `.hublaunch/plans/2025-12-29-14:30-feature-name.md`).
@@ -156,4 +172,4 @@ Read `hula instructions proceed` and execute the full validation workflow agains
156
172
  5. If `--test` and/or `--handoff <username>` were also present in `$ARGUMENTS`, pass them through to the launch — same as the Launch Offer's reply table does for a manual reply containing those flags.
157
173
  - **Without `--autoLaunch`**, behavior is completely unchanged: ask and wait as today.
158
174
 
159
- **Note:** The plan is saved locally. When you run `/hula-launch`, the plan is automatically synced to `origin/main` before the GitHub issue is created and the implementation begins — no separate upload step needed. Because validation ends with the Launch Offer, an affirmative reply runs the `/hula-launch` workflow for the user automatically; they can also decline and run `/hula-launch` themselves later. `/hula-confirm` remains available as a standalone command for re-validation at any time. If `--autoLaunch` was passed to `/hula-plan`, the launch runs automatically once validation completes — no reply needed.
175
+ **Note:** The plan is saved locally AND pushed to its feature branch on origin (Step 2). When you run `/hula-launch`, the plan branch is re-synced automatically (covering validation edits and renames) before the GitHub issue is created and the implementation begins — no separate upload step needed. Because validation ends with the Launch Offer, an affirmative reply runs the `/hula-launch` workflow for the user automatically; they can also decline and run `/hula-launch` themselves later. `/hula-confirm` remains available as a standalone command for re-validation at any time. If `--autoLaunch` was passed to `/hula-plan`, the launch runs automatically once validation completes — no reply needed.
@@ -0,0 +1,162 @@
1
+ ---
2
+ name: hula-research
3
+ description: Research a codebase and present a clear, digestible R&D report. Use when the user wants to understand how the code works, get an architecture overview, or investigate a specific area, feature, or subsystem.
4
+ disable-model-invocation: true
5
+ argument-hint: "[topic or area to focus on — omit for a whole-codebase overview]"
6
+ allowed-tools: Bash Read
7
+ ---
8
+
9
+ You are an expert software researcher for the HubLaunch workflow. Your job is to go through the code, do the R&D, and present the user a report that is **easy to absorb yet complete on the things that matter**.
10
+
11
+ ## Golden rules
12
+
13
+ 1. **Read-only.** This is research, not implementation. **Never edit, create, move, or delete any file**, and never run commands that change state (no `git commit`, `git checkout`, `npm install`, writes, etc.). Only read and search.
14
+ 2. **Digestible first, deep second.** Lead with a short summary the user can read in 30 seconds. Put detail below it, structured so the reader can stop early. Do not dump everything you found.
15
+ 3. **Ground every claim in the code.** Reference real files and line numbers (e.g. `src/services/git/GitService.ts:58`). If you are inferring rather than confirming, say so.
16
+ 4. **One simple diagram, when it helps.** Use a plain ASCII/box-and-arrow diagram — **never Mermaid** or any other rendered diagram syntax. Keep it small enough to read at a glance.
17
+
18
+ ## Input
19
+
20
+ Research request: $ARGUMENTS
21
+
22
+ ### Scope detection
23
+
24
+ - **If an argument is provided** (a topic, area, feature, file, or question — e.g. `/hula-research the launch pipeline` or `/hula-research how auth tokens flow`): scope the research to that topic. Go **deeper** on it; ignore unrelated parts of the codebase except where they connect.
25
+ - **If no argument is provided**: produce a **whole-codebase architecture overview** — breadth over depth. Cover what the project is, its major pieces, and how they fit together.
26
+
27
+ If the argument is genuinely ambiguous (could mean two very different things), ask **one** short clarifying question, then proceed.
28
+
29
+ ## Research workflow
30
+
31
+ Do this analysis **before** writing the report. Work efficiently — you do not need to read every file, but you must not guess at the important ones.
32
+
33
+ 1. **Orient.** Read the entry points and the map of the project: `package.json` (scripts, bin, deps), `README.md`, `tsconfig.json`, top-level `src/` layout, and any CLAUDE.md / docs. Establish what the project *is* and how it runs.
34
+ 2. **Map the structure.** Identify the major directories and what each is responsible for (commands, services, types, config, templates, utils, etc.). Note the naming conventions and patterns in use.
35
+ 3. **Trace the important paths.** For the chosen scope, follow the real flow: entry point → command → service(s) → external calls → output. Read the type definitions that describe the data shapes. Follow imports to understand how pieces connect.
36
+ 4. **Find the load-bearing pieces.** Identify the files, services, or abstractions that the rest of the code depends on most. These deserve the most attention in the report.
37
+ 5. **Note the rough edges.** Spot anything worth flagging: complexity hot spots, duplication, TODO/FIXME markers, tight coupling, missing tests, or surprising design choices. Be honest but fair.
38
+
39
+ Use whatever read-only search and file tools the harness provides (codebase/semantic search, file reads, `grep`, `git log`/`git blame` for history). Prefer reading source over assuming.
40
+
41
+ ## Report format
42
+
43
+ Present the report **in chat** (do not write it to a file). Use this layered structure so the reader can stop reading whenever they have enough:
44
+
45
+ ```markdown
46
+ # 🔬 Research: <topic, or "Codebase Overview">
47
+
48
+ ## TL;DR
49
+ <2–4 sentences. What this is, and the single most important thing to understand. A busy reader should be able to stop here.>
50
+
51
+ ## Key Findings
52
+ - <3–7 punchy bullets — the things that actually matter. Each ties to a concrete place in the code.>
53
+
54
+ ## How it fits together
55
+ <One ASCII diagram (see guidelines below) + 2–4 sentences walking through it.>
56
+ ```
57
+
58
+ Then, **below the summary**, include the deeper material. Put each deep section inside a collapsible block so the report stays scannable (fall back to plain `###` headings if the harness doesn't render `<details>`):
59
+
60
+ ```markdown
61
+ <details>
62
+ <summary><b>Components & responsibilities</b></summary>
63
+
64
+ - **<Component>** (`path`) — what it does, who calls it, what it depends on.
65
+ - ...
66
+ </details>
67
+
68
+ <details>
69
+ <summary><b>Data & control flow</b></summary>
70
+
71
+ <Step-by-step of the key path, with file:line references.>
72
+ </details>
73
+
74
+ <details>
75
+ <summary><b>Patterns & conventions</b></summary>
76
+
77
+ <Naming, structure, error handling, config, testing patterns worth knowing before touching the code.>
78
+ </details>
79
+
80
+ <details>
81
+ <summary><b>Key files to know</b></summary>
82
+
83
+ | File | Why it matters |
84
+ | --- | --- |
85
+ | `src/...` | ... |
86
+ </details>
87
+
88
+ <details>
89
+ <summary><b>Risks, gaps & open questions</b></summary>
90
+
91
+ - ⚠️ <complexity / coupling / missing tests / tech debt>
92
+ - ❓ <anything you could not determine from the code>
93
+ </details>
94
+ ```
95
+
96
+ End with a short pointer block (not collapsed):
97
+
98
+ ```markdown
99
+ ## Where to dig next
100
+ - To change X, start at `src/...`
101
+ - Related area worth a follow-up `/hula-research <topic>`: ...
102
+ ```
103
+
104
+ Scale the report to the scope: a **topic-focused** request should go deep on that topic; a **whole-codebase overview** should stay broad and keep each section short. Never let the deep sections bury the TL;DR and Key Findings.
105
+
106
+ ## ASCII diagram guidelines
107
+
108
+ Include **one** diagram when it clarifies structure or flow (most reports benefit from one; skip it only if it would add nothing). Rules:
109
+
110
+ - **ASCII only — no Mermaid, no PlantUML, no image syntax.** It must render as plain text in any chat.
111
+ - Keep it small: a handful of boxes and arrows, not a wall of ASCII art.
112
+ - Use boxes for components and arrows (`──▶`, `│`, `▼`) for flow or dependency direction.
113
+ - Label arrows when the relationship isn't obvious.
114
+
115
+ Example (a flow diagram):
116
+
117
+ ```text
118
+ User
119
+ │ /hula-launch <branch>
120
+ ▼
121
+ ┌─────────────┐ reads ┌──────────────────┐
122
+ │ launch.ts │ ───────────▶ │ hublaunch.config│
123
+ └──────┬──────┘ └──────────────────┘
124
+ │ POST job
125
+ ▼
126
+ ┌──────────────────┐ runs ┌───────────────────┐
127
+ │ HulaApiClient │ ──────▶ │ hula-project server│
128
+ └──────────────────┘ │ (Claude Code in │
129
+ │ cloud container) │
130
+ └─────────┬─────────┘
131
+ │ opens
132
+ ▼
133
+ GitHub PR
134
+ ```
135
+
136
+ Example (a layered/module diagram):
137
+
138
+ ```text
139
+ ┌──────────────────────────────────────────────┐
140
+ │ commands/ (CLI surface: create, launch …) │
141
+ └───────────────┬──────────────────────────────┘
142
+ │ calls
143
+ ▼
144
+ ┌──────────────────────────────────────────────┐
145
+ │ services/ (github, git, api, logs, …) │
146
+ └───────────────┬──────────────────────────────┘
147
+ │ uses
148
+ ▼
149
+ ┌──────────────────────────────────────────────┐
150
+ │ utils/ • types/ • config/ (shared core) │
151
+ └──────────────────────────────────────────────┘
152
+ ```
153
+
154
+ ## Quality bar
155
+
156
+ - ✅ Scope correctly detected (topic-focused vs. whole-codebase overview)
157
+ - ✅ TL;DR + Key Findings let a reader grasp the gist in under a minute
158
+ - ✅ All important aspects covered, deeper detail available but not overwhelming
159
+ - ✅ One clear ASCII diagram (never Mermaid) when it helps
160
+ - ✅ Claims grounded in real `file:line` references; inferences labeled as such
161
+ - ✅ Honest about risks, gaps, and what couldn't be determined
162
+ - ✅ **Nothing was modified** — read-only throughout
@@ -29,7 +29,7 @@ Your job is to:
29
29
  ```
30
30
  ℹ️ Upload is no longer a separate step.
31
31
 
32
- `hula launch` automatically uploads the plan to `origin/main` before starting the job.
32
+ `hula launch` automatically publishes the plan to its feature branch before starting the job (creating the branch from the base branch if `/hula-plan` didn't already).
33
33
 
34
34
  **Next Step:** Run `/hula-launch <branch-name>` to upload and launch in one step.
35
35
 
@@ -84,7 +84,7 @@ Display this message to the user:
84
84
  ```
85
85
  ℹ️ Upload is no longer a separate step.
86
86
 
87
- `hula launch` automatically uploads the plan to `origin/main` before starting the job.
87
+ `hula launch` automatically publishes the plan to its feature branch before starting the job (creating the branch from the base branch if `/hula-plan` didn't already).
88
88
 
89
89
  **Next Step:** Run `/hula-launch <branch-name>` to upload and launch in one step.
90
90
 
@@ -25,6 +25,14 @@ export declare function parseIssueNumber(value: string | number): number | null;
25
25
  * Validate email address
26
26
  */
27
27
  export declare function isValidEmail(email: string): boolean;
28
+ /**
29
+ * Sanitize an issue/tracking name into the git branch name used for its run.
30
+ * MUST stay byte-identical to `sanitizePlanName` in hula-server's
31
+ * `packages/shared/src/utils.ts` — the server derives the sandbox branch from
32
+ * the same issueName, so both sides have to resolve the SAME branch name for
33
+ * the plan-branch flow to hand off correctly.
34
+ */
35
+ export declare function sanitizePlanName(name: string): string;
28
36
  /**
29
37
  * Sanitize filename
30
38
  */
@@ -1 +1 @@
1
- {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAElE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAG/D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO/C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAUtE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAGnD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMzD"}
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAElE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAG/D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO/C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAUtE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAGnD;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMzD"}
@@ -51,6 +51,16 @@ export function isValidEmail(email) {
51
51
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
52
52
  return emailRegex.test(email);
53
53
  }
54
+ /**
55
+ * Sanitize an issue/tracking name into the git branch name used for its run.
56
+ * MUST stay byte-identical to `sanitizePlanName` in hula-server's
57
+ * `packages/shared/src/utils.ts` — the server derives the sandbox branch from
58
+ * the same issueName, so both sides have to resolve the SAME branch name for
59
+ * the plan-branch flow to hand off correctly.
60
+ */
61
+ export function sanitizePlanName(name) {
62
+ return name.replace(/[^a-zA-Z0-9_-]/g, "_");
63
+ }
54
64
  /**
55
65
  * Sanitize filename
56
66
  */
@@ -1 +1 @@
1
- {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;AAC3E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IACpD,8DAA8D;IAC9D,OAAO,+CAA+C,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACxE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAsB;IACrD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAClD,CAAC;IAED,6BAA6B;IAC7B,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAElC,OAAO,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,UAAU,GAAG,4BAA4B,CAAC;IAChD,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,OAAO,QAAQ;SACZ,OAAO,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC,wBAAwB;SAC/D,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,8BAA8B;SACnD,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,4BAA4B;SAChD,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,kCAAkC;AAC9D,CAAC"}
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;AAC3E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IACpD,8DAA8D;IAC9D,OAAO,+CAA+C,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACxE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAsB;IACrD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAClD,CAAC;IAED,6BAA6B;IAC7B,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAElC,OAAO,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,UAAU,GAAG,4BAA4B,CAAC;IAChD,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;AAC9C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,OAAO,QAAQ;SACZ,OAAO,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC,wBAAwB;SAC/D,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,8BAA8B;SACnD,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,4BAA4B;SAChD,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,kCAAkC;AAC9D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hub-launch",
3
- "version": "1.27.0",
3
+ "version": "1.29.0",
4
4
  "description": "GitHub Issue and PR automation CLI tool with plugin/hook system for project-specific customizations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -44,6 +44,7 @@ const SKILL_NAMES = [
44
44
  'hula-upload',
45
45
  'hula-info',
46
46
  'hula-help',
47
+ 'hula-research',
47
48
  ];
48
49
 
49
50
  function main() {