@codedrifters/configulator 0.0.212 → 0.0.214

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/lib/index.mjs CHANGED
@@ -717,9 +717,10 @@ var baseBundle = {
717
717
  "|-------|----------|",
718
718
  "| `status:ready` | The issue is fully specified, has no open blockers, and is available for a worker to pick up. |",
719
719
  "| `status:blocked` | The issue cannot be started yet \u2014 either it declares `Depends on: #N` on an open issue, or it is an epic with one or more open children. |",
720
- "| `status:in-progress` | A worker has claimed the issue and a branch exists. Set when the worker starts; cleared only on completion or failure. |",
720
+ "| `status:in-progress` | A worker has claimed the issue and a branch exists. Set when the worker starts; cleared only when the worker opens a PR or the issue fails. |",
721
+ "| `status:ready-for-review` | A PR has been opened for this issue and is awaiting review and merge. Replaces `status:in-progress` at the moment the PR opens. |",
721
722
  "| `status:needs-attention` | Automated triage has flagged the issue for human review (stale, failed worker, or ambiguous state). Humans reset this label manually. |",
722
- "| `status:done` | The change has shipped. Usually set when the PR merges and the issue closes. |",
723
+ "| `status:done` | The change has shipped. Set when the PR merges and the issue closes. |",
723
724
  "",
724
725
  "### Blocking Rules",
725
726
  "",
@@ -741,9 +742,9 @@ var baseBundle = {
741
742
  " either blocking rule applies.",
742
743
  "- **Worker claims the issue** \u2192 remove `status:ready`, add",
743
744
  " `status:in-progress`. A branch must exist before this transition.",
744
- "- **Worker opens a PR** \u2192 leave `status:in-progress` in place until the",
745
- " PR merges. Do not pre-flip to `status:done`.",
746
- "- **PR merges / issue closes** \u2192 remove `status:in-progress`, add",
745
+ "- **Worker opens a PR** \u2192 remove `status:in-progress`, add",
746
+ " `status:ready-for-review`. The PR URL should be posted on the issue.",
747
+ "- **PR merges / issue closes** \u2192 remove `status:ready-for-review`, add",
747
748
  " `status:done`.",
748
749
  "- **Dependency resolves** \u2192 if the issue was `status:blocked` solely because",
749
750
  " of the dependency-blocking rule, remove `status:blocked` and add",
@@ -760,8 +761,9 @@ var baseBundle = {
760
761
  " by CI. Those are expected self-healing behaviors, not failures.",
761
762
  "",
762
763
  "An issue must always carry exactly one of `status:ready`, `status:blocked`,",
763
- "`status:in-progress`, or `status:done`. The `status:needs-attention` label",
764
- "is additive \u2014 it coexists with whichever of those four applies."
764
+ "`status:in-progress`, `status:ready-for-review`, or `status:done`. The",
765
+ "`status:needs-attention` label is additive \u2014 it coexists with whichever of",
766
+ "those five applies."
765
767
  ].join("\n"),
766
768
  tags: ["workflow"]
767
769
  },
@@ -4283,11 +4285,14 @@ var issueWorkerSubAgent = {
4283
4285
  "",
4284
4286
  "## Phase 8: Update Status",
4285
4287
  "",
4286
- "After the PR is created:",
4288
+ "After the PR is created, transition the issue to the review phase:",
4287
4289
  "```bash",
4288
- 'gh issue edit <number> --remove-label "status:in-progress" --add-label "status:done"',
4290
+ 'gh issue edit <number> --remove-label "status:in-progress" --add-label "status:ready-for-review"',
4289
4291
  "```",
4290
4292
  "",
4293
+ "Do **not** set `status:done` here \u2014 the `pr-reviewer` sub-agent is",
4294
+ "responsible for that transition once the PR successfully merges.",
4295
+ "",
4291
4296
  "## Phase 9: Branch Cleanup",
4292
4297
  "",
4293
4298
  "The PR will not auto-merge until the `pr-reviewer` enables it. Poll the PR",
@@ -5176,6 +5181,14 @@ var prReviewerSubAgent = {
5176
5181
  " git fetch --prune origin",
5177
5182
  " git branch -d <branch-name> 2>/dev/null || git branch -D <branch-name> 2>/dev/null || true",
5178
5183
  " ```",
5184
+ " Transition the linked issue to `status:done` (replaces whichever of",
5185
+ " `status:ready-for-review` or `status:in-progress` it was carrying):",
5186
+ " ```bash",
5187
+ " gh issue edit <issue-number> \\",
5188
+ ' --remove-label "status:ready-for-review" \\',
5189
+ ' --remove-label "status:in-progress" \\',
5190
+ ' --add-label "status:done"',
5191
+ " ```",
5179
5192
  " Then check the linked issue state:",
5180
5193
  " ```bash",
5181
5194
  " gh issue view <issue-number> --json state --jq '.state'",
@@ -6639,11 +6652,106 @@ var researchPipelineBundle = {
6639
6652
  ]
6640
6653
  };
6641
6654
 
6655
+ // src/projects/project-metadata.ts
6656
+ import { Component as Component2 } from "projen";
6657
+ import { NodeProject } from "projen/lib/javascript";
6658
+ var GITHUB_HTTPS_RE = /(?:https?:\/\/|git\+https:\/\/)github\.com\/([^/]+)\/([^/.]+)(?:\.git)?/;
6659
+ var GITHUB_SSH_RE = /git@github\.com:([^/]+)\/([^/.]+)(?:\.git)?/;
6660
+ function parseGitHubUrl(url) {
6661
+ const httpsMatch = url.match(GITHUB_HTTPS_RE);
6662
+ if (httpsMatch) {
6663
+ return { owner: httpsMatch[1], name: httpsMatch[2] };
6664
+ }
6665
+ const sshMatch = url.match(GITHUB_SSH_RE);
6666
+ if (sshMatch) {
6667
+ return { owner: sshMatch[1], name: sshMatch[2] };
6668
+ }
6669
+ return { owner: void 0, name: void 0 };
6670
+ }
6671
+ var ProjectMetadata = class _ProjectMetadata extends Component2 {
6672
+ /**
6673
+ * Returns the ProjectMetadata instance for a project. Walks up the parent
6674
+ * chain so sub-projects resolve the metadata declared on a root
6675
+ * `MonorepoProject` without needing a duplicate declaration of their own.
6676
+ * Returns `undefined` if no ancestor has a `ProjectMetadata` component.
6677
+ */
6678
+ static of(project) {
6679
+ const isProjectMetadata = (c) => c instanceof _ProjectMetadata;
6680
+ let current = project;
6681
+ while (current) {
6682
+ const found = current.components.find(isProjectMetadata);
6683
+ if (found) {
6684
+ return found;
6685
+ }
6686
+ current = current.parent;
6687
+ }
6688
+ return void 0;
6689
+ }
6690
+ constructor(project, options = {}) {
6691
+ super(project);
6692
+ this.metadata = this.resolveMetadata(options);
6693
+ }
6694
+ /**
6695
+ * Merges explicit options with auto-detected values.
6696
+ * Auto-detection reads the repository URL from package.json
6697
+ * (via Projen's NodePackage manifest) and parses GitHub owner/name.
6698
+ * Explicit options always take precedence over auto-detected values.
6699
+ */
6700
+ resolveMetadata(options) {
6701
+ const autoDetected = this.autoDetectRepository();
6702
+ return {
6703
+ repository: {
6704
+ owner: options.repository?.owner ?? autoDetected.owner,
6705
+ name: options.repository?.name ?? autoDetected.name,
6706
+ defaultBranch: options.repository?.defaultBranch ?? "main"
6707
+ },
6708
+ githubProject: options.githubProject,
6709
+ organization: options.organization,
6710
+ slack: options.slack,
6711
+ labels: options.labels,
6712
+ milestones: options.milestones,
6713
+ docsPath: options.docsPath,
6714
+ deployment: options.deployment
6715
+ };
6716
+ }
6717
+ /**
6718
+ * Attempts to auto-detect repository owner and name from the Projen
6719
+ * project's package.json repository field.
6720
+ */
6721
+ autoDetectRepository() {
6722
+ if (!(this.project instanceof NodeProject)) {
6723
+ return { owner: void 0, name: void 0 };
6724
+ }
6725
+ const manifest = this.project.package.manifest;
6726
+ const repoField = manifest.repository;
6727
+ if (!repoField) {
6728
+ return { owner: void 0, name: void 0 };
6729
+ }
6730
+ const url = typeof repoField === "string" ? repoField : repoField.url ?? "";
6731
+ return parseGitHubUrl(url);
6732
+ }
6733
+ };
6734
+
6642
6735
  // src/agent/bundles/slack.ts
6736
+ function hasSlackConfig(slack) {
6737
+ if (!slack) {
6738
+ return false;
6739
+ }
6740
+ if (slack.projectChannel || slack.alertsChannel) {
6741
+ return true;
6742
+ }
6743
+ if (slack.channels && Object.keys(slack.channels).length > 0) {
6744
+ return true;
6745
+ }
6746
+ return false;
6747
+ }
6643
6748
  var slackBundle = {
6644
6749
  name: "slack",
6645
- description: "Slack MCP message formatting and best practices",
6646
- appliesWhen: () => false,
6750
+ description: "Slack MCP message formatting and best practices. Auto-activates when ProjectMetadata declares a Slack integration; can still be force-included via `includeBundles: ['slack']`.",
6751
+ appliesWhen: (project) => {
6752
+ const pm = ProjectMetadata.of(project);
6753
+ return hasSlackConfig(pm?.metadata.slack);
6754
+ },
6647
6755
  rules: [
6648
6756
  {
6649
6757
  name: "slack-message-formatting",
@@ -6672,7 +6780,11 @@ var slackBundle = {
6672
6780
  " \u2022 Feature B: <https://github.com/org/repo/pull/2|repo#2>",
6673
6781
  " ```",
6674
6782
  "",
6675
- "5. **Avoid:** Plain URLs immediately after a bullet/label on the same line (e.g., `\u2022 Feature A: https://github.com/...`) when sending via API, as it can render with bullets inside or between links"
6783
+ "5. **Avoid:** Plain URLs immediately after a bullet/label on the same line (e.g., `\u2022 Feature A: https://github.com/...`) when sending via API, as it can render with bullets inside or between links",
6784
+ "",
6785
+ "## Activation",
6786
+ "",
6787
+ "This bundle auto-activates when the consuming project declares a Slack integration through `ProjectMetadata` (any of `slack.projectChannel`, `slack.alertsChannel`, or a non-empty `slack.channels` record). If no `ProjectMetadata` is configured, opt in manually via `AgentConfigOptions.includeBundles: ['slack']`."
6676
6788
  ].join("\n"),
6677
6789
  tags: ["workflow"]
6678
6790
  }
@@ -7297,12 +7409,12 @@ var softwareProfileBundle = {
7297
7409
  };
7298
7410
 
7299
7411
  // src/turbo/turbo-repo.ts
7300
- import { Component as Component3, FileBase, JsonFile } from "projen/lib";
7412
+ import { Component as Component4, FileBase, JsonFile } from "projen/lib";
7301
7413
  import { JobPermission } from "projen/lib/github/workflows-model";
7302
7414
 
7303
7415
  // src/turbo/turbo-repo-task.ts
7304
- import { Component as Component2 } from "projen/lib";
7305
- var TurboRepoTask = class extends Component2 {
7416
+ import { Component as Component3 } from "projen/lib";
7417
+ var TurboRepoTask = class extends Component3 {
7306
7418
  constructor(project, options) {
7307
7419
  super(project);
7308
7420
  this.project = project;
@@ -7343,7 +7455,7 @@ var TurboRepoTask = class extends Component2 {
7343
7455
  // src/turbo/turbo-repo.ts
7344
7456
  var ROOT_TURBO_TASK_NAME = "turbo:build";
7345
7457
  var ROOT_CI_TASK_NAME = "build:all";
7346
- var _TurboRepo = class _TurboRepo extends Component3 {
7458
+ var _TurboRepo = class _TurboRepo extends Component4 {
7347
7459
  constructor(project, options = {}) {
7348
7460
  super(project);
7349
7461
  this.project = project;
@@ -7669,7 +7781,7 @@ var typescriptBundle = {
7669
7781
  };
7670
7782
 
7671
7783
  // src/vitest/vitest-component.ts
7672
- import { Component as Component4 } from "projen";
7784
+ import { Component as Component5 } from "projen";
7673
7785
  import { Jest } from "projen/lib/javascript";
7674
7786
  import { TextFile } from "projen/lib/textfile";
7675
7787
 
@@ -7748,7 +7860,7 @@ var VERSION = {
7748
7860
  };
7749
7861
 
7750
7862
  // src/vitest/vitest-component.ts
7751
- var Vitest = class _Vitest extends Component4 {
7863
+ var Vitest = class _Vitest extends Component5 {
7752
7864
  constructor(project, options = {}) {
7753
7865
  super(project);
7754
7866
  this.project = project;
@@ -7948,86 +8060,6 @@ function prefix(rel, entry) {
7948
8060
  return path.posix.join(rel, entry);
7949
8061
  }
7950
8062
 
7951
- // src/projects/project-metadata.ts
7952
- import { Component as Component5 } from "projen";
7953
- import { NodeProject as NodeProject2 } from "projen/lib/javascript";
7954
- var GITHUB_HTTPS_RE = /(?:https?:\/\/|git\+https:\/\/)github\.com\/([^/]+)\/([^/.]+)(?:\.git)?/;
7955
- var GITHUB_SSH_RE = /git@github\.com:([^/]+)\/([^/.]+)(?:\.git)?/;
7956
- function parseGitHubUrl(url) {
7957
- const httpsMatch = url.match(GITHUB_HTTPS_RE);
7958
- if (httpsMatch) {
7959
- return { owner: httpsMatch[1], name: httpsMatch[2] };
7960
- }
7961
- const sshMatch = url.match(GITHUB_SSH_RE);
7962
- if (sshMatch) {
7963
- return { owner: sshMatch[1], name: sshMatch[2] };
7964
- }
7965
- return { owner: void 0, name: void 0 };
7966
- }
7967
- var ProjectMetadata = class _ProjectMetadata extends Component5 {
7968
- /**
7969
- * Returns the ProjectMetadata instance for a project. Walks up the parent
7970
- * chain so sub-projects resolve the metadata declared on a root
7971
- * `MonorepoProject` without needing a duplicate declaration of their own.
7972
- * Returns `undefined` if no ancestor has a `ProjectMetadata` component.
7973
- */
7974
- static of(project) {
7975
- const isProjectMetadata = (c) => c instanceof _ProjectMetadata;
7976
- let current = project;
7977
- while (current) {
7978
- const found = current.components.find(isProjectMetadata);
7979
- if (found) {
7980
- return found;
7981
- }
7982
- current = current.parent;
7983
- }
7984
- return void 0;
7985
- }
7986
- constructor(project, options = {}) {
7987
- super(project);
7988
- this.metadata = this.resolveMetadata(options);
7989
- }
7990
- /**
7991
- * Merges explicit options with auto-detected values.
7992
- * Auto-detection reads the repository URL from package.json
7993
- * (via Projen's NodePackage manifest) and parses GitHub owner/name.
7994
- * Explicit options always take precedence over auto-detected values.
7995
- */
7996
- resolveMetadata(options) {
7997
- const autoDetected = this.autoDetectRepository();
7998
- return {
7999
- repository: {
8000
- owner: options.repository?.owner ?? autoDetected.owner,
8001
- name: options.repository?.name ?? autoDetected.name,
8002
- defaultBranch: options.repository?.defaultBranch ?? "main"
8003
- },
8004
- githubProject: options.githubProject,
8005
- organization: options.organization,
8006
- slack: options.slack,
8007
- labels: options.labels,
8008
- milestones: options.milestones,
8009
- docsPath: options.docsPath,
8010
- deployment: options.deployment
8011
- };
8012
- }
8013
- /**
8014
- * Attempts to auto-detect repository owner and name from the Projen
8015
- * project's package.json repository field.
8016
- */
8017
- autoDetectRepository() {
8018
- if (!(this.project instanceof NodeProject2)) {
8019
- return { owner: void 0, name: void 0 };
8020
- }
8021
- const manifest = this.project.package.manifest;
8022
- const repoField = manifest.repository;
8023
- if (!repoField) {
8024
- return { owner: void 0, name: void 0 };
8025
- }
8026
- const url = typeof repoField === "string" ? repoField : repoField.url ?? "";
8027
- return parseGitHubUrl(url);
8028
- }
8029
- };
8030
-
8031
8063
  // src/agent/renderers/claude-renderer.ts
8032
8064
  import { JsonFile as JsonFile2 } from "projen";
8033
8065
  import { TextFile as TextFile2 } from "projen/lib/textfile";
@@ -9823,6 +9855,11 @@ var DEFAULT_STATUS_LABELS = [
9823
9855
  color: "FBCA04",
9824
9856
  description: "Actively being worked on"
9825
9857
  },
9858
+ {
9859
+ name: "status:ready-for-review",
9860
+ color: "1D76DB",
9861
+ description: "PR opened and awaiting review"
9862
+ },
9826
9863
  {
9827
9864
  name: "status:blocked",
9828
9865
  color: "D93F0B",