@specship/specship-win32-arm64 0.21.2 → 0.22.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 (96) hide show
  1. package/lib/dist/bin/specship.js +302 -4
  2. package/lib/dist/bin/specship.js.map +1 -1
  3. package/lib/dist/commands/specship/jira.md +74 -0
  4. package/lib/dist/commands/specship/spec.md +61 -1
  5. package/lib/dist/extraction/index.d.ts +6 -0
  6. package/lib/dist/extraction/index.d.ts.map +1 -1
  7. package/lib/dist/extraction/index.js.map +1 -1
  8. package/lib/dist/extraction/specs/markdown-spec-extractor.d.ts.map +1 -1
  9. package/lib/dist/extraction/specs/markdown-spec-extractor.js +8 -1
  10. package/lib/dist/extraction/specs/markdown-spec-extractor.js.map +1 -1
  11. package/lib/dist/index.d.ts +7 -0
  12. package/lib/dist/index.d.ts.map +1 -1
  13. package/lib/dist/index.js +45 -18
  14. package/lib/dist/index.js.map +1 -1
  15. package/lib/dist/jira/auto-publish.d.ts +67 -0
  16. package/lib/dist/jira/auto-publish.d.ts.map +1 -0
  17. package/lib/dist/jira/auto-publish.js +232 -0
  18. package/lib/dist/jira/auto-publish.js.map +1 -0
  19. package/lib/dist/jira/board-first.d.ts +64 -0
  20. package/lib/dist/jira/board-first.d.ts.map +1 -0
  21. package/lib/dist/jira/board-first.js +91 -0
  22. package/lib/dist/jira/board-first.js.map +1 -0
  23. package/lib/dist/jira/client.d.ts +80 -1
  24. package/lib/dist/jira/client.d.ts.map +1 -1
  25. package/lib/dist/jira/client.js +213 -1
  26. package/lib/dist/jira/client.js.map +1 -1
  27. package/lib/dist/jira/config.d.ts +1 -1
  28. package/lib/dist/jira/config.d.ts.map +1 -1
  29. package/lib/dist/jira/config.js +14 -3
  30. package/lib/dist/jira/config.js.map +1 -1
  31. package/lib/dist/jira/coverage.d.ts +105 -0
  32. package/lib/dist/jira/coverage.d.ts.map +1 -0
  33. package/lib/dist/jira/coverage.js +160 -0
  34. package/lib/dist/jira/coverage.js.map +1 -0
  35. package/lib/dist/jira/index.d.ts +1 -0
  36. package/lib/dist/jira/index.d.ts.map +1 -1
  37. package/lib/dist/jira/index.js +1 -0
  38. package/lib/dist/jira/index.js.map +1 -1
  39. package/lib/dist/jira/milestone-comment.d.ts +95 -0
  40. package/lib/dist/jira/milestone-comment.d.ts.map +1 -0
  41. package/lib/dist/jira/milestone-comment.js +271 -0
  42. package/lib/dist/jira/milestone-comment.js.map +1 -0
  43. package/lib/dist/jira/publish.d.ts +69 -2
  44. package/lib/dist/jira/publish.d.ts.map +1 -1
  45. package/lib/dist/jira/publish.js +0 -0
  46. package/lib/dist/jira/publish.js.map +1 -1
  47. package/lib/dist/jira/published-specs.d.ts +23 -0
  48. package/lib/dist/jira/published-specs.d.ts.map +1 -0
  49. package/lib/dist/jira/published-specs.js +106 -0
  50. package/lib/dist/jira/published-specs.js.map +1 -0
  51. package/lib/dist/jira/reconcile.d.ts +81 -0
  52. package/lib/dist/jira/reconcile.d.ts.map +1 -0
  53. package/lib/dist/jira/reconcile.js +111 -0
  54. package/lib/dist/jira/reconcile.js.map +1 -0
  55. package/lib/dist/jira/regression-pack.d.ts +547 -0
  56. package/lib/dist/jira/regression-pack.d.ts.map +1 -0
  57. package/lib/dist/jira/regression-pack.js +986 -0
  58. package/lib/dist/jira/regression-pack.js.map +1 -0
  59. package/lib/dist/jira/repo-config.d.ts +59 -0
  60. package/lib/dist/jira/repo-config.d.ts.map +1 -0
  61. package/lib/dist/jira/repo-config.js +222 -0
  62. package/lib/dist/jira/repo-config.js.map +1 -0
  63. package/lib/dist/jira/spec-amend.d.ts +46 -0
  64. package/lib/dist/jira/spec-amend.d.ts.map +1 -0
  65. package/lib/dist/jira/spec-amend.js +232 -0
  66. package/lib/dist/jira/spec-amend.js.map +1 -0
  67. package/lib/dist/jira/spec-writer.d.ts +22 -0
  68. package/lib/dist/jira/spec-writer.d.ts.map +1 -1
  69. package/lib/dist/jira/spec-writer.js +113 -0
  70. package/lib/dist/jira/spec-writer.js.map +1 -1
  71. package/lib/dist/jira/types.d.ts +62 -0
  72. package/lib/dist/jira/types.d.ts.map +1 -1
  73. package/lib/dist/jira/types.js +15 -1
  74. package/lib/dist/jira/types.js.map +1 -1
  75. package/lib/dist/mcp/jira-tools.d.ts +102 -0
  76. package/lib/dist/mcp/jira-tools.d.ts.map +1 -1
  77. package/lib/dist/mcp/jira-tools.js +807 -50
  78. package/lib/dist/mcp/jira-tools.js.map +1 -1
  79. package/lib/dist/mcp/server-instructions.d.ts +1 -1
  80. package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
  81. package/lib/dist/mcp/server-instructions.js +4 -0
  82. package/lib/dist/mcp/server-instructions.js.map +1 -1
  83. package/lib/dist/mcp/spec-tools.d.ts.map +1 -1
  84. package/lib/dist/mcp/spec-tools.js +7 -1
  85. package/lib/dist/mcp/spec-tools.js.map +1 -1
  86. package/lib/dist/mcp/tools.d.ts +3 -0
  87. package/lib/dist/mcp/tools.d.ts.map +1 -1
  88. package/lib/dist/mcp/tools.js +50 -0
  89. package/lib/dist/mcp/tools.js.map +1 -1
  90. package/lib/dist/resolution/spec-link-resolver.d.ts +2 -0
  91. package/lib/dist/resolution/spec-link-resolver.d.ts.map +1 -1
  92. package/lib/dist/resolution/spec-link-resolver.js +11 -3
  93. package/lib/dist/resolution/spec-link-resolver.js.map +1 -1
  94. package/lib/node_modules/.package-lock.json +1 -1
  95. package/lib/package.json +1 -1
  96. package/package.json +1 -1
@@ -872,10 +872,32 @@ function main() {
872
872
  }
873
873
  const { default: SpecShip } = await loadSpecShip();
874
874
  const cg = await SpecShip.open(projectPath);
875
+ // JIRA auto-publish (REQ-JIRATEAM-002): print the summary the sync's
876
+ // auto-publish pass produced. Silent when the repo has no binding
877
+ // (sync omits the field entirely). Never fails or blocks output.
878
+ const pushJiraAutoPublish = async (result) => {
879
+ if (!result.jiraAutoPublish)
880
+ return;
881
+ try {
882
+ const { summarizeAutoPublishReport } = await Promise.resolve().then(() => __importStar(require('../jira/auto-publish')));
883
+ const line = summarizeAutoPublishReport(result.jiraAutoPublish);
884
+ if (line)
885
+ console.log(line);
886
+ for (const r of result.jiraAutoPublish.results) {
887
+ if (r.status === 'failed') {
888
+ console.log(`JIRA: ${r.specId} failed — ${r.note ?? 'unknown error'}`);
889
+ }
890
+ }
891
+ }
892
+ catch {
893
+ /* summary is best-effort */
894
+ }
895
+ };
875
896
  if (options.quiet) {
876
897
  const result = await cg.sync();
877
898
  pushDriftNotices(result);
878
899
  await pushJiraDriftComments(cg, result);
900
+ await pushJiraAutoPublish(result);
879
901
  pushDriftSummary(cg);
880
902
  cg.destroy();
881
903
  return;
@@ -905,6 +927,7 @@ function main() {
905
927
  }
906
928
  pushDriftNotices(result);
907
929
  await pushJiraDriftComments(cg, result);
930
+ await pushJiraAutoPublish(result);
908
931
  pushDriftSummary(cg);
909
932
  clack.outro('Done');
910
933
  cg.destroy();
@@ -3296,6 +3319,23 @@ function main() {
3296
3319
  process.exit(1);
3297
3320
  }
3298
3321
  executor.approve(arg, options.comment);
3322
+ // Milestone: plan_approved (REQ-JIRATEAM-003.A1). Only fires for a
3323
+ // JIRA-tracked run (metadata.jira present) — a non-JIRA run is a
3324
+ // silent no-op. Soft-fails internally, so a JIRA hiccup never
3325
+ // reverses the approval.
3326
+ try {
3327
+ const run = cg.getSpecQueries().getWorkflowRunById(arg);
3328
+ const jira = run?.metadata?.jira;
3329
+ if (jira?.issueKey) {
3330
+ const { resolveJiraCredentials, JiraClient } = await Promise.resolve().then(() => __importStar(require('../jira')));
3331
+ const { postMilestoneComment } = await Promise.resolve().then(() => __importStar(require('../jira/milestone-comment')));
3332
+ const creds = resolveJiraCredentials();
3333
+ await postMilestoneComment(new JiraClient(creds), jira.issueKey, 'plan_approved', { specId: jira.specId ?? jira.issueKey }, { projectRoot });
3334
+ }
3335
+ }
3336
+ catch {
3337
+ /* soft-fail — the approval already committed. */
3338
+ }
3299
3339
  // eslint-disable-next-line no-console
3300
3340
  console.log(`Run ${arg} approved. Call \`specship workflow resume ${arg}\` to continue.`);
3301
3341
  break;
@@ -3590,6 +3630,52 @@ function main() {
3590
3630
  process.exit(1);
3591
3631
  }
3592
3632
  });
3633
+ /**
3634
+ * specship jira bind — persist the repo's JIRA binding into
3635
+ * specship.config.json (REQ-JIRATEAM-008.A2). The committed binding is what
3636
+ * board-first flows read — the same file `updateRepoJiraBinding` writes.
3637
+ * Credentials never live here; `assertNoCredentialsInRepoConfig` enforces it.
3638
+ */
3639
+ jira
3640
+ .command('bind')
3641
+ .description('Write the repo JIRA binding into specship.config.json (project, epic).')
3642
+ .option('--project <key>', 'JIRA project key to bind (e.g., "PROJ")')
3643
+ .option('--epic <key>', 'Default epic key to anchor new work (e.g., "PROJ-42")')
3644
+ .option('--path <projectRoot>', 'Project root (default: cwd)')
3645
+ .action(async (options) => {
3646
+ const projectRoot = path.resolve(options.path ?? process.cwd());
3647
+ if (!options.project && !options.epic) {
3648
+ error('Nothing to bind. Pass --project <KEY> and/or --epic <KEY>.');
3649
+ process.exit(1);
3650
+ }
3651
+ try {
3652
+ const { updateRepoJiraBinding, loadRepoJiraBinding } = await Promise.resolve().then(() => __importStar(require('../jira/repo-config')));
3653
+ const patch = {};
3654
+ if (options.project)
3655
+ patch.projectKey = options.project.trim().toUpperCase();
3656
+ if (options.epic)
3657
+ patch.epicKey = options.epic.trim().toUpperCase();
3658
+ // --epic alone requires an existing bound project (updateRepoJiraBinding
3659
+ // insists on projectKey being present in the merged result).
3660
+ if (!patch.projectKey) {
3661
+ const { binding } = loadRepoJiraBinding(projectRoot);
3662
+ if (!binding) {
3663
+ error('No existing JIRA project binding. Pass --project <KEY> on the first bind.');
3664
+ process.exit(1);
3665
+ }
3666
+ }
3667
+ const { path: file, binding } = updateRepoJiraBinding(projectRoot, patch);
3668
+ success(`Wrote JIRA binding to ${file}.`);
3669
+ info(` projectKey: ${binding.projectKey}`);
3670
+ if (binding.epicKey)
3671
+ info(` epicKey: ${binding.epicKey}`);
3672
+ }
3673
+ catch (err) {
3674
+ const msg = err instanceof Error ? err.message : String(err);
3675
+ error(`Failed to write binding: ${msg}`);
3676
+ process.exit(1);
3677
+ }
3678
+ });
3593
3679
  /**
3594
3680
  * specship jira transition — move a tracked issue to a target state, or list
3595
3681
  * the transitions it currently offers (REQ-JIRATRANS-001). Reuses the client's
@@ -3656,6 +3742,103 @@ function main() {
3656
3742
  cg.close();
3657
3743
  }
3658
3744
  });
3745
+ /**
3746
+ * specship jira coverage — sprint coverage report (REQ-JIRATEAM-004). Joins
3747
+ * the bound project's active (or named) sprint to spec truth. Read-only by
3748
+ * default; `--post <issueKey>` upserts a single watermarked JIRA comment.
3749
+ */
3750
+ jira
3751
+ .command('coverage')
3752
+ .description('Sprint coverage report joining JIRA sprint issues to spec truth (read-only unless --post).')
3753
+ .option('--project <key>', 'JIRA project key (default: configured publish project)')
3754
+ .option('--sprint <name>', 'named sprint (default: the project\'s open sprint)')
3755
+ .option('--post <issueKey>', 'upsert the report as a watermarked comment on this issue (edit-in-place)')
3756
+ .option('--path <projectRoot>', 'project root (default: cwd)')
3757
+ .action(async (options) => {
3758
+ const projectRoot = path.resolve(options.path ?? process.cwd());
3759
+ if (!(0, directory_1.isInitialized)(projectRoot)) {
3760
+ error(`SpecShip not initialized in ${projectRoot}. Run \`specship init -i\` first.`);
3761
+ process.exit(1);
3762
+ }
3763
+ const { SpecShip } = await loadSpecShip();
3764
+ const { handleSpecshipJiraCoverage } = await Promise.resolve().then(() => __importStar(require('../mcp/jira-tools')));
3765
+ const cg = await SpecShip.open(projectRoot);
3766
+ try {
3767
+ const args = {};
3768
+ if (options.project)
3769
+ args.project = options.project;
3770
+ if (options.sprint)
3771
+ args.sprint = options.sprint;
3772
+ if (options.post) {
3773
+ args.post = true;
3774
+ args.issue_key = options.post;
3775
+ }
3776
+ const result = await handleSpecshipJiraCoverage(args, {
3777
+ specQueries: cg.getSpecQueries(),
3778
+ projectRoot,
3779
+ });
3780
+ const out = result.content.map((c) => c.text).join('\n');
3781
+ // eslint-disable-next-line no-console
3782
+ console.log(out);
3783
+ if (result.isError)
3784
+ process.exit(1);
3785
+ }
3786
+ finally {
3787
+ cg.close();
3788
+ }
3789
+ });
3790
+ /**
3791
+ * specship jira reconcile — detect JIRA-side edits and (with --apply) fold
3792
+ * them back into the spec (REQ-JIRATEAM-005). Preview is read-only and the
3793
+ * default; --apply must be paired with --issue plus the confirmed accept
3794
+ * flags AND the fingerprint from the preview so an unreviewed apply is
3795
+ * rejected by the handler's fingerprint gate.
3796
+ */
3797
+ jira
3798
+ .command('reconcile')
3799
+ .description('Detect JIRA-side edits to published specs; --apply folds a confirmed diff back into the spec.')
3800
+ .option('--issue <key>', 'narrow to one issue (required for --apply)')
3801
+ .option('--apply', 'apply the confirmed diff — preview first and confirm the diff before using this')
3802
+ .option('--accept-content', 'apply: accept the edited summary/description')
3803
+ .option('--accept-subtask <key...>', 'apply: accept the proposed criterion for this JIRA Sub-task key (repeatable)')
3804
+ .option('--expected-fingerprint <fp>', 'apply: the live fingerprint from the preview the user just approved')
3805
+ .option('--path <projectRoot>', 'project root (default: cwd)')
3806
+ .action(async (options) => {
3807
+ const projectRoot = path.resolve(options.path ?? process.cwd());
3808
+ if (!(0, directory_1.isInitialized)(projectRoot)) {
3809
+ error(`SpecShip not initialized in ${projectRoot}. Run \`specship init -i\` first.`);
3810
+ process.exit(1);
3811
+ }
3812
+ const { SpecShip } = await loadSpecShip();
3813
+ const { handleSpecshipJiraReconcile } = await Promise.resolve().then(() => __importStar(require('../mcp/jira-tools')));
3814
+ const cg = await SpecShip.open(projectRoot);
3815
+ try {
3816
+ const args = {};
3817
+ args.mode = options.apply ? 'apply' : 'preview';
3818
+ if (options.issue)
3819
+ args.issue_key = options.issue;
3820
+ if (options.acceptContent)
3821
+ args.accept_content = true;
3822
+ if (options.acceptSubtask && options.acceptSubtask.length > 0) {
3823
+ args.accept_subtasks = options.acceptSubtask;
3824
+ }
3825
+ if (options.expectedFingerprint) {
3826
+ args.expected_live_fingerprint = options.expectedFingerprint;
3827
+ }
3828
+ const result = await handleSpecshipJiraReconcile(args, {
3829
+ specQueries: cg.getSpecQueries(),
3830
+ projectRoot,
3831
+ });
3832
+ const out = result.content.map((c) => c.text).join('\n');
3833
+ // eslint-disable-next-line no-console
3834
+ console.log(out);
3835
+ if (result.isError)
3836
+ process.exit(1);
3837
+ }
3838
+ finally {
3839
+ cg.close();
3840
+ }
3841
+ });
3659
3842
  /**
3660
3843
  * specship jira release — stamp a released version onto issues
3661
3844
  * (REQ-JIRAPUB-007): ensure the project version exists, add it as fixVersion
@@ -3683,6 +3866,9 @@ function main() {
3683
3866
  .split(',')
3684
3867
  .map((k) => k.trim())
3685
3868
  .filter(Boolean);
3869
+ // Map issue key → spec id for the release_stamped milestone (so the
3870
+ // marker keys on both the spec and the version — REQ-JIRATEAM-003).
3871
+ const issueKeyToSpecId = new Map();
3686
3872
  if (keys.length === 0) {
3687
3873
  // Default: every spec under <root>/specs with a jira_issue key.
3688
3874
  const projectRoot = path.resolve(options.path ?? process.cwd());
@@ -3691,9 +3877,14 @@ function main() {
3691
3877
  for (const name of fs.readdirSync(specsDir)) {
3692
3878
  if (!name.toLowerCase().endsWith('.md'))
3693
3879
  continue;
3694
- const key = readSpecJiraKey(path.join(specsDir, name));
3695
- if (key)
3696
- keys.push(key);
3880
+ const abs = path.join(specsDir, name);
3881
+ const key = readSpecJiraKey(abs);
3882
+ if (!key)
3883
+ continue;
3884
+ keys.push(key);
3885
+ const idLine = /^id:\s*([^\r\n]+)$/m.exec(fs.readFileSync(abs, 'utf8'))?.[1]?.trim();
3886
+ if (idLine)
3887
+ issueKeyToSpecId.set(key, idLine);
3697
3888
  }
3698
3889
  }
3699
3890
  catch {
@@ -3706,7 +3897,9 @@ function main() {
3706
3897
  process.exit(1);
3707
3898
  }
3708
3899
  const client = new JiraClient(creds);
3709
- const result = await releaseIssues(client, projectKey, version, keys);
3900
+ const result = await releaseIssues(client, projectKey, version, keys, {
3901
+ specIdForIssue: (k) => issueKeyToSpecId.get(k),
3902
+ });
3710
3903
  const stamped = result.issues.filter((i) => i.fixVersionAdded).length;
3711
3904
  const commented = result.issues.filter((i) => i.commented).length;
3712
3905
  success(`Version ${version}${result.versionCreated ? ' created' : ' already existed'} in ${projectKey}; ` +
@@ -3717,6 +3910,111 @@ function main() {
3717
3910
  process.exit(1);
3718
3911
  }
3719
3912
  });
3913
+ /**
3914
+ * specship jira regression-pack — generate or refresh the SpecShip Regression
3915
+ * Pack in the bound JIRA project (REQ-JIRAREG-001). Idempotent; --dry-run
3916
+ * prints the plan without any JIRA write.
3917
+ */
3918
+ jira
3919
+ .command('regression-pack')
3920
+ .description('Generate / refresh the SpecShip Regression Pack in the bound JIRA project.')
3921
+ .option('--project <key>', 'JIRA project key (default: configured publish project)')
3922
+ .option('--dry-run', 'plan the pack and print counts without any JIRA write')
3923
+ .option('--path <projectRoot>', 'project root (default: cwd)')
3924
+ .action(async (options) => {
3925
+ const projectRoot = path.resolve(options.path ?? process.cwd());
3926
+ if (!(0, directory_1.isInitialized)(projectRoot)) {
3927
+ error(`SpecShip not initialized in ${projectRoot}. Run \`specship init -i\` first.`);
3928
+ process.exit(1);
3929
+ }
3930
+ const { SpecShip } = await loadSpecShip();
3931
+ const { handleSpecshipJiraRegressionPack } = await Promise.resolve().then(() => __importStar(require('../mcp/jira-tools')));
3932
+ const cg = await SpecShip.open(projectRoot);
3933
+ try {
3934
+ const args = {};
3935
+ if (options.project)
3936
+ args.project = options.project;
3937
+ if (options.dryRun)
3938
+ args.dry_run = true;
3939
+ const result = await handleSpecshipJiraRegressionPack(args, {
3940
+ specQueries: cg.getSpecQueries(),
3941
+ projectRoot,
3942
+ getLinkedNodesForReq: (reqId) => cg.getLinkedNodesForReq(reqId),
3943
+ getNeighbourNodes: (nodeIds) => cg.getNeighbourNodes(nodeIds),
3944
+ });
3945
+ const out = result.content.map((c) => c.text).join('\n');
3946
+ // eslint-disable-next-line no-console
3947
+ console.log(out);
3948
+ if (result.isError)
3949
+ process.exit(1);
3950
+ }
3951
+ finally {
3952
+ cg.close();
3953
+ }
3954
+ });
3955
+ /**
3956
+ * specship jira regression-record — record a single pack case result
3957
+ * (REQ-JIRAREG-005). Comment + transition + validates-link feedback on the
3958
+ * source criterion. `--run <id>` keys idempotency per (case, run).
3959
+ */
3960
+ jira
3961
+ .command('regression-record')
3962
+ .description('Record a regression pack case result (REQ-JIRAREG-005).')
3963
+ .requiredOption('--case <key>', 'JIRA case issue key (e.g., "PROJ-42")')
3964
+ .requiredOption('--criterion <id>', 'source criterion id (e.g., "REQ-FOO-001.A2")')
3965
+ .requiredOption('--result <status>', 'pass | fail | unexecuted', 'pass')
3966
+ .option('--executor <who>', 'human | agent', 'human')
3967
+ .option('--harness <id>', 'behaviour harness id (e.g., "behaviour-e2e")')
3968
+ .option('--run <id>', 'stable run id — one comment per (case, run)')
3969
+ .option('--log-ref <ref>', 'evidence log pointer')
3970
+ .option('--error <text>', 'error text (fail path)')
3971
+ .option('--path <projectRoot>', 'project root (default: cwd)')
3972
+ .action(async (options) => {
3973
+ const projectRoot = path.resolve(options.path ?? process.cwd());
3974
+ if (!(0, directory_1.isInitialized)(projectRoot)) {
3975
+ error(`SpecShip not initialized in ${projectRoot}. Run \`specship init -i\` first.`);
3976
+ process.exit(1);
3977
+ }
3978
+ const { SpecShip } = await loadSpecShip();
3979
+ const { handleSpecshipJiraRegressionRecord } = await Promise.resolve().then(() => __importStar(require('../mcp/jira-tools')));
3980
+ const cg = await SpecShip.open(projectRoot);
3981
+ try {
3982
+ // Accept the friendlier `pass`/`fail` short forms alongside the
3983
+ // canonical `passed`/`failed` names.
3984
+ const canonicalStatus = options.result === 'pass'
3985
+ ? 'passed'
3986
+ : options.result === 'fail'
3987
+ ? 'failed'
3988
+ : options.result;
3989
+ const args = {
3990
+ case: options.case,
3991
+ criterion: options.criterion,
3992
+ result: canonicalStatus,
3993
+ };
3994
+ if (options.executor)
3995
+ args.executor = options.executor;
3996
+ if (options.harness)
3997
+ args.harness = options.harness;
3998
+ if (options.run)
3999
+ args.run = options.run;
4000
+ if (options.logRef)
4001
+ args.log_ref = options.logRef;
4002
+ if (options.error)
4003
+ args.error = options.error;
4004
+ const result = await handleSpecshipJiraRegressionRecord(args, {
4005
+ specQueries: cg.getSpecQueries(),
4006
+ projectRoot,
4007
+ });
4008
+ const out = result.content.map((c) => c.text).join('\n');
4009
+ // eslint-disable-next-line no-console
4010
+ console.log(out);
4011
+ if (result.isError)
4012
+ process.exit(1);
4013
+ }
4014
+ finally {
4015
+ cg.close();
4016
+ }
4017
+ });
3720
4018
  // Parse and run
3721
4019
  program.parse();
3722
4020
  } // end main()