@theholocron/astromech 5.0.0-alpha.129 → 5.0.0-alpha.133

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 CHANGED
@@ -69,7 +69,7 @@ documents, not a naming convention repos need to follow.
69
69
  | `delivery.publish` | semantic-release | no local equivalent — CI only; carries `preview` (npm dist-tags) |
70
70
  | `delivery.deploy` | Cloudflare Pages / Vercel | no local equivalent — CI only; carries `preview` |
71
71
  | `delivery.bundleSize` | bundle-size upload to Codecov | no local equivalent — CI only |
72
- | `platform.repoSync` | `holocron sync` | keeps generated files current |
72
+ | `platform.repoSync` | `holocron repo sync` | keeps generated files current |
73
73
  | `platform.commitStandards` | commitlint | no local equivalent — enforced by the `commit-msg` hook locally, over the PR's commit range in CI |
74
74
  | `platform.repoValidation` | `scripts/validate-adrs.mjs`, `scripts/validate-registry.mjs`, `scripts/validate-docs-presence.mjs` | a job-bearing task — spec/ADR frontmatter, registry-doc completeness, and docs-presence, not linters |
75
75
  | `knowledge.wiki` | Fern | publishes `docs/wiki/*.md` — not a sync, a publish; carries `preview` |
@@ -174,7 +174,7 @@ de-duplicated. Most tasks are single always-run jobs now, so their context
174
174
  names that job directly (`"Typecheck / tsc --noEmit"`) — the `… /
175
175
  Conclusion` fan-in aggregate is only used where a task genuinely has
176
176
  several conditionally-run jobs feeding one check
177
- (`verification.unitTests`, `platform.repoValidation`). `holocron setup`
177
+ (`verification.unitTests`, `platform.repoValidation`). `holocron repo setup`
178
178
  prepends `"DCO"` and applies the list for `protection: "strict"` repos.
179
179
  Policy-free — manifest only.
180
180
 
@@ -188,7 +188,7 @@ came from), same manifest-derived category as `thinCallers()`. Pass the
188
188
  current file's content (or `null`) and it either merges the
189
189
  `individual_components` list in (preserving everything else in the file —
190
190
  thresholds, flags, custom rules) or scaffolds a fresh file from the base
191
- template. `holocron setup` writes the result via the `source` capability;
191
+ template. `holocron repo setup` writes the result via the `source` capability;
192
192
  this method never touches the filesystem beyond reading `packages/*` and
193
193
  `apps/*` under `cwd`.
194
194
 
@@ -201,7 +201,7 @@ Deploys the workspace packages whose manifest declares it (holocron#930):
201
201
  tasks: [{ name: "delivery.deploy", with: { on: "release", channel: "alpha" } }];
202
202
  ```
203
203
 
204
- `holocron deploy-on-release --channel=<alpha|main> --from=<previous release commit> --to=<release commit>`
204
+ `holocron deploy on-release --channel=<alpha|main> --from=<previous release commit> --to=<release commit>`
205
205
  (or `deployOnRelease()` from `@theholocron/astromech`) deploys each such package
206
206
  when the release is on its `channel` (default `main`, the stable release;
207
207
  set `alpha` for prereleases) and changes the package or one of its `workspace:*` dependencies
@@ -1,4 +1,4 @@
1
- import { i as normalizeTaskEntry, n as TaskEntry, r as TasksConfig, t as TaskConfigItem } from "../schema-CGybbV7_.mjs";
1
+ import { i as normalizeTaskEntry, n as TaskEntry, r as TasksConfig, t as TaskConfigItem } from "../schema-BDld3xq1.mjs";
2
2
  //#region src/config/define.d.ts
3
3
  /**
4
4
  * Typed identity helper for `astromech.config.ts`:
package/dist/index.d.mts CHANGED
@@ -1,11 +1,11 @@
1
- import { r as TasksConfig } from "./schema-CGybbV7_.mjs";
1
+ import { r as TasksConfig } from "./schema-BDld3xq1.mjs";
2
2
  //#region src/generators/github-action-thin-callers.d.ts
3
3
  /**
4
4
  * Workflow templates + thin-caller generation.
5
5
  *
6
6
  * `WORKFLOW_TEMPLATES` holds each reusable `.github/workflows/<name>.yml`
7
7
  * (synced to `theholocron/.github`); `generateThinCallerContent` wraps one
8
- * into the thin caller `holocron setup` / `holocron sync` write locally.
8
+ * into the thin caller `holocron repo setup` / `holocron repo sync` write locally.
9
9
  */
10
10
  declare const WORKFLOW_TEMPLATES: Record<string, string>;
11
11
  declare const KNOWN_WORKFLOWS: Set<string>;
@@ -55,7 +55,7 @@ interface PreviewConfig {
55
55
  project: string;
56
56
  /**
57
57
  * Base domain for preview URLs (e.g. `"preview.theholocron.dev"`).
58
- * When set, `holocron setup` automatically provisions:
58
+ * When set, `holocron repo setup` automatically provisions:
59
59
  * - Cloudflare Pages custom domain `*.<domain>` on the project
60
60
  * - DNS wildcard CNAME `*.<domain>` → `<project>.pages.dev`
61
61
  *
@@ -102,12 +102,12 @@ declare function generateCombinedDeployContent(deployWith: Record<string, unknow
102
102
  * - run-chromatic object → run-chromatic: true + chromatic-projects
103
103
  * - plain arrays → JSON-stringified for YAML scalar quoting
104
104
  *
105
- * Used by both `holocron setup` and `sync-workflow-templates`.
105
+ * Used by both `holocron repo setup` and `sync-workflow-templates`.
106
106
  */
107
107
  declare function normalizeWorkflowWith(raw: Record<string, unknown>): Record<string, unknown>;
108
108
  /**
109
109
  * Derive on.push.paths entries from the deploy with: shorthand.
110
- * Used by both `holocron setup` and `sync-workflow-templates`.
110
+ * Used by both `holocron repo setup` and `sync-workflow-templates`.
111
111
  */
112
112
  declare function deriveDeployPaths(raw: Record<string, unknown>): string[];
113
113
  //#endregion
@@ -231,6 +231,34 @@ interface CiInput extends RunDeps, CiOptions {
231
231
  }
232
232
  declare function runCi(input: CiInput): CiReport;
233
233
  //#endregion
234
+ //#region src/tasks/group.d.ts
235
+ interface GroupOptions {
236
+ /** Print the resolved commands without running anything. */
237
+ dryRun?: boolean;
238
+ /** `turbo --filter=<pkg>` passthrough (monorepo). */
239
+ filter?: string;
240
+ }
241
+ interface GroupJobReport {
242
+ task: string;
243
+ status: "ok" | "fail" | "skip" | "dry-run";
244
+ command?: string;
245
+ message?: string;
246
+ }
247
+ interface GroupReport {
248
+ /** `"unknown"` when the namespace matches zero configured tasks. */
249
+ status: "ok" | "fail" | "dry-run" | "unknown";
250
+ jobs: GroupJobReport[];
251
+ }
252
+ interface GroupInput extends RunDeps, GroupOptions {
253
+ cwd: string;
254
+ config: TasksConfig;
255
+ /** The bare namespace, e.g. `"sourceQuality"` — matched against `"sourceQuality."`-prefixed task names. */
256
+ namespace: string;
257
+ }
258
+ /** Every configured task whose name starts with `"<namespace>."`, in manifest declaration order. */
259
+ declare function matchNamespace(config: TasksConfig, namespace: string): string[];
260
+ declare function runGroup(input: GroupInput): GroupReport;
261
+ //#endregion
234
262
  //#region src/astromech.d.ts
235
263
  interface AstromechOptions {
236
264
  /** Repo root. */
@@ -276,8 +304,15 @@ interface RunOptions {
276
304
  filter?: string;
277
305
  }
278
306
  interface Astromech {
279
- /** Run one task — or one of its sub-jobs (`opts.job`) — locally. */
280
- run(task: string, opts?: RunOptions): RunTaskReport;
307
+ /**
308
+ * Run one task — or one of its sub-jobs (`opts.job`) — locally. When
309
+ * `task` isn't an exact registry task but matches the prefix of one or
310
+ * more configured tasks (`"sourceQuality"` against `sourceQuality.*`),
311
+ * runs every matching task in sequence instead ({@link GroupReport}) —
312
+ * `opts.job` is ignored for a namespace match, since a job belongs to
313
+ * one task, not a namespace.
314
+ */
315
+ run(task: string, opts?: RunOptions): RunTaskReport | GroupReport;
281
316
  /**
282
317
  * Run the merge-gating checks locally, in CI order — "will CI pass?".
283
318
  * Default scope: `required: true` tasks (falls back to every `ci: true`
@@ -292,7 +327,7 @@ interface Astromech {
292
327
  */
293
328
  thinCallers(): Map<string, string>;
294
329
  /**
295
- * The complete reusable-workflow batch `holocron sync-github` pushes to
330
+ * The complete reusable-workflow batch `holocron sync github` pushes to
296
331
  * `theholocron/.github` — repo-relative path → content, "do not edit" header
297
332
  * already applied to the YAML. Config-independent (the same for every repo).
298
333
  */
@@ -305,10 +340,19 @@ interface Astromech {
305
340
  * when there is no config or `syncScripts: false`.
306
341
  */
307
342
  packageScripts(): Record<string, string>;
343
+ /**
344
+ * Task names this repo's manifest can actually run locally — the same
345
+ * filter {@link packageScripts} applies (skips `local: false` and tasks
346
+ * with no local runner at all), but independent of `syncScripts`: a repo
347
+ * that opts out of generated `package.json` scripts still has real
348
+ * runnable tasks. Empty when there is no config. Backs `holocron`'s own
349
+ * interactive task picker (`run` with no task given).
350
+ */
351
+ runnableTasks(): string[];
308
352
  /**
309
353
  * The branch-protection required-status-check contexts for this repo —
310
354
  * every `required: true` task's check context plus `extraRequiredChecks`,
311
- * ordered and de-duplicated. `holocron setup` prepends `"DCO"` and applies
355
+ * ordered and de-duplicated. `holocron repo setup` prepends `"DCO"` and applies
312
356
  * the list; this method is policy-free (manifest only).
313
357
  */
314
358
  requiredChecks(): string[];
@@ -316,7 +360,7 @@ interface Astromech {
316
360
  * This repo's `codecov.yml` — component `paths` derived from `packages/*`.
317
361
  * Pass the current file's content (`null` if none exists yet) to either
318
362
  * merge the component list in or scaffold a fresh file. Policy-free same
319
- * as {@link requiredChecks} — `holocron setup` owns writing the result.
363
+ * as {@link requiredChecks} — `holocron repo setup` owns writing the result.
320
364
  */
321
365
  codecovConfig(existing: string | null): string;
322
366
  /**
@@ -359,14 +403,14 @@ declare function createAstromech(options: AstromechOptions): Astromech;
359
403
  * come from workspace packages; the status targets track the `test` task's
360
404
  * coverage setup), the same category as the reusable `test.yml` this package
361
405
  * also generates. Moved out of `@theholocron/cli` (theholocron/holocron#650)
362
- * — `holocron setup`'s codecov step now calls {@link codecovConfig} instead
406
+ * — `holocron repo setup`'s codecov step now calls {@link codecovConfig} instead
363
407
  * of importing this logic directly.
364
408
  */
365
409
  interface WorkspacePackage {
366
410
  slug: string;
367
411
  name: string;
368
412
  /** Which workspace root the package was discovered under. Defaults to `"packages"`. */
369
- dir?: "packages" | "apps";
413
+ dir?: "packages" | "apps" | "plugins";
370
414
  }
371
415
  declare function codecovComponentBlock(packages: WorkspacePackage[]): string;
372
416
  /**
@@ -382,17 +426,18 @@ declare function codecovComponentBlock(packages: WorkspacePackage[]): string;
382
426
  declare function ensureIfNotFound(yaml: string): string;
383
427
  declare function mergeCodecovComponents(existing: string, packages: WorkspacePackage[]): string;
384
428
  /**
385
- * Every public `packages/*` and `apps/*` workspace, sorted by slug. `[]`
386
- * when neither directory exists. Monorepo templates (Next.js, React, …)
387
- * ship user-facing code under `apps/` alongside library code under
388
- * `packages/` — both need a codecov component so `codecov/patch/<slug>`
389
- * actually posts for each.
429
+ * Every public `packages/*`, `apps/*`, and `plugins/*` workspace, sorted by
430
+ * slug. `[]` when none of the three directories exist. Monorepo templates
431
+ * (Next.js, React, …) ship user-facing code under `apps/` alongside library
432
+ * code under `packages/`; `holocron` itself splits vendor plugin packages
433
+ * into their own `plugins/*` root — every recognized root needs a codecov
434
+ * component so `codecov/patch/<slug>` actually posts for each.
390
435
  */
391
436
  declare function readWorkspacePackages(repoRoot: string): WorkspacePackage[];
392
437
  /** A brand-new `codecov.yml` — the scaffold header + the base template + this repo's component list. */
393
438
  declare function createCodecovConfig(packages: WorkspacePackage[]): string;
394
439
  /**
395
- * The full pipeline `holocron setup` needs: read this repo's public
440
+ * The full pipeline `holocron repo setup` needs: read this repo's public
396
441
  * `packages/*`, then either merge them into an `existing` `codecov.yml` or
397
442
  * scaffold a new one.
398
443
  */
@@ -401,7 +446,7 @@ declare function codecovConfig(repoRoot: string, existing: string | null): strin
401
446
  //#region src/generators/github-action-reusable-workflows.d.ts
402
447
  /**
403
448
  * The **reusable** GitHub Actions surface pushed to `theholocron/.github` by
404
- * `holocron sync-github` — the `workflow_call` implementations and composite
449
+ * `holocron sync github` — the `workflow_call` implementations and composite
405
450
  * actions that every repo's thin callers delegate to.
406
451
  *
407
452
  * `theholocron/.github` is a **pure sync target**: `.github/workflows/*`,
@@ -419,7 +464,7 @@ declare const REUSABLE_ACTIONS: Record<string, string>;
419
464
  /** GitHub starter-workflow metadata → `workflow-templates/<name>.properties.json`. */
420
465
  declare const WORKFLOW_TEMPLATE_PROPERTIES: Record<string, string>;
421
466
  /**
422
- * The complete file batch `holocron sync-github` pushes to `theholocron/.github`:
467
+ * The complete file batch `holocron sync github` pushes to `theholocron/.github`:
423
468
  * path → content. YAML gets the "do not edit" header; the starter-workflow
424
469
  * `.properties.json` files are left bare (native JSON, not a commented file).
425
470
  */
@@ -463,7 +508,7 @@ declare function requiredChecks(config: TasksConfig): string[];
463
508
  * listing which packages to build) is a structurally different, genuinely
464
509
  * per-repo document — out of scope here, same as Bucket C content.
465
510
  *
466
- * Not yet wired into `holocron setup`'s per-package write loop (every
511
+ * Not yet wired into `holocron repo setup`'s per-package write loop (every
467
512
  * other Bucket B file there is a single repo-root file, safely
468
513
  * overwritten every run — `tsconfig.json` is per-package, and most
469
514
  * packages' files still carry real hand-authored content today, not yet
@@ -515,7 +560,7 @@ declare function createTsconfig(options: TsconfigOptions): string;
515
560
  * `sourceQuality.*`, `security.*`, `delivery.*`, `platform.*`,
516
561
  * `knowledge.*`), not tool names — `eslint`/`vitest`/`tsdown`/… stay
517
562
  * internal to this file and `theholocron/configs`. See
518
- * `.notes/tech-vocabulary-rename.spec.md` (#675) for the full mapping and
563
+ * `docs/wiki/specifications/tech-vocabulary-rename.spec.md` (#675) for the full mapping and
519
564
  * the reasoning behind each namespace and decomposition.
520
565
  *
521
566
  * Spec: `docs/wiki/specifications/tech-astromech-task-runner.spec.md` (epic #581).
@@ -653,4 +698,4 @@ interface DeployOnReleaseReport {
653
698
  */
654
699
  declare function deployOnRelease(options: DeployOnReleaseOptions, { run, readJson, listDirs, sleep, now, loadTasks }?: DeployOnReleaseDeps): Promise<DeployOnReleaseReport>;
655
700
  //#endregion
656
- export { type Astromech, type AstromechOptions, CI_ORDER, type CiJobReport, type CiOptions, type CiReport, type DeployOnReleaseOptions, type DeployOnReleaseReport, type DeployOnReleaseResult, type ExecFn, type JobDef, KNOWN_TASKS, KNOWN_WORKFLOWS, type LocalRunner, type OrgContext, type PreviewConfig, REUSABLE_ACTIONS, REUSABLE_WORKFLOWS, type RunLogger, type RunOptions, type RunTaskInput, type RunTaskReport, TASKS, type TaskDef, type TsconfigOptions, WORKFLOW_CHECK_CONTEXTS, WORKFLOW_TEMPLATES, WORKFLOW_TEMPLATE_PROPERTIES, type WorkspacePackage, codecovComponentBlock, codecovConfig, createAstromech, createCodecovConfig, createTsconfig, deployOnRelease, deriveDeployPaths, ensureIfNotFound, extractPreviewConfig, generateCombinedDeployContent, generateThinCallerContent, mergeCodecovComponents, normalizeWorkflowWith, readWorkspacePackages, requiredChecks, reusableTemplates, runCi, runTask };
701
+ export { type Astromech, type AstromechOptions, CI_ORDER, type CiJobReport, type CiOptions, type CiReport, type DeployOnReleaseOptions, type DeployOnReleaseReport, type DeployOnReleaseResult, type ExecFn, type GroupJobReport, type GroupOptions, type GroupReport, type JobDef, KNOWN_TASKS, KNOWN_WORKFLOWS, type LocalRunner, type OrgContext, type PreviewConfig, REUSABLE_ACTIONS, REUSABLE_WORKFLOWS, type RunLogger, type RunOptions, type RunTaskInput, type RunTaskReport, TASKS, type TaskDef, type TsconfigOptions, WORKFLOW_CHECK_CONTEXTS, WORKFLOW_TEMPLATES, WORKFLOW_TEMPLATE_PROPERTIES, type WorkspacePackage, codecovComponentBlock, codecovConfig, createAstromech, createCodecovConfig, createTsconfig, deployOnRelease, deriveDeployPaths, ensureIfNotFound, extractPreviewConfig, generateCombinedDeployContent, generateThinCallerContent, matchNamespace, mergeCodecovComponents, normalizeWorkflowWith, readWorkspacePackages, requiredChecks, reusableTemplates, runCi, runGroup, runTask };
package/dist/index.mjs CHANGED
@@ -11,13 +11,13 @@ var codecov_default = "codecov:\n require_ci_to_pass: true\n\ncoverage:\n prec
11
11
  * come from workspace packages; the status targets track the `test` task's
12
12
  * coverage setup), the same category as the reusable `test.yml` this package
13
13
  * also generates. Moved out of `@theholocron/cli` (theholocron/holocron#650)
14
- * — `holocron setup`'s codecov step now calls {@link codecovConfig} instead
14
+ * — `holocron repo setup`'s codecov step now calls {@link codecovConfig} instead
15
15
  * of importing this logic directly.
16
16
  */
17
17
  const INDIVIDUAL_COMPONENTS_MARKER = " individual_components:";
18
18
  function scaffoldHeader() {
19
19
  return [
20
- `# Scaffolded by holocron setup — edit this file freely.`,
20
+ `# Scaffolded by holocron repo setup — edit this file freely.`,
21
21
  `# Source: theholocron/holocron · packages/astromech/src/generators/codecov.ts`,
22
22
  ``
23
23
  ].join("\n");
@@ -91,21 +91,26 @@ function readWorkspaceDir(repoRoot, dir) {
91
91
  return packages;
92
92
  }
93
93
  /**
94
- * Every public `packages/*` and `apps/*` workspace, sorted by slug. `[]`
95
- * when neither directory exists. Monorepo templates (Next.js, React, …)
96
- * ship user-facing code under `apps/` alongside library code under
97
- * `packages/` — both need a codecov component so `codecov/patch/<slug>`
98
- * actually posts for each.
94
+ * Every public `packages/*`, `apps/*`, and `plugins/*` workspace, sorted by
95
+ * slug. `[]` when none of the three directories exist. Monorepo templates
96
+ * (Next.js, React, …) ship user-facing code under `apps/` alongside library
97
+ * code under `packages/`; `holocron` itself splits vendor plugin packages
98
+ * into their own `plugins/*` root — every recognized root needs a codecov
99
+ * component so `codecov/patch/<slug>` actually posts for each.
99
100
  */
100
101
  function readWorkspacePackages(repoRoot) {
101
- return [...readWorkspaceDir(repoRoot, "packages"), ...readWorkspaceDir(repoRoot, "apps")].sort((a, b) => a.slug.localeCompare(b.slug));
102
+ return [
103
+ ...readWorkspaceDir(repoRoot, "packages"),
104
+ ...readWorkspaceDir(repoRoot, "apps"),
105
+ ...readWorkspaceDir(repoRoot, "plugins")
106
+ ].sort((a, b) => a.slug.localeCompare(b.slug));
102
107
  }
103
108
  /** A brand-new `codecov.yml` — the scaffold header + the base template + this repo's component list. */
104
109
  function createCodecovConfig(packages) {
105
110
  return `${scaffoldHeader()}${codecov_default.trimEnd()}${codecovComponentBlock(packages)}`;
106
111
  }
107
112
  /**
108
- * The full pipeline `holocron setup` needs: read this repo's public
113
+ * The full pipeline `holocron repo setup` needs: read this repo's public
109
114
  * `packages/*`, then either merge them into an `existing` `codecov.yml` or
110
115
  * scaffold a new one.
111
116
  */
@@ -118,7 +123,7 @@ function codecovConfig(repoRoot, existing) {
118
123
  var auto_commit_default = "name: Auto Commit\ndescription: >\n Commit and push any file changes using stefanzweifel/git-auto-commit-action.\n If a branch name is provided and differs from the current branch, a new branch\n is created automatically.\n\ninputs:\n token:\n description: >\n GitHub token with push access to the target branch. Used to authenticate\n the git remote so the commit can be pushed.\n required: true\n branch:\n description: >\n Branch to commit to. Leave empty to commit to the current branch (useful\n in PR contexts). Provide an explicit name (e.g. chore/auto-sync) to push\n to a separate branch.\n required: false\n default: \"\"\n commit-message:\n description: Commit message.\n required: true\n commit-options:\n description: >\n Additional options passed to git commit (e.g. --no-verify).\n required: false\n default: \"\"\n commit-user-name:\n description: Git user.name for the commit.\n required: false\n default: \"github-actions[bot]\"\n commit-user-email:\n description: Git user.email for the commit.\n required: false\n default: \"41898282+github-actions[bot]@users.noreply.github.com\"\n commit-author:\n description: >\n Git author string in \"Name <email>\" format.\n required: false\n default: \"github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>\"\n\noutputs:\n changes-detected:\n description: \"'true' if any files were committed, 'false' otherwise.\"\n value: ${{ steps.commit.outputs.changes_detected }}\n\nruns:\n using: composite\n steps:\n - name: Configure git remote with token\n shell: bash\n run: |\n REMOTE_URL=$(git remote get-url origin)\n AUTHED_URL=$(echo \"$REMOTE_URL\" | sed \"s|https://|https://x-access-token:${TOKEN}@|\")\n git remote set-url origin \"$AUTHED_URL\"\n env:\n TOKEN: ${{ inputs.token }}\n\n - name: Reset branch to current HEAD\n if: ${{ inputs.branch != '' }}\n shell: bash\n run: git checkout -B \"$BRANCH\"\n env:\n BRANCH: ${{ inputs.branch }}\n\n - name: Build signed commit message\n id: msg\n shell: bash\n run: |\n TRAILER=\"Signed-off-by: ${COMMIT_USER_NAME} <${COMMIT_USER_EMAIL}>\"\n if echo \"$COMMIT_MESSAGE\" | grep -qF \"$TRAILER\"; then\n FINAL=\"$COMMIT_MESSAGE\"\n else\n FINAL=\"${COMMIT_MESSAGE}\"$'\\n\\n'\"${TRAILER}\"\n fi\n {\n echo \"value<<EOF_TRAILER\"\n printf '%s' \"$FINAL\"\n echo \"\"\n echo \"EOF_TRAILER\"\n } >> \"$GITHUB_OUTPUT\"\n env:\n COMMIT_MESSAGE: ${{ inputs.commit-message }}\n COMMIT_USER_NAME: ${{ inputs.commit-user-name }}\n COMMIT_USER_EMAIL: ${{ inputs.commit-user-email }}\n\n - uses: stefanzweifel/git-auto-commit-action@4a55954c782fc1ea30b9056cd3e7a2b40ca8887d # v7.2.0\n id: commit\n with:\n branch: ${{ inputs.branch }}\n commit_message: ${{ steps.msg.outputs.value }}\n commit_options: ${{ inputs.commit-options }}\n commit_user_name: ${{ inputs.commit-user-name }}\n commit_user_email: ${{ inputs.commit-user-email }}\n commit_author: ${{ inputs.commit-author }}\n";
119
124
  //#endregion
120
125
  //#region src/templates/reusable/actions/holocron.yml
121
- var holocron_default = "name: Holocron\ndescription: >\n Run the Holocron CLI — `holocron run <task> [job]` by default, or any other\n subcommand via `command:` (`sync`, `sync-github`, …). Resolves\n `@theholocron/cli` from `node_modules` (published tarball) or builds it from\n source when it resolves to an unbuilt workspace checkout (the holocron repo\n itself). Requires dependencies to be installed already (run the setup action\n first).\n\ninputs:\n command:\n description: >\n Holocron subcommand. Default `run` — then `task` (and optional `job`)\n name the manifest task. Set to `sync` / `sync-github` / … to run that\n subcommand directly; `args` becomes everything after it.\n required: false\n default: run\n task:\n description: >\n Manifest task to run when command is run — typecheck, test, build, audit.\n required: false\n default: \"\"\n job:\n description: Optional sub-job within the task (e.g. knip, performance for audit).\n required: false\n default: \"\"\n args:\n description: >\n For `command: run`, extra arguments forwarded to the tool after `--`.\n For any other command, the arguments passed straight to it.\n required: false\n default: \"\"\n\noutputs:\n log-file:\n description: >\n Path to a file holding the full captured stdout+stderr of this\n invocation — the same text the live Actions log shows, saved for a\n caller that wants to ship it elsewhere (e.g. Sentinel's dispatched\n checks shipping it to Axiom, holocron#769/#794).\n value: ${{ steps.run.outputs.log-file }}\n\nruns:\n using: composite\n\n steps:\n - name: Build the workspace when the CLI resolves to an unbuilt checkout\n shell: bash\n # The holocron repo carries @theholocron/cli as `workspace:*`; its bin\n # (dist/cli.mjs) does not exist on a fresh checkout. `pnpm build` is a\n # turbo run — cached and cheap once warm. A no-op everywhere else, where\n # the published tarball already ships dist/.\n #\n # pnpm creates every workspace package's node_modules/.bin/holocron shim\n # once, during the setup action's earlier `pnpm install` — before this\n # build has run, so every one of them is silently skipped (\"Failed to\n # create bin ... ENOENT\"), not just @theholocron/cli's own. That's a\n # one-time decision: a later build doesn't retroactively fix a shim that\n # was never created. Re-running `pnpm install` here (fast — the lockfile\n # hasn't changed, so it only re-links `.bin`) is what actually fixes it,\n # confirmed against a real cold install: `holocron` stays unresolvable\n # from inside any package until this second install runs.\n run: |\n if [ ! -f node_modules/@theholocron/cli/dist/cli.mjs ]; then\n echo \"→ @theholocron/cli dist/ missing — building the workspace from source\" >&2\n pnpm build\n echo \"→ re-linking node_modules/.bin — pnpm skipped it pre-build\" >&2\n pnpm install --frozen-lockfile\n fi\n\n - name: holocron ${{ inputs.command }} ${{ inputs.task }}\n id: run\n shell: bash\n env:\n HOLOCRON_COMMAND: ${{ inputs.command }}\n HOLOCRON_TASK: ${{ inputs.task }}\n HOLOCRON_JOB: ${{ inputs.job }}\n HOLOCRON_ARGS: ${{ inputs.args }}\n run: |\n if [ \"$HOLOCRON_COMMAND\" = \"run\" ]; then\n set -- run \"$HOLOCRON_TASK\"\n [ -n \"$HOLOCRON_JOB\" ] && set -- \"$@\" \"$HOLOCRON_JOB\"\n # shellcheck disable=SC2086\n [ -n \"$HOLOCRON_ARGS\" ] && set -- \"$@\" -- $HOLOCRON_ARGS\n else\n # shellcheck disable=SC2086\n set -- \"$HOLOCRON_COMMAND\" $HOLOCRON_ARGS\n fi\n # Invoke the built entry directly. `pnpm exec holocron` relies on a\n # node_modules/.bin/holocron shim that pnpm does not create for a\n # workspace package whose dist/ was absent at install time (the holocron\n # repo itself). Resolving the package's main export gives dist/index.mjs;\n # the bin sits next to it as dist/cli.mjs. This is `require.resolve` from\n # node_modules — it works in the holocron monorepo AND in every consumer\n # repo (theholocron/holocron#655), unlike a hard-coded `packages/cli/…`.\n cli=\"$(dirname \"$(node -e 'process.stdout.write(require.resolve(\"@theholocron/cli\"))')\")/cli.mjs\"\n if [ ! -f \"$cli\" ]; then\n echo \"::error::@theholocron/cli entry not found at $cli — is the workspace built?\" >&2\n exit 1\n fi\n echo \"→ $cli $*\" >&2\n # `tee` keeps the live Actions log streaming exactly as before while\n # also capturing it to a file callers can ship elsewhere (log-file\n # output, above). PIPESTATUS[0] -- not $? -- is `node`'s own exit\n # code; $? after a pipe is tee's, which succeeds even when node fails.\n log_file=\"${RUNNER_TEMP}/holocron-output.log\"\n node \"$cli\" \"$@\" 2>&1 | tee \"$log_file\"\n exit_code=${PIPESTATUS[0]}\n echo \"log-file=$log_file\" >> \"$GITHUB_OUTPUT\"\n exit \"$exit_code\"\n";
126
+ var holocron_default = "name: Holocron\ndescription: >\n Run the Holocron CLI — `holocron run <task> [job]` by default, or any other\n subcommand via `command:` (`repo sync`, `sync github`, …). Resolves\n `@theholocron/cli` from `node_modules` (published tarball) or builds it from\n source when it resolves to an unbuilt workspace checkout (the holocron repo\n itself). Requires dependencies to be installed already (run the setup action\n first).\n\ninputs:\n command:\n description: >\n Holocron subcommand. Default `run` — then `task` (and optional `job`)\n name the manifest task. Set to `repo sync` / `sync github` / … to run that\n subcommand directly; `args` becomes everything after it.\n required: false\n default: run\n task:\n description: >\n Manifest task to run when command is run — typecheck, test, build, audit.\n required: false\n default: \"\"\n job:\n description: Optional sub-job within the task (e.g. knip, performance for audit).\n required: false\n default: \"\"\n args:\n description: >\n For `command: run`, extra arguments forwarded to the tool after `--`.\n For any other command, the arguments passed straight to it.\n required: false\n default: \"\"\n\noutputs:\n log-file:\n description: >\n Path to a file holding the full captured stdout+stderr of this\n invocation — the same text the live Actions log shows, saved for a\n caller that wants to ship it elsewhere (e.g. Sentinel's dispatched\n checks shipping it to Axiom, holocron#769/#794).\n value: ${{ steps.run.outputs.log-file }}\n\nruns:\n using: composite\n\n steps:\n - name: Build the workspace when the CLI resolves to an unbuilt checkout\n shell: bash\n # The holocron repo carries @theholocron/cli as `workspace:*`; its bin\n # (dist/cli.mjs) does not exist on a fresh checkout. `pnpm build` is a\n # turbo run — cached and cheap once warm. A no-op everywhere else, where\n # the published tarball already ships dist/.\n #\n # pnpm creates every workspace package's node_modules/.bin/holocron shim\n # once, during the setup action's earlier `pnpm install` — before this\n # build has run, so every one of them is silently skipped (\"Failed to\n # create bin ... ENOENT\"), not just @theholocron/cli's own. That's a\n # one-time decision: a later build doesn't retroactively fix a shim that\n # was never created. Re-running `pnpm install` here (fast — the lockfile\n # hasn't changed, so it only re-links `.bin`) is what actually fixes it,\n # confirmed against a real cold install: `holocron` stays unresolvable\n # from inside any package until this second install runs.\n run: |\n if [ ! -f node_modules/@theholocron/cli/dist/cli.mjs ]; then\n echo \"→ @theholocron/cli dist/ missing — building the workspace from source\" >&2\n pnpm build\n echo \"→ re-linking node_modules/.bin — pnpm skipped it pre-build\" >&2\n pnpm install --frozen-lockfile\n fi\n\n - name: holocron ${{ inputs.command }} ${{ inputs.task }}\n id: run\n shell: bash\n env:\n HOLOCRON_COMMAND: ${{ inputs.command }}\n HOLOCRON_TASK: ${{ inputs.task }}\n HOLOCRON_JOB: ${{ inputs.job }}\n HOLOCRON_ARGS: ${{ inputs.args }}\n run: |\n if [ \"$HOLOCRON_COMMAND\" = \"run\" ]; then\n set -- run \"$HOLOCRON_TASK\"\n [ -n \"$HOLOCRON_JOB\" ] && set -- \"$@\" \"$HOLOCRON_JOB\"\n # shellcheck disable=SC2086\n [ -n \"$HOLOCRON_ARGS\" ] && set -- \"$@\" -- $HOLOCRON_ARGS\n else\n # `command` may be a multi-word path (`repo sync`, `deploy on-release`):\n # word-split it so each token is its own argument.\n # shellcheck disable=SC2086\n set -- $HOLOCRON_COMMAND $HOLOCRON_ARGS\n fi\n # Invoke the built entry directly. `pnpm exec holocron` relies on a\n # node_modules/.bin/holocron shim that pnpm does not create for a\n # workspace package whose dist/ was absent at install time (the holocron\n # repo itself). Resolving the package's main export gives dist/index.mjs;\n # the bin sits next to it as dist/cli.mjs. This is `require.resolve` from\n # node_modules — it works in the holocron monorepo AND in every consumer\n # repo (theholocron/holocron#655), unlike a hard-coded `packages/cli/…`.\n cli=\"$(dirname \"$(node -e 'process.stdout.write(require.resolve(\"@theholocron/cli\"))')\")/cli.mjs\"\n if [ ! -f \"$cli\" ]; then\n echo \"::error::@theholocron/cli entry not found at $cli — is the workspace built?\" >&2\n exit 1\n fi\n echo \"→ $cli $*\" >&2\n # `tee` keeps the live Actions log streaming exactly as before while\n # also capturing it to a file callers can ship elsewhere (log-file\n # output, above). PIPESTATUS[0] -- not $? -- is `node`'s own exit\n # code; $? after a pipe is tee's, which succeeds even when node fails.\n log_file=\"${RUNNER_TEMP}/holocron-output.log\"\n node \"$cli\" \"$@\" 2>&1 | tee \"$log_file\"\n exit_code=${PIPESTATUS[0]}\n echo \"log-file=$log_file\" >> \"$GITHUB_OUTPUT\"\n exit \"$exit_code\"\n";
122
127
  //#endregion
123
128
  //#region src/templates/reusable/actions/install.yml
124
129
  var install_default = "name: Install dependencies\ndescription: Install project dependencies with pnpm frozen lockfile.\n\nruns:\n using: composite\n\n steps:\n - name: Install dependencies\n if: ${{ hashFiles('pnpm-lock.yaml') != '' }}\n shell: bash\n run: pnpm install --frozen-lockfile\n";
@@ -142,7 +147,7 @@ var delivery_bundleSize_default$1 = "name: Audit the Bundle Size\n\non: # yamlli
142
147
  var delivery_deploy_default$1 = "name: Deploy\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n type:\n description: \"Type of deployment: docs or storybook\"\n required: true\n type: string\n storybook-projects:\n description: >\n JSON array of { \"name\"?, \"workingDir\", \"outputDir\"? } objects for storybook deploys.\n Each is built via `pnpm -C <workingDir> build:storybook`. If \"name\" is provided the\n output is placed under `sandbox/<name>/`; omit \"name\" for single-repo deploys and the\n output lands directly in `sandbox/`.\n type: string\n required: false\n default: \"[]\"\n build-script:\n description: pnpm script that builds the Storybook static output (single storybook, type:storybook only)\n type: string\n required: false\n default: build:storybook\n output-dir:\n description: Directory where Storybook writes its static output (single storybook, type:storybook only)\n type: string\n required: false\n default: storybook-static\n\njobs:\n deploy:\n name: Deploy\n runs-on: ubuntu-latest\n permissions:\n contents: read\n pages: write\n id-token: write\n environment:\n name: github-pages\n url: ${{ steps.deployment.outputs.page_url }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Build docs site\n if: ${{ inputs.type == 'docs' }}\n run: pnpm -C docs build\n\n - name: Build Storybook projects\n if: ${{ inputs.storybook-projects != '[]' }}\n env:\n PROJECTS: ${{ inputs.storybook-projects }}\n run: |\n echo \"$PROJECTS\" | jq -c '.[]' | while IFS= read -r project; do\n workingDir=$(echo \"$project\" | jq -r '.workingDir')\n pnpm -C \"$workingDir\" build:storybook\n done\n\n - name: Build Storybook\n if: ${{ inputs.type == 'storybook' && inputs.storybook-projects == '[]' }}\n env:\n BUILD_SCRIPT: ${{ inputs.build-script }}\n run: pnpm run \"$BUILD_SCRIPT\"\n\n - name: Assemble site\n env:\n DEPLOY_TYPE: ${{ inputs.type }}\n PROJECTS: ${{ inputs.storybook-projects }}\n STORYBOOK_OUTPUT_DIR: ${{ inputs.output-dir }}\n run: |\n mkdir -p _site\n if [ \"$DEPLOY_TYPE\" = \"docs\" ]; then\n cp -r docs/dist/. _site/\n fi\n if [ \"$PROJECTS\" != \"[]\" ]; then\n echo \"$PROJECTS\" | jq -c '.[]' | while IFS= read -r project; do\n name=$(echo \"$project\" | jq -r '.name // \"\"')\n workingDir=$(echo \"$project\" | jq -r '.workingDir')\n outputDir=$(echo \"$project\" | jq -r '.outputDir // \"storybook-static\"')\n if [ -n \"$name\" ]; then\n target=\"_site/sandbox/${name}\"\n else\n target=\"_site/sandbox\"\n fi\n mkdir -p \"$target\"\n cp -r \"${workingDir}/${outputDir}/.\" \"$target/\"\n done\n elif [ \"$DEPLOY_TYPE\" = \"storybook\" ]; then\n mkdir -p _site/sandbox\n cp -r \"${STORYBOOK_OUTPUT_DIR}/.\" _site/sandbox/\n fi\n\n - uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1\n name: Upload pages artifact\n with:\n path: _site\n\n - uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5\n id: deployment\n name: Deploy to GitHub Pages\n";
143
148
  //#endregion
144
149
  //#region src/templates/reusable/delivery.publish.yml
145
- var delivery_publish_default$1 = "name: Release\n\n# Semantic-release with OIDC Trusted Publishing.\n# actions/setup-node writes a default NODE_AUTH_TOKEN=${{ github.token }}\n# which shadows OIDC auth. We explicitly clear it so npm falls through to\n# the Trusted Publisher OIDC exchange.\n# The calling repo must have a .releaserc.json that configures branches,\n# plugins, and any publish options. npm@11+ is installed to support OIDC.\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n dry-run:\n description: >\n When true, runs semantic-release --dry-run: analyzes commits and\n previews the next release without git writes or publish. Only\n meaningful for workflow_dispatch triggers; push-triggered runs\n always run fully.\n type: boolean\n required: false\n default: false\n post-release:\n description: >\n When true, dispatches a readme sync broadcast after a successful\n release. Enable for packages consumed by other repos via the\n registry-doc system so downstream README installation blocks\n stay current.\n type: boolean\n required: false\n default: false\n run-build:\n description: Run `pnpm build` before releasing\n type: boolean\n required: false\n default: true\n deploy-on-release:\n description: >\n When true, runs a separate `deploy` job after a successful release\n (holocron#930): `holocron deploy-on-release` deploys every workspace\n package whose `delivery.deploy` task is `with: { on: release }`, when\n the release is on its channel and changes its paths. The job is its\n own check, re-runnable on its own, and gets VERCEL_TOKEN; the release\n job never sees it. Off by default, so a repo that doesn't deploy from\n its release never exposes the token.\n type: boolean\n required: false\n default: false\n sentry-project:\n description: >\n Sentry project slug for sourcemap upload and release creation after\n publishing. Omit to skip the Sentry release step entirely.\n type: string\n required: false\n default: \"\"\n secrets:\n HOLOCRON_RELEASE_TOKEN:\n description: >\n Fine-grained PAT (Contents + Issues + Pull requests: write) owned by\n an admin. Required when the default branch is protected by a ruleset —\n github.token cannot push through rulesets, but an admin PAT can.\n Takes priority over HOLOCRON_SYNC_TOKEN. Falls back to github.token.\n required: false\n HOLOCRON_SYNC_TOKEN:\n description: >\n Legacy alias for HOLOCRON_RELEASE_TOKEN — kept for backward compatibility.\n Prefer HOLOCRON_RELEASE_TOKEN for new repos.\n required: false\n HOLOCRON_READ_TOKEN:\n description: >\n Fine-grained PAT for read-only GitHub API calls (e.g. resolving git\n committer identity via `gh api user`). Falls back to github.token.\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for `gh` CLI calls. Used when\n HOLOCRON_READ_TOKEN is not set.\n required: false\n SENTRY_AUTH_TOKEN:\n description: >\n Sentry auth token for sourcemap upload and release creation.\n Required when sentry-project is set. Use the org-level secret.\n required: false\n TURBO_TOKEN:\n required: false\n VERCEL_TOKEN:\n description: >\n Vercel token for the deploy job. Only used when deploy-on-release is\n true, and only by that job.\n required: false\n\njobs:\n release:\n name: Semantic release\n permissions:\n contents: write\n id-token: write\n issues: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 30\n outputs:\n # Read by the deploy job (holocron#930). Empty unless semantic-release\n # published: `commit` is the release commit, `previous` the commit of\n # the release before it (to diff against), `channel` the new version's\n # prerelease identifier (`alpha`), empty for a stable release (`main`).\n commit: ${{ steps.release.outputs.commit }}\n previous: ${{ steps.release.outputs.previous }}\n channel: ${{ steps.release.outputs.channel }}\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n # Do not cancel in-progress releases — a partial release is worse than a slow one.\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n fetch-depth: 0\n persist-credentials: false\n # Use HOLOCRON_RELEASE_TOKEN when available — git push (tags, release commits)\n # uses the checkout credential, not GITHUB_TOKEN env var. The\n # built-in github.token cannot push through branch protection rulesets.\n token: ${{ secrets.HOLOCRON_RELEASE_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || github.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Configure git identity\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n git config --global user.name \"$GIT_NAME\"\n git config --global user.email \"$GIT_EMAIL\"\n git config --global format.signoff true\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - name: Upgrade npm for OIDC support\n run: npm install -g npm@11 sigstore\n # sigstore is required by libnpmpublish/provenance.js at module parse\n # time — before any config takes effect. Some npm 11.x builds stopped\n # bundling it; installing it globally into the same prefix ensures it\n # resolves regardless of npm version. (Discovered 2026-07-09.)\n\n - run: pnpm build\n name: Build\n if: ${{ inputs.run-build == true }}\n\n - name: Release\n id: release\n run: |\n BEFORE=$(git rev-parse HEAD)\n PREVIOUS_TAG=$(git describe --tags --abbrev=0 2>/dev/null || true)\n PREVIOUS=\"\"\n if [ -n \"$PREVIOUS_TAG\" ]; then PREVIOUS=$(git rev-list -n 1 \"$PREVIOUS_TAG\"); fi\n if [ \"$DRY_RUN\" = \"true\" ]; then\n npx semantic-release --dry-run\n else\n npx semantic-release\n fi\n AFTER=$(git rev-parse HEAD)\n # semantic-release only commits (`chore(release): … [skip ci]`) when it\n # actually publishes. That commit gets no CI (and so no coverage\n # upload), which makes the next PR's `codecov/project` compare a full\n # report against a stale ancestor — a phantom drop (holocron#644).\n # Emit the new SHA so the steps below upload coverage for it.\n if [ \"$BEFORE\" != \"$AFTER\" ]; then\n echo \"commit=$AFTER\" >> \"$GITHUB_OUTPUT\"\n echo \"previous=$PREVIOUS\" >> \"$GITHUB_OUTPUT\"\n # The new version's channel: the prerelease identifier of its tag\n # (v5.0.0-alpha.108 -> alpha), empty for a stable release.\n VERSION=$(git describe --tags --abbrev=0)\n VERSION=${VERSION#v}\n CHANNEL=\"\"\n case \"$VERSION\" in *-*) PRE=${VERSION#*-}; CHANNEL=${PRE%%.*} ;; esac\n echo \"channel=$CHANNEL\" >> \"$GITHUB_OUTPUT\"\n fi\n env:\n DRY_RUN: ${{ inputs.dry-run }}\n # Prefer HOLOCRON_RELEASE_TOKEN (fine-grained PAT, Contents+Issues+PRs write,\n # owned by an admin with ruleset bypass) so @semantic-release/git can\n # push the version-bump commit through branch protection. Falls back to\n # HOLOCRON_SYNC_TOKEN (legacy) then github.token for unprotected repos.\n GITHUB_TOKEN: ${{ secrets.HOLOCRON_RELEASE_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || github.token }}\n HUSKY: \"0\"\n NPM_CONFIG_PROVENANCE: true\n\n - uses: theholocron/.github/.github/actions/holocron@main\n name: Coverage for the release commit\n if: ${{ steps.release.outputs.commit != '' }}\n with:\n task: verification.unitTests\n\n - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0\n name: Upload release-commit coverage to Codecov\n if: ${{ steps.release.outputs.commit != '' }}\n # fail_ci_if_error makes a failed upload fail this step, so it is visible, but\n # continue-on-error keeps it from failing the job: the release has already\n # published, and the Sentry release steps below must still run (holocron#934).\n continue-on-error: true\n with:\n use_oidc: true\n fail_ci_if_error: true\n override_commit: ${{ steps.release.outputs.commit }}\n override_branch: ${{ github.ref_name }}\n\n - name: Get release version\n id: release_version\n if: ${{ inputs.sentry-project != '' && inputs.dry-run != true }}\n env:\n SENTRY_PROJECT: ${{ inputs.sentry-project }}\n run: |\n TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo \"\")\n if [ -n \"$TAG\" ]; then\n echo \"release=${SENTRY_PROJECT}@${TAG#v}\" >> \"$GITHUB_OUTPUT\"\n fi\n\n - name: Create Sentry release\n if: ${{ inputs.sentry-project != '' && steps.release_version.outputs.release != '' && inputs.dry-run != true }}\n uses: getsentry/action-release@ff07929a6537bac57790c3451cf4d364aca38528 # v3\n env:\n SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}\n SENTRY_ORG: theholocron\n SENTRY_PROJECT: ${{ inputs.sentry-project }}\n with:\n environment: production\n version: ${{ steps.release_version.outputs.release }}\n sourcemaps: \"**/dist\"\n\n deploy:\n name: Deploy\n needs: release\n # Only after a release that actually published (`commit` is empty on a dry\n # run or when nothing was released). A failed deploy fails only this job:\n # the release is already on npm, and this job re-runs on its own.\n if: ${{ inputs.deploy-on-release == true && inputs.dry-run != true && needs.release.outputs.commit != '' }}\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 30\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout the release commit\n with:\n ref: ${{ needs.release.outputs.commit }}\n fetch-depth: 0\n persist-credentials: false\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - uses: theholocron/.github/.github/actions/holocron@main\n name: Deploy packages that deploy on release\n env:\n VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}\n with:\n command: deploy-on-release\n args: >-\n --channel=${{ needs.release.outputs.channel }}\n --from=${{ needs.release.outputs.previous }}\n --to=${{ needs.release.outputs.commit }}\n\n sync-readme:\n name: Post-release readme sync\n needs: release\n if: ${{ inputs.post-release == true && inputs.dry-run != true }}\n runs-on: ubuntu-latest\n timeout-minutes: 5\n steps:\n - name: Trigger broadcast readme sync\n run: |\n gh workflow run sync-dispatch.yml \\\n --repo theholocron/.github \\\n --field \"steps=readme\"\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN }}\n";
150
+ var delivery_publish_default$1 = "name: Release\n\n# Semantic-release with OIDC Trusted Publishing.\n# actions/setup-node writes a default NODE_AUTH_TOKEN=${{ github.token }}\n# which shadows OIDC auth. We explicitly clear it so npm falls through to\n# the Trusted Publisher OIDC exchange.\n# The calling repo must have a .releaserc.json that configures branches,\n# plugins, and any publish options. npm@11+ is installed to support OIDC.\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n dry-run:\n description: >\n When true, runs semantic-release --dry-run: analyzes commits and\n previews the next release without git writes or publish. Only\n meaningful for workflow_dispatch triggers; push-triggered runs\n always run fully.\n type: boolean\n required: false\n default: false\n post-release:\n description: >\n When true, dispatches a readme sync broadcast after a successful\n release. Enable for packages consumed by other repos via the\n registry-doc system so downstream README installation blocks\n stay current.\n type: boolean\n required: false\n default: false\n run-build:\n description: Run `pnpm build` before releasing\n type: boolean\n required: false\n default: true\n deploy-on-release:\n description: >\n When true, runs a separate `deploy` job after a successful release\n (holocron#930): `holocron deploy on-release` deploys every workspace\n package whose `delivery.deploy` task is `with: { on: release }`, when\n the release is on its channel and changes its paths. The job is its\n own check, re-runnable on its own, and gets VERCEL_TOKEN; the release\n job never sees it. Off by default, so a repo that doesn't deploy from\n its release never exposes the token.\n type: boolean\n required: false\n default: false\n sentry-project:\n description: >\n Sentry project slug for sourcemap upload and release creation after\n publishing. Omit to skip the Sentry release step entirely.\n type: string\n required: false\n default: \"\"\n secrets:\n HOLOCRON_RELEASE_TOKEN:\n description: >\n Fine-grained PAT (Contents + Issues + Pull requests: write) owned by\n an admin. Required when the default branch is protected by a ruleset —\n github.token cannot push through rulesets, but an admin PAT can.\n Takes priority over HOLOCRON_SYNC_TOKEN. Falls back to github.token.\n required: false\n HOLOCRON_SYNC_TOKEN:\n description: >\n Legacy alias for HOLOCRON_RELEASE_TOKEN — kept for backward compatibility.\n Prefer HOLOCRON_RELEASE_TOKEN for new repos.\n required: false\n HOLOCRON_READ_TOKEN:\n description: >\n Fine-grained PAT for read-only GitHub API calls (e.g. resolving git\n committer identity via `gh api user`). Falls back to github.token.\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for `gh` CLI calls. Used when\n HOLOCRON_READ_TOKEN is not set.\n required: false\n SENTRY_AUTH_TOKEN:\n description: >\n Sentry auth token for sourcemap upload and release creation.\n Required when sentry-project is set. Use the org-level secret.\n required: false\n TURBO_TOKEN:\n required: false\n VERCEL_TOKEN:\n description: >\n Vercel token for the deploy job. Only used when deploy-on-release is\n true, and only by that job.\n required: false\n\njobs:\n release:\n name: Semantic release\n permissions:\n contents: write\n id-token: write\n issues: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 30\n outputs:\n # Read by the deploy job (holocron#930). Empty unless semantic-release\n # published: `commit` is the release commit, `previous` the commit of\n # the release before it (to diff against), `channel` the new version's\n # prerelease identifier (`alpha`), empty for a stable release (`main`).\n commit: ${{ steps.release.outputs.commit }}\n previous: ${{ steps.release.outputs.previous }}\n channel: ${{ steps.release.outputs.channel }}\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n # Do not cancel in-progress releases — a partial release is worse than a slow one.\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n fetch-depth: 0\n persist-credentials: false\n # Use HOLOCRON_RELEASE_TOKEN when available — git push (tags, release commits)\n # uses the checkout credential, not GITHUB_TOKEN env var. The\n # built-in github.token cannot push through branch protection rulesets.\n token: ${{ secrets.HOLOCRON_RELEASE_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || github.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Configure git identity\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n git config --global user.name \"$GIT_NAME\"\n git config --global user.email \"$GIT_EMAIL\"\n git config --global format.signoff true\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - name: Upgrade npm for OIDC support\n run: npm install -g npm@11 sigstore\n # sigstore is required by libnpmpublish/provenance.js at module parse\n # time — before any config takes effect. Some npm 11.x builds stopped\n # bundling it; installing it globally into the same prefix ensures it\n # resolves regardless of npm version. (Discovered 2026-07-09.)\n\n - run: pnpm build\n name: Build\n if: ${{ inputs.run-build == true }}\n\n - name: Release\n id: release\n run: |\n BEFORE=$(git rev-parse HEAD)\n PREVIOUS_TAG=$(git describe --tags --abbrev=0 2>/dev/null || true)\n PREVIOUS=\"\"\n if [ -n \"$PREVIOUS_TAG\" ]; then PREVIOUS=$(git rev-list -n 1 \"$PREVIOUS_TAG\"); fi\n if [ \"$DRY_RUN\" = \"true\" ]; then\n npx semantic-release --dry-run\n else\n npx semantic-release\n fi\n AFTER=$(git rev-parse HEAD)\n # semantic-release only commits (`chore(release): … [skip ci]`) when it\n # actually publishes. That commit gets no CI (and so no coverage\n # upload), which makes the next PR's `codecov/project` compare a full\n # report against a stale ancestor — a phantom drop (holocron#644).\n # Emit the new SHA so the steps below upload coverage for it.\n if [ \"$BEFORE\" != \"$AFTER\" ]; then\n echo \"commit=$AFTER\" >> \"$GITHUB_OUTPUT\"\n echo \"previous=$PREVIOUS\" >> \"$GITHUB_OUTPUT\"\n # The new version's channel: the prerelease identifier of its tag\n # (v5.0.0-alpha.108 -> alpha), empty for a stable release.\n VERSION=$(git describe --tags --abbrev=0)\n VERSION=${VERSION#v}\n CHANNEL=\"\"\n case \"$VERSION\" in *-*) PRE=${VERSION#*-}; CHANNEL=${PRE%%.*} ;; esac\n echo \"channel=$CHANNEL\" >> \"$GITHUB_OUTPUT\"\n fi\n env:\n DRY_RUN: ${{ inputs.dry-run }}\n # Prefer HOLOCRON_RELEASE_TOKEN (fine-grained PAT, Contents+Issues+PRs write,\n # owned by an admin with ruleset bypass) so @semantic-release/git can\n # push the version-bump commit through branch protection. Falls back to\n # HOLOCRON_SYNC_TOKEN (legacy) then github.token for unprotected repos.\n GITHUB_TOKEN: ${{ secrets.HOLOCRON_RELEASE_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || github.token }}\n HUSKY: \"0\"\n NPM_CONFIG_PROVENANCE: true\n\n - uses: theholocron/.github/.github/actions/holocron@main\n name: Coverage for the release commit\n if: ${{ steps.release.outputs.commit != '' }}\n with:\n task: verification.unitTests\n\n - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0\n name: Upload release-commit coverage to Codecov\n if: ${{ steps.release.outputs.commit != '' }}\n # fail_ci_if_error makes a failed upload fail this step, so it is visible, but\n # continue-on-error keeps it from failing the job: the release has already\n # published, and the Sentry release steps below must still run (holocron#934).\n continue-on-error: true\n with:\n use_oidc: true\n fail_ci_if_error: true\n override_commit: ${{ steps.release.outputs.commit }}\n override_branch: ${{ github.ref_name }}\n\n - name: Get release version\n id: release_version\n if: ${{ inputs.sentry-project != '' && inputs.dry-run != true }}\n env:\n SENTRY_PROJECT: ${{ inputs.sentry-project }}\n run: |\n TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo \"\")\n if [ -n \"$TAG\" ]; then\n echo \"release=${SENTRY_PROJECT}@${TAG#v}\" >> \"$GITHUB_OUTPUT\"\n fi\n\n - name: Create Sentry release\n if: ${{ inputs.sentry-project != '' && steps.release_version.outputs.release != '' && inputs.dry-run != true }}\n uses: getsentry/action-release@ff07929a6537bac57790c3451cf4d364aca38528 # v3\n env:\n SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}\n SENTRY_ORG: theholocron\n SENTRY_PROJECT: ${{ inputs.sentry-project }}\n with:\n environment: production\n version: ${{ steps.release_version.outputs.release }}\n sourcemaps: \"**/dist\"\n\n deploy:\n name: Deploy\n needs: release\n # Only after a release that actually published (`commit` is empty on a dry\n # run or when nothing was released). A failed deploy fails only this job:\n # the release is already on npm, and this job re-runs on its own.\n if: ${{ inputs.deploy-on-release == true && inputs.dry-run != true && needs.release.outputs.commit != '' }}\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 30\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout the release commit\n with:\n ref: ${{ needs.release.outputs.commit }}\n fetch-depth: 0\n persist-credentials: false\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - uses: theholocron/.github/.github/actions/holocron@main\n name: Deploy packages that deploy on release\n env:\n VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}\n with:\n command: deploy on-release\n args: >-\n --channel=${{ needs.release.outputs.channel }}\n --from=${{ needs.release.outputs.previous }}\n --to=${{ needs.release.outputs.commit }}\n\n sync-readme:\n name: Post-release readme sync\n needs: release\n if: ${{ inputs.post-release == true && inputs.dry-run != true }}\n runs-on: ubuntu-latest\n timeout-minutes: 5\n steps:\n - name: Trigger broadcast readme sync\n run: |\n gh workflow run sync-dispatch.yml \\\n --repo theholocron/.github \\\n --field \"steps=readme\"\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN }}\n";
146
151
  //#endregion
147
152
  //#region src/templates/reusable/dependencies.yml
148
153
  var dependencies_default$1 = "name: Dependencies\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n secrets:\n merge-token:\n description: >\n Optional privileged token for auto-merge. Falls back to GITHUB_TOKEN.\n Required when branch protection enforces required reviews — GITHUB_TOKEN\n cannot approve its own PRs.\n required: false\n\njobs:\n dependabot:\n name: Update the dependencies\n permissions:\n contents: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 5\n if: github.event.pull_request.user.login == 'dependabot[bot]'\n steps:\n - uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0\n name: Fetch Dependabot metadata\n id: metadata\n\n - run: gh pr merge --auto --squash \"$PR_URL\"\n # --squash is intentional: repo protection sets allow_merge_commit: false,\n # so --merge would fail on any repo using the standard preset.\n name: Enable auto-merge for Dependabot PRs\n if: steps.metadata.outputs.update-type == 'version-update:semver-patch'\n env:\n PR_URL: ${{ github.event.pull_request.html_url }}\n GH_TOKEN: ${{ secrets.merge-token || github.token }}\n";
@@ -160,7 +165,7 @@ var platform_commitStandards_default$1 = "name: Commit Standards\n\non: # yamlli
160
165
  var platform_dispatchedCheck_default = "name: Dispatched Check\n\non: # yamllint disable-line rule:truthy\n workflow_dispatch:\n inputs:\n repo:\n description: Target repo, \"owner/name\", to check out and run the task against.\n type: string\n required: true\n ref:\n description: Git ref (branch or commit SHA) to check out.\n type: string\n required: true\n task:\n description: The holocron task name to run (e.g. \"verification.typeSafety\").\n type: string\n required: true\n check-run-id:\n description: >\n ID of the check run already posted as \"queued\" on the target repo —\n patched to \"completed\" once the task finishes.\n type: string\n required: true\n\npermissions:\n contents: read\n\njobs:\n run-task:\n name: Run a Sentinel-dispatched task against another repo\n runs-on: ubuntu-latest\n timeout-minutes: 20\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n # actions/create-github-app-token defaults to scoping its token to the\n # *current* repo (.github, where this workflow runs) when owner/\n # repositories are omitted — useless here, since every real use of this\n # token targets inputs.repo instead. Split \"owner/name\" up front so the\n # token step below can scope explicitly to the actual target.\n - name: Parse target repo\n id: target\n run: |\n echo \"owner=${INPUT_REPO%%/*}\" >> \"$GITHUB_OUTPUT\"\n echo \"name=${INPUT_REPO##*/}\" >> \"$GITHUB_OUTPUT\"\n env:\n INPUT_REPO: ${{ inputs.repo }}\n\n # Sentinel's own dispatch call only carries plain, non-secret inputs\n # (repo/ref/task/check-run-id — all visible in the Actions UI/logs).\n # This step mints a fresh, short-lived installation token here instead,\n # scoped by the same App's stored credentials — never a raw token\n # passed through a dispatch input.\n - name: Generate installation token\n id: app-token\n uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0\n with:\n app-id: ${{ secrets.SENTINEL_APP_ID }}\n private-key: ${{ secrets.SENTINEL_APP_PRIVATE_KEY }}\n owner: ${{ steps.target.outputs.owner }}\n repositories: ${{ steps.target.outputs.name }}\n\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout target repository\n with:\n repository: ${{ inputs.repo }}\n ref: ${{ inputs.ref }}\n token: ${{ steps.app-token.outputs.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Run the task\n id: run-task\n continue-on-error: true\n uses: theholocron/.github/.github/actions/holocron@main\n with:\n task: ${{ inputs.task }}\n\n # A bare .../actions/runs/<id> link lands on the run summary, one click\n # short of the actual step-by-step log a normal check's details_url\n # points at. This job is always alone in its run, so the first (only)\n # job in the run's own job list is unambiguously this one.\n - name: Resolve this job's numeric ID\n id: job-info\n if: always()\n run: |\n job_id=$(gh api \"repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/jobs\" --jq '.jobs[0].id')\n echo \"job_id=$job_id\" >> \"$GITHUB_OUTPUT\"\n env:\n GH_TOKEN: ${{ steps.app-token.outputs.token }}\n\n # Ships the task's real captured output (tsc/vitest/etc — whatever\n # `holocron run` actually printed) to the same Axiom dataset Sentinel's\n # own structured logs already flow into, tagged so it's queryable by\n # this exact run. Reuses the existing dataset rather than provisioning\n # a new one — a prototype-stage call, revisit if CI-log volume ever\n # warrants a dedicated dataset. Builds a permalink filtered to this\n # run's own logs (Axiom's own \"copy query link\" URL shape:\n # /<org>/query?initForm={\"apl\":\"...\"} ) so a viewer lands directly on\n # the relevant lines, not a bare dataset view.\n - name: Ship task output to Axiom\n id: axiom\n if: always()\n run: |\n message=$(tail -c 40000 \"$LOG_FILE\" 2>/dev/null || echo \"(no output captured)\")\n # \"level\" is one of the field names Axiom's Stream/Query tabs\n # recognize for severity-color highlighting (docs: level, @level,\n # severity, @severity, status.code) -- conclusion alone isn't.\n level=$([ \"$CONCLUSION\" = \"success\" ] && echo \"info\" || echo \"error\")\n event=$(jq -cn \\\n --arg time \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\" \\\n --arg repo \"$REPO\" --arg task \"$TASK\" --arg run_id \"$GITHUB_RUN_ID\" \\\n --arg job_id \"$JOB_ID\" --arg check_run_id \"$CHECK_RUN_ID\" \\\n --arg conclusion \"$CONCLUSION\" --arg level \"$level\" --arg message \"$message\" \\\n '{_time: $time, source: \"dispatched-check\", repo: $repo, task: $task,\n run_id: $run_id, job_id: $job_id, check_run_id: $check_run_id,\n conclusion: $conclusion, level: $level, message: $message}')\n curl -sf -X POST \"https://api.axiom.co/v1/datasets/${AXIOM_DATASET}/ingest\" \\\n -H \"Authorization: Bearer ${AXIOM_TOKEN}\" \\\n -H \"Content-Type: application/json\" \\\n -d \"[${event}]\" || echo \"::warning::Axiom ingest failed — continuing, the check itself still reports the real result\"\n\n # The ['...'] is Axiom's own APL array-dataset-reference syntax, not\n # a shell quote boundary — $AXIOM_DATASET/$CHECK_RUN_ID both expand\n # fine here; shellcheck's single-quote heuristic just can't tell.\n # shellcheck disable=SC2016\n apl=\"['${AXIOM_DATASET}'] | where check_run_id == \\\"${CHECK_RUN_ID}\\\"\"\n init_form=$(jq -cn --arg apl \"$apl\" '{apl: $apl}')\n encoded=$(jq -rn --arg s \"$init_form\" '$s | @uri')\n echo \"query-url=https://app.axiom.co/${AXIOM_ORG}/query?initForm=${encoded}\" >> \"$GITHUB_OUTPUT\"\n env:\n LOG_FILE: ${{ steps.run-task.outputs.log-file }}\n REPO: ${{ inputs.repo }}\n TASK: ${{ inputs.task }}\n JOB_ID: ${{ steps.job-info.outputs.job_id }}\n CHECK_RUN_ID: ${{ inputs.check-run-id }}\n CONCLUSION: ${{ steps.run-task.outcome == 'success' && 'success' || 'failure' }}\n AXIOM_ORG: the-holocron-7bbe\n AXIOM_DATASET: holocron-sentinel\n AXIOM_TOKEN: ${{ secrets.SENTINEL_AXIOM_INGEST_TOKEN }}\n\n # Always runs, success or failure — the queued check run on the target\n # repo must be resolved either way, not left hanging. Full JSON body via\n # jq + --input, not -f flags: output.text needs real nesting (gh api -f\n # has no dot-notation for that), and the captured task output can\n # contain characters (quotes, $, backticks) that would break a\n # hand-built -f string.\n - name: Report result to the target repo's check run\n if: always()\n run: |\n excerpt=$(tail -c 3000 \"$LOG_FILE\" 2>/dev/null || echo \"(no output captured)\")\n # The single-quoted format string is intentional — every %s fills\n # via printf's own args below, not shell expansion; nothing in it\n # needs to expand.\n # shellcheck disable=SC2016\n text=$(printf '**Task:** `%s`\\n\\n**Result:** %s\\n\\n[Full logs on Axiom](%s)\\n\\n### Last output\\n\\n```\\n%s\\n```\\n' \\\n \"$TASK\" \"$CONCLUSION\" \"$QUERY_URL\" \"$excerpt\")\n body=$(jq -n \\\n --arg conclusion \"$CONCLUSION\" \\\n --arg details_url \"$RUN_URL\" \\\n --arg title \"$TASK ($CONCLUSION)\" \\\n --arg summary \"Dispatched via theholocron/.github — see the log excerpt below, or the full run/Axiom links.\" \\\n --arg text \"$text\" \\\n '{status: \"completed\", conclusion: $conclusion, details_url: $details_url,\n output: {title: $title, summary: $summary, text: $text}}')\n echo \"$body\" | gh api --method PATCH \"/repos/${REPO}/check-runs/${CHECK_RUN_ID}\" --input -\n env:\n # `GH_TOKEN` is the literal name `gh api` requires to auto-authenticate\n # -- not a stand-in for a shared/blanket credential. Its value is the\n # short-lived, Sentinel-App-scoped token minted above, same as the\n # checkout step uses; never secrets.HOLOCRON_SYNC_TOKEN (the one\n # genuinely shared PAT in this org, used by sync-dispatch.yml).\n GH_TOKEN: ${{ steps.app-token.outputs.token }}\n REPO: ${{ inputs.repo }}\n TASK: ${{ inputs.task }}\n CHECK_RUN_ID: ${{ inputs.check-run-id }}\n CONCLUSION: ${{ steps.run-task.outcome == 'success' && 'success' || 'failure' }}\n LOG_FILE: ${{ steps.run-task.outputs.log-file }}\n QUERY_URL: ${{ steps.axiom.outputs.query-url }}\n RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/job/${{ steps.job-info.outputs.job_id }}\n";
161
166
  //#endregion
162
167
  //#region src/templates/reusable/platform.repoSync.yml
163
- var platform_repoSync_default$1 = "name: Sync\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n steps:\n description: >\n Sync steps to run (default: all). Valid values:\n labels, properties, teams, topics, keywords, description, homepage, readme, workflows, wiki.\n Pass a space-separated list to run a subset, e.g. \"readme\" or \"readme wiki\".\n type: string\n required: false\n secrets:\n HOLOCRON_ADMIN_TOKEN:\n description: Fine-grained PAT with admin scopes (labels, properties, teams).\n required: false\n HOLOCRON_AXIOM_TOKEN:\n description: >\n Axiom API token. When set alongside the HOLOCRON_AXIOM_DATASET\n repo/org variable, the CLI ships this run's structured logs to Axiom.\n Falls back to the vendor-native AXIOM_TOKEN secret.\n required: false\n AXIOM_TOKEN:\n description: Vendor-native fallback for HOLOCRON_AXIOM_TOKEN.\n required: false\n HOLOCRON_DEPLOY_TOKEN:\n description: Fine-grained PAT for GitHub Pages configuration.\n required: false\n HOLOCRON_ISSUES_TOKEN:\n description: Fine-grained PAT for issue management.\n required: false\n HOLOCRON_ORG_TOKEN:\n description: Org-scoped fine-grained PAT for team sync and org properties.\n required: false\n HOLOCRON_READ_TOKEN:\n description: Fine-grained PAT for read-only GitHub API calls.\n required: false\n HOLOCRON_SYNC_TOKEN:\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for gh CLI calls. Used when\n HOLOCRON_SYNC_TOKEN is not set.\n required: false\n\njobs:\n sync:\n name: Run holocron sync\n runs-on: ubuntu-latest\n timeout-minutes: 10\n permissions:\n contents: write\n pull-requests: write\n # Job-level so the `holocron` composite action's steps inherit them.\n env:\n HOLOCRON_ADMIN_TOKEN: ${{ secrets.HOLOCRON_ADMIN_TOKEN }}\n HOLOCRON_AXIOM_TOKEN: ${{ secrets.HOLOCRON_AXIOM_TOKEN || secrets.AXIOM_TOKEN }}\n HOLOCRON_AXIOM_DATASET: ${{ vars.HOLOCRON_AXIOM_DATASET || vars.AXIOM_DATASET }}\n POSTHOG_PROJECT_TOKEN: ${{ vars.POSTHOG_PROJECT_TOKEN }}\n HOLOCRON_DEPLOY_TOKEN: ${{ secrets.HOLOCRON_DEPLOY_TOKEN }}\n HOLOCRON_ISSUES_TOKEN: ${{ secrets.HOLOCRON_ISSUES_TOKEN }}\n HOLOCRON_ORG_TOKEN: ${{ secrets.HOLOCRON_ORG_TOKEN }}\n HOLOCRON_READ_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n token: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Run holocron sync\n # The `holocron` action resolves @theholocron/cli from node_modules (or\n # builds the workspace when it's an unbuilt checkout — the holocron repo\n # itself). `inputs.steps` is a space-separated list or empty; the\n # `--steps <list>` arg is omitted when empty.\n uses: theholocron/.github/.github/actions/holocron@main\n with:\n command: sync\n args: ${{ inputs.steps != '' && format('--steps {0}', inputs.steps) || '' }}\n\n - name: Format generated files\n run: |\n pnpm exec prettier --write README.md docs/src/content/docs/index.mdx 2>/dev/null || true\n # `holocron sync` writes package.json fields (keywords, description,\n # homepage) with a plain assignment, which appends new keys at the\n # end — re-apply the canonical order the lint config enforces.\n pnpm exec eslint --fix --no-warn-ignored package.json 2>/dev/null || true\n\n - uses: theholocron/.github/.github/actions/auto-commit@main\n id: auto-commit\n name: Commit sync changes\n with:\n token: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n branch: chore/auto-sync\n commit-message: \"chore: sync from holocron.config\"\n commit-options: \"--no-verify\"\n\n - name: Open PR if changes were committed\n if: steps.auto-commit.outputs.changes-detected == 'true'\n run: |\n gh pr create \\\n --title \"chore: sync README and repo metadata\" \\\n --body \"Automated sync triggered by changes to config or package files. Merge to apply.\" \\\n --base main \\\n --head chore/auto-sync \\\n || echo \"PR already open — branch updated.\"\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - name: Broadcast wiki sync if navbar changed\n if: >-\n steps.auto-commit.outputs.changes-detected == 'true' &&\n github.event_name == 'push' &&\n (inputs.steps == '' || contains(inputs.steps, 'wiki'))\n run: |\n if git diff HEAD~1 --name-only | grep -q 'fern/docs.yml'; then\n gh workflow run sync-dispatch.yml \\\n --repo theholocron/.github \\\n --field \"steps=wiki\" \\\n || echo \"skipping broadcast — insufficient permissions\"\n fi\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n";
168
+ var platform_repoSync_default$1 = "name: Sync\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n steps:\n description: >\n Sync steps to run (default: all). Valid values:\n labels, properties, teams, topics, keywords, description, homepage, readme, workflows, wiki.\n Pass a space-separated list to run a subset, e.g. \"readme\" or \"readme wiki\".\n type: string\n required: false\n secrets:\n HOLOCRON_ADMIN_TOKEN:\n description: Fine-grained PAT with admin scopes (labels, properties, teams).\n required: false\n HOLOCRON_AXIOM_TOKEN:\n description: >\n Axiom API token. When set alongside the HOLOCRON_AXIOM_DATASET\n repo/org variable, the CLI ships this run's structured logs to Axiom.\n Falls back to the vendor-native AXIOM_TOKEN secret.\n required: false\n AXIOM_TOKEN:\n description: Vendor-native fallback for HOLOCRON_AXIOM_TOKEN.\n required: false\n HOLOCRON_DEPLOY_TOKEN:\n description: Fine-grained PAT for GitHub Pages configuration.\n required: false\n HOLOCRON_ISSUES_TOKEN:\n description: Fine-grained PAT for issue management.\n required: false\n HOLOCRON_ORG_TOKEN:\n description: Org-scoped fine-grained PAT for team sync and org properties.\n required: false\n HOLOCRON_READ_TOKEN:\n description: Fine-grained PAT for read-only GitHub API calls.\n required: false\n HOLOCRON_SYNC_TOKEN:\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for gh CLI calls. Used when\n HOLOCRON_SYNC_TOKEN is not set.\n required: false\n\njobs:\n sync:\n name: Run holocron repo sync\n runs-on: ubuntu-latest\n timeout-minutes: 10\n permissions:\n contents: write\n pull-requests: write\n # Job-level so the `holocron` composite action's steps inherit them.\n env:\n HOLOCRON_ADMIN_TOKEN: ${{ secrets.HOLOCRON_ADMIN_TOKEN }}\n HOLOCRON_AXIOM_TOKEN: ${{ secrets.HOLOCRON_AXIOM_TOKEN || secrets.AXIOM_TOKEN }}\n HOLOCRON_AXIOM_DATASET: ${{ vars.HOLOCRON_AXIOM_DATASET || vars.AXIOM_DATASET }}\n POSTHOG_PROJECT_TOKEN: ${{ vars.POSTHOG_PROJECT_TOKEN }}\n HOLOCRON_DEPLOY_TOKEN: ${{ secrets.HOLOCRON_DEPLOY_TOKEN }}\n HOLOCRON_ISSUES_TOKEN: ${{ secrets.HOLOCRON_ISSUES_TOKEN }}\n HOLOCRON_ORG_TOKEN: ${{ secrets.HOLOCRON_ORG_TOKEN }}\n HOLOCRON_READ_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n token: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Run holocron repo sync\n # The `holocron` action resolves @theholocron/cli from node_modules (or\n # builds the workspace when it's an unbuilt checkout — the holocron repo\n # itself). `inputs.steps` is a space-separated list or empty; the\n # `--steps <list>` arg is omitted when empty.\n uses: theholocron/.github/.github/actions/holocron@main\n with:\n command: repo sync\n args: ${{ inputs.steps != '' && format('--steps {0}', inputs.steps) || '' }}\n\n - name: Format generated files\n run: |\n pnpm exec prettier --write README.md docs/src/content/docs/index.mdx 2>/dev/null || true\n # `holocron repo sync` writes package.json fields (keywords, description,\n # homepage) with a plain assignment, which appends new keys at the\n # end — re-apply the canonical order the lint config enforces.\n pnpm exec eslint --fix --no-warn-ignored package.json 2>/dev/null || true\n\n - uses: theholocron/.github/.github/actions/auto-commit@main\n id: auto-commit\n name: Commit sync changes\n with:\n token: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n branch: chore/auto-sync\n commit-message: \"chore: sync from holocron.config\"\n commit-options: \"--no-verify\"\n\n - name: Open PR if changes were committed\n if: steps.auto-commit.outputs.changes-detected == 'true'\n run: |\n gh pr create \\\n --title \"chore: sync README and repo metadata\" \\\n --body \"Automated sync triggered by changes to config or package files. Merge to apply.\" \\\n --base main \\\n --head chore/auto-sync \\\n || echo \"PR already open — branch updated.\"\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - name: Broadcast wiki sync if navbar changed\n if: >-\n steps.auto-commit.outputs.changes-detected == 'true' &&\n github.event_name == 'push' &&\n (inputs.steps == '' || contains(inputs.steps, 'wiki'))\n run: |\n if git diff HEAD~1 --name-only | grep -q 'fern/docs.yml'; then\n gh workflow run sync-dispatch.yml \\\n --repo theholocron/.github \\\n --field \"steps=wiki\" \\\n || echo \"skipping broadcast — insufficient permissions\"\n fi\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n";
164
169
  //#endregion
165
170
  //#region src/templates/reusable/platform.repoValidation.yml
166
171
  var platform_repoValidation_default$1 = "name: Repo Validation\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n secrets:\n TURBO_TOKEN:\n required: false\n\njobs:\n adrs:\n name: Validate ADRs and specs\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 10\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n fetch-depth: 0\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - uses: theholocron/.github/.github/actions/holocron@main\n name: Validate ADR and spec frontmatter\n with:\n task: platform.repoValidation\n job: adrs\n\n registry:\n name: Validate registry consistency\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 10\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - uses: theholocron/.github/.github/actions/holocron@main\n name: Validate registry consistency\n with:\n task: platform.repoValidation\n job: registry\n\n docs-presence:\n name: Validate docs presence\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 10\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n fetch-depth: 0\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - uses: theholocron/.github/.github/actions/holocron@main\n name: Validate docs presence for new packages\n with:\n task: platform.repoValidation\n job: docsPresence\n env:\n BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}\n\n conclusion:\n name: Conclusion\n runs-on: ubuntu-latest\n if: always()\n needs: [adrs, registry, docs-presence]\n steps:\n - name: Check job statuses\n run: |\n if [[ \"$RESULTS\" == *\"failure\"* ]] || [[ \"$RESULTS\" == *\"cancelled\"* ]]; then\n exit 1\n fi\n env:\n RESULTS: ${{ join(needs.*.result, ',') }}\n";
@@ -196,7 +201,7 @@ var stale_default$1 = "name: Stale\n\non: # yamllint disable-line rule:truthy\n
196
201
  var sync_dispatch_default = "name: Sync Dispatch\n\non: # yamllint disable-line rule:truthy\n workflow_dispatch:\n inputs:\n steps:\n description: >\n Sync steps to pass to each repo's sync.yml. Default is \"readme\"\n (only README marker blocks are updated).\n type: string\n required: false\n default: readme\n\npermissions:\n contents: read\n\njobs:\n broadcast:\n name: Broadcast sync to all repos\n runs-on: ubuntu-latest\n timeout-minutes: 15\n steps:\n - name: Dispatch sync to all repos with sync.yml\n run: |\n gh api /orgs/theholocron/repos --paginate --jq '.[].name' \\\n | while IFS= read -r repo; do\n gh api \"/repos/theholocron/$repo/contents/.github/workflows/sync.yml\" --silent 2>/dev/null || continue\n echo \"Dispatching sync to theholocron/$repo\"\n gh workflow run sync.yml \\\n --repo \"theholocron/$repo\" \\\n --field \"steps=$STEPS\" \\\n || echo \"Warning: could not dispatch to theholocron/$repo — skipping\"\n done\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n STEPS: ${{ inputs.steps }}\n";
197
202
  //#endregion
198
203
  //#region src/templates/reusable/sync-github.yml
199
- var sync_github_default = "name: Sync workflow templates\n\n# Builds the holocron CLI from source and pushes updated workflow templates\n# and composite actions to downstream .github repos. Runs whenever the\n# template source files change on main or alpha.\n#\n# Secrets required:\n# HOLOCRON_SYNC_TOKEN — fine-grained PAT (resource owner: org) with:\n# Actions: Read and write (dispatch workflow runs via gh workflow run)\n# Contents: Read and write (git trees, blobs, refs)\n# Pull requests: Read and write (open sync PR)\n# Workflows: Read and write (write .github/workflows/*.yml)\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n primary-repo:\n description: >\n Primary .github repo — receives composite actions, reusable workflows,\n and thin-caller templates. Requires a PR (branch protection assumed).\n type: string\n required: false\n default: theholocron/.github\n secondary-repos:\n description: >\n Space-separated list of secondary repos (reusable workflows + thin\n callers only, no composite actions). Changes are delivered via pull\n request, same as the primary repo.\n type: string\n required: false\n default: \"\"\n sync-branch:\n description: Branch name used for the primary and secondary repo PRs\n type: string\n required: false\n default: chore/sync-templates\n secrets:\n HOLOCRON_SYNC_TOKEN:\n required: true\n HOLOCRON_READ_TOKEN:\n description: >\n Fine-grained PAT for read-only GitHub API calls (e.g. resolving git\n committer identity via `gh api user`). Falls back to HOLOCRON_SYNC_TOKEN.\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for `gh` CLI calls. Used when neither\n HOLOCRON_READ_TOKEN nor HOLOCRON_SYNC_TOKEN is set.\n required: false\n HOLOCRON_AXIOM_TOKEN:\n description: >\n Axiom API token. When set alongside the HOLOCRON_AXIOM_DATASET\n repo/org variable, the CLI ships this run's structured logs to Axiom.\n Falls back to the vendor-native AXIOM_TOKEN secret.\n required: false\n AXIOM_TOKEN:\n description: Vendor-native fallback for HOLOCRON_AXIOM_TOKEN.\n required: false\n TURBO_TOKEN:\n required: false\n\njobs:\n sync:\n name: Sync templates\n runs-on: ubuntu-latest\n timeout-minutes: 15\n permissions:\n contents: read\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n HOLOCRON_AXIOM_TOKEN: ${{ secrets.HOLOCRON_AXIOM_TOKEN || secrets.AXIOM_TOKEN }}\n HOLOCRON_AXIOM_DATASET: ${{ vars.HOLOCRON_AXIOM_DATASET || vars.AXIOM_DATASET }}\n POSTHOG_PROJECT_TOKEN: ${{ vars.POSTHOG_PROJECT_TOKEN }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm build\n name: Build CLI\n\n - name: Cache actionlint\n id: cache-actionlint\n uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0\n with:\n path: /tmp/actionlint\n key: actionlint-v1.7.7-linux-amd64\n\n - name: Download actionlint\n if: steps.cache-actionlint.outputs.cache-hit != 'true'\n run: |\n curl -fsSL https://github.com/rhysd/actionlint/releases/download/v1.7.7/actionlint_1.7.7_linux_amd64.tar.gz \\\n | tar -xz -C /tmp actionlint\n\n - name: Validate generated workflows\n run: |\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$PRIMARY_REPO\" \\\n --output-dir /tmp/sync-validate\n /tmp/actionlint /tmp/sync-validate/.github/workflows/*.yml\n env:\n PRIMARY_REPO: ${{ inputs.primary-repo }}\n\n - name: Sync primary repo (PR)\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n COMMIT_MSG=\"chore: sync from theholocron/holocron\"$'\\n\\n'\"Signed-off-by: $GIT_NAME <$GIT_EMAIL>\"\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$PRIMARY_REPO\" \\\n --branch \"$SYNC_BRANCH\" \\\n --pr \\\n --message \"$COMMIT_MSG\"\n GH_TOKEN=\"$HOLOCRON_SYNC_TOKEN\" gh pr merge --auto --squash \\\n --repo \"$PRIMARY_REPO\" \"$SYNC_BRANCH\" 2>/dev/null || true\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n PRIMARY_REPO: ${{ inputs.primary-repo }}\n SYNC_BRANCH: ${{ inputs.sync-branch }}\n\n - name: Sync secondary repos (PR)\n if: ${{ inputs.secondary-repos != '' }}\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n COMMIT_MSG=\"chore: sync from theholocron/holocron\"$'\\n\\n'\"Signed-off-by: $GIT_NAME <$GIT_EMAIL>\"\n for repo in $SECONDARY_REPOS; do\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$repo\" \\\n --branch \"$SYNC_BRANCH\" \\\n --pr \\\n --message \"$COMMIT_MSG\"\n GH_TOKEN=\"$HOLOCRON_SYNC_TOKEN\" gh pr merge --auto --squash \\\n --repo \"$repo\" \"$SYNC_BRANCH\" 2>/dev/null || true\n done\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n SECONDARY_REPOS: ${{ inputs.secondary-repos }}\n SYNC_BRANCH: ${{ inputs.sync-branch }}\n";
204
+ var sync_github_default = "name: Sync workflow templates\n\n# Builds the holocron CLI from source and pushes updated workflow templates\n# and composite actions to downstream .github repos. Runs whenever the\n# template source files change on main or alpha.\n#\n# Secrets required:\n# HOLOCRON_SYNC_TOKEN — fine-grained PAT (resource owner: org) with:\n# Actions: Read and write (dispatch workflow runs via gh workflow run)\n# Contents: Read and write (git trees, blobs, refs)\n# Pull requests: Read and write (open sync PR)\n# Workflows: Read and write (write .github/workflows/*.yml)\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n primary-repo:\n description: >\n Primary .github repo — receives composite actions, reusable workflows,\n and thin-caller templates. Requires a PR (branch protection assumed).\n type: string\n required: false\n default: theholocron/.github\n secondary-repos:\n description: >\n Space-separated list of secondary repos (reusable workflows + thin\n callers only, no composite actions). Changes are delivered via pull\n request, same as the primary repo.\n type: string\n required: false\n default: \"\"\n sync-branch:\n description: Branch name used for the primary and secondary repo PRs\n type: string\n required: false\n default: chore/sync-templates\n secrets:\n HOLOCRON_SYNC_TOKEN:\n required: true\n HOLOCRON_READ_TOKEN:\n description: >\n Fine-grained PAT for read-only GitHub API calls (e.g. resolving git\n committer identity via `gh api user`). Falls back to HOLOCRON_SYNC_TOKEN.\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for `gh` CLI calls. Used when neither\n HOLOCRON_READ_TOKEN nor HOLOCRON_SYNC_TOKEN is set.\n required: false\n HOLOCRON_AXIOM_TOKEN:\n description: >\n Axiom API token. When set alongside the HOLOCRON_AXIOM_DATASET\n repo/org variable, the CLI ships this run's structured logs to Axiom.\n Falls back to the vendor-native AXIOM_TOKEN secret.\n required: false\n AXIOM_TOKEN:\n description: Vendor-native fallback for HOLOCRON_AXIOM_TOKEN.\n required: false\n TURBO_TOKEN:\n required: false\n\njobs:\n sync:\n name: Sync templates\n runs-on: ubuntu-latest\n timeout-minutes: 15\n permissions:\n contents: read\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n HOLOCRON_AXIOM_TOKEN: ${{ secrets.HOLOCRON_AXIOM_TOKEN || secrets.AXIOM_TOKEN }}\n HOLOCRON_AXIOM_DATASET: ${{ vars.HOLOCRON_AXIOM_DATASET || vars.AXIOM_DATASET }}\n POSTHOG_PROJECT_TOKEN: ${{ vars.POSTHOG_PROJECT_TOKEN }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm build\n name: Build CLI\n\n - name: Cache actionlint\n id: cache-actionlint\n uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0\n with:\n path: /tmp/actionlint\n key: actionlint-v1.7.7-linux-amd64\n\n - name: Download actionlint\n if: steps.cache-actionlint.outputs.cache-hit != 'true'\n run: |\n curl -fsSL https://github.com/rhysd/actionlint/releases/download/v1.7.7/actionlint_1.7.7_linux_amd64.tar.gz \\\n | tar -xz -C /tmp actionlint\n\n - name: Validate generated workflows\n run: |\n node packages/cli/dist/cli.mjs sync github \\\n --repo \"$PRIMARY_REPO\" \\\n --output-dir /tmp/sync-validate\n /tmp/actionlint /tmp/sync-validate/.github/workflows/*.yml\n env:\n PRIMARY_REPO: ${{ inputs.primary-repo }}\n\n - name: Sync primary repo (PR)\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n COMMIT_MSG=\"chore: sync from theholocron/holocron\"$'\\n\\n'\"Signed-off-by: $GIT_NAME <$GIT_EMAIL>\"\n node packages/cli/dist/cli.mjs sync github \\\n --repo \"$PRIMARY_REPO\" \\\n --branch \"$SYNC_BRANCH\" \\\n --pr \\\n --message \"$COMMIT_MSG\"\n GH_TOKEN=\"$HOLOCRON_SYNC_TOKEN\" gh pr merge --auto --squash \\\n --repo \"$PRIMARY_REPO\" \"$SYNC_BRANCH\" 2>/dev/null || true\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n PRIMARY_REPO: ${{ inputs.primary-repo }}\n SYNC_BRANCH: ${{ inputs.sync-branch }}\n\n - name: Sync secondary repos (PR)\n if: ${{ inputs.secondary-repos != '' }}\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n COMMIT_MSG=\"chore: sync from theholocron/holocron\"$'\\n\\n'\"Signed-off-by: $GIT_NAME <$GIT_EMAIL>\"\n for repo in $SECONDARY_REPOS; do\n node packages/cli/dist/cli.mjs sync github \\\n --repo \"$repo\" \\\n --branch \"$SYNC_BRANCH\" \\\n --pr \\\n --message \"$COMMIT_MSG\"\n GH_TOKEN=\"$HOLOCRON_SYNC_TOKEN\" gh pr merge --auto --squash \\\n --repo \"$repo\" \"$SYNC_BRANCH\" 2>/dev/null || true\n done\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n SECONDARY_REPOS: ${{ inputs.secondary-repos }}\n SYNC_BRANCH: ${{ inputs.sync-branch }}\n";
200
205
  //#endregion
201
206
  //#region src/templates/reusable/tag.yml
202
207
  var tag_default = "name: Tag\n\n# Release Please — fully automated tag and GitHub Release from Conventional Commits.\n# No package.json or npm publishing required. Operates in \"simple\" mode by default:\n# analyzes commits since the last tag, maintains a rolling Release PR, and creates\n# a tag + GitHub Release when that PR is merged.\n#\n# The calling repo must have two files at the root:\n# release-please-config.json — declares packages and release-type\n# .release-please-manifest.json — tracks the current version\n\non: # yamllint disable-line rule:truthy\n # Self-trigger: when this workflow lives in theholocron/.github itself,\n # push to main runs Release Please for that repo's own releases.\n push:\n branches:\n - main\n workflow_call:\n inputs:\n release-type:\n description: Release Please release type (simple, node, python, etc.)\n type: string\n required: false\n default: simple\n config-file:\n description: Path to release-please-config.json\n type: string\n required: false\n default: release-please-config.json\n manifest-file:\n description: Path to .release-please-manifest.json\n type: string\n required: false\n default: .release-please-manifest.json\n\njobs:\n tag:\n name: Tag release\n permissions:\n contents: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 10\n steps:\n - uses: google-github-actions/release-please-action@e4dc86ba9405554aeba3c6bb2d169500e7d3b4ee # v4.1.1\n name: Run Release Please\n with:\n release-type: ${{ inputs.release-type }}\n config-file: ${{ inputs.config-file }}\n manifest-file: ${{ inputs.manifest-file }}\n";
@@ -216,7 +221,7 @@ var verification_unitTests_default$1 = "name: Test\n\non: # yamllint disable-lin
216
221
  *
217
222
  * `WORKFLOW_TEMPLATES` holds each reusable `.github/workflows/<name>.yml`
218
223
  * (synced to `theholocron/.github`); `generateThinCallerContent` wraps one
219
- * into the thin caller `holocron setup` / `holocron sync` write locally.
224
+ * into the thin caller `holocron repo setup` / `holocron repo sync` write locally.
220
225
  */
221
226
  const WORKFLOW_TEMPLATES = {
222
227
  "verification.unitTests": "name: Verification\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main, alpha]\n pull_request:\n\nconcurrency:\n group: test-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: read\n id-token: write\n statuses: write\n\njobs:\n test:\n name: Test\n uses: theholocron/.github/.github/workflows/verification.unitTests.yml@main\n with:\n run-unit: true\n secrets: inherit\n",
@@ -436,7 +441,7 @@ function generateCombinedDeployContent(deployWith, paths, preview) {
436
441
  * - run-chromatic object → run-chromatic: true + chromatic-projects
437
442
  * - plain arrays → JSON-stringified for YAML scalar quoting
438
443
  *
439
- * Used by both `holocron setup` and `sync-workflow-templates`.
444
+ * Used by both `holocron repo setup` and `sync-workflow-templates`.
440
445
  */
441
446
  function normalizeWorkflowWith(raw) {
442
447
  const result = { ...raw };
@@ -469,7 +474,7 @@ function normalizeWorkflowWith(raw) {
469
474
  }
470
475
  /**
471
476
  * Derive on.push.paths entries from the deploy with: shorthand.
472
- * Used by both `holocron setup` and `sync-workflow-templates`.
477
+ * Used by both `holocron repo setup` and `sync-workflow-templates`.
473
478
  */
474
479
  function deriveDeployPaths(raw) {
475
480
  const paths = [];
@@ -497,7 +502,7 @@ function deriveDeployPaths(raw) {
497
502
  //#region src/generators/github-action-reusable-workflows.ts
498
503
  /**
499
504
  * The **reusable** GitHub Actions surface pushed to `theholocron/.github` by
500
- * `holocron sync-github` — the `workflow_call` implementations and composite
505
+ * `holocron sync github` — the `workflow_call` implementations and composite
501
506
  * actions that every repo's thin callers delegate to.
502
507
  *
503
508
  * `theholocron/.github` is a **pure sync target**: `.github/workflows/*`,
@@ -557,19 +562,19 @@ const SOURCE = "packages/astromech/src/generators/github-action-reusable-workflo
557
562
  * "AUTO-GENERATED — do not edit" header for the YAML pushed to
558
563
  * `theholocron/.github`. Matches `createHeader().workflowHeader({ forPrimary: true })`
559
564
  * field-for-field, minus any timestamp — a live `Synced:` line makes the content
560
- * hash change on every run and defeats `sync-github`'s unchanged-file skip.
565
+ * hash change on every run and defeats `sync github`'s unchanged-file skip.
561
566
  */
562
567
  function reusableHeader() {
563
568
  return [
564
569
  `# AUTO-GENERATED — do not edit in theholocron/.github directly.`,
565
570
  `# Source: theholocron/holocron · ${SOURCE}`,
566
- `# Tool: holocron sync-github`,
571
+ `# Tool: holocron sync github`,
567
572
  `# Changes: edit source in theholocron/holocron`,
568
573
  ``
569
574
  ].join("\n");
570
575
  }
571
576
  /**
572
- * The complete file batch `holocron sync-github` pushes to `theholocron/.github`:
577
+ * The complete file batch `holocron sync github` pushes to `theholocron/.github`:
573
578
  * path → content. YAML gets the "do not edit" header; the starter-workflow
574
579
  * `.properties.json` files are left bare (native JSON, not a commented file).
575
580
  */
@@ -783,7 +788,7 @@ const CI_ORDER = [
783
788
  * {@link WORKFLOW_CHECK_CONTEXTS} entry; `config.extraRequiredChecks` adds
784
789
  * contexts not backed by a task (codecov, DCO is prepended by the caller).
785
790
  *
786
- * `@theholocron/cli`'s `holocron setup` calls this instead of the old
791
+ * `@theholocron/cli`'s `holocron repo setup` calls this instead of the old
787
792
  * hand-maintained `repo.requiredChecks` array. Policy-free — it only knows the
788
793
  * manifest.
789
794
  */
@@ -1761,6 +1766,65 @@ function taskName(item) {
1761
1766
  return typeof item === "string" ? item : item.name;
1762
1767
  }
1763
1768
  //#endregion
1769
+ //#region src/tasks/group.ts
1770
+ /**
1771
+ * `holocron run <namespace>` — run every configured task under one
1772
+ * namespace prefix (`sourceQuality.*`, `verification.*`, …) in sequence.
1773
+ * `Astromech.run()` falls back here whenever the given name isn't an exact
1774
+ * `TASKS` entry but matches the prefix of one or more configured tasks —
1775
+ * same "aggregate several real tasks into one report" shape `runCi` already
1776
+ * established, scoped to one namespace instead of the merge-gating set.
1777
+ *
1778
+ * Every task in the namespace always runs — one task's failure never skips
1779
+ * the rest, same as `runCi`'s own loop — so a single invocation surfaces
1780
+ * every problem in the namespace at once instead of stopping at the first.
1781
+ */
1782
+ /** Every configured task whose name starts with `"<namespace>."`, in manifest declaration order. */
1783
+ function matchNamespace(config, namespace) {
1784
+ const prefix = `${namespace}.`;
1785
+ return (config.tasks ?? []).map(normalizeTaskEntry).reduce((names, entry) => {
1786
+ if (entry.name.startsWith(prefix) && !names.includes(entry.name)) names.push(entry.name);
1787
+ return names;
1788
+ }, []);
1789
+ }
1790
+ function runGroup(input) {
1791
+ const { print, namespace } = input;
1792
+ const names = matchNamespace(input.config, namespace);
1793
+ if (names.length === 0) return {
1794
+ status: "unknown",
1795
+ jobs: []
1796
+ };
1797
+ print(`holocron run ${namespace} — ${names.length} task(s)`);
1798
+ print("");
1799
+ const jobs = [];
1800
+ for (const name of names) {
1801
+ print(`▶ ${name}`);
1802
+ const r = runTask({
1803
+ print: (line) => print(` ${line}`),
1804
+ logger: input.logger,
1805
+ exec: input.exec,
1806
+ readFile: input.readFile,
1807
+ fileExists: input.fileExists,
1808
+ listDir: input.listDir,
1809
+ lookPath: input.lookPath,
1810
+ task: name,
1811
+ cwd: input.cwd,
1812
+ dryRun: input.dryRun ?? false,
1813
+ ...input.filter ? { filter: input.filter } : {}
1814
+ });
1815
+ jobs.push({
1816
+ task: name,
1817
+ status: r.status,
1818
+ command: r.command,
1819
+ message: r.message
1820
+ });
1821
+ }
1822
+ return {
1823
+ status: jobs.some((j) => j.status === "fail") ? "fail" : jobs.every((j) => j.status === "dry-run") ? "dry-run" : "ok",
1824
+ jobs
1825
+ };
1826
+ }
1827
+ //#endregion
1764
1828
  //#region src/astromech.ts
1765
1829
  /**
1766
1830
  * `createAstromech(options)` — the self-contained task runner.
@@ -1795,17 +1859,46 @@ function createAstromech(options) {
1795
1859
  lookPath: options.lookPath ?? realLookPath
1796
1860
  };
1797
1861
  const items = () => (options.config?.tasks ?? []).map((i) => normalizeTaskEntry(i));
1862
+ /**
1863
+ * Task names this repo's manifest can actually run locally — shared by
1864
+ * {@link packageScripts} and by `holocron`'s own interactive task picker.
1865
+ * Deliberately independent of `syncScripts`/`holocronScript`/`hooks`:
1866
+ * those govern whether/how `package.json` scripts get *written*, not
1867
+ * which tasks exist to run. A repo with `syncScripts: false` (this repo
1868
+ * itself, among others) still has real runnable tasks — found live when
1869
+ * `packageScripts()`'s `{}` short-circuit silently emptied the picker too.
1870
+ */
1871
+ const runnableTaskNames = () => {
1872
+ const out = [];
1873
+ for (const entry of items()) {
1874
+ const def = TASKS[entry.name];
1875
+ const hasNoLocalRunner = def?.local === null && !def.linterGroup && !def.jobs;
1876
+ if (entry.local === false || !KNOWN_TASKS.has(entry.name) || hasNoLocalRunner) continue;
1877
+ out.push(entry.name);
1878
+ }
1879
+ return out;
1880
+ };
1798
1881
  return {
1799
- run: (task, opts = {}) => runTask({
1800
- ...deps,
1801
- task,
1802
- cwd: options.cwd,
1803
- ...opts.job !== void 0 ? { job: opts.job } : {},
1804
- passthrough: opts.passthrough ?? [],
1805
- dryRun: opts.dryRun ?? false,
1806
- required: opts.required ?? false,
1807
- ...opts.filter ? { filter: opts.filter } : {}
1808
- }),
1882
+ run: (task, opts = {}) => {
1883
+ if (!TASKS[task] && options.config && matchNamespace(options.config, task).length > 0) return runGroup({
1884
+ ...deps,
1885
+ cwd: options.cwd,
1886
+ config: options.config,
1887
+ namespace: task,
1888
+ dryRun: opts.dryRun ?? false,
1889
+ ...opts.filter ? { filter: opts.filter } : {}
1890
+ });
1891
+ return runTask({
1892
+ ...deps,
1893
+ task,
1894
+ cwd: options.cwd,
1895
+ ...opts.job !== void 0 ? { job: opts.job } : {},
1896
+ passthrough: opts.passthrough ?? [],
1897
+ dryRun: opts.dryRun ?? false,
1898
+ required: opts.required ?? false,
1899
+ ...opts.filter ? { filter: opts.filter } : {}
1900
+ });
1901
+ },
1809
1902
  ci: (opts = {}) => runCi({
1810
1903
  ...deps,
1811
1904
  cwd: options.cwd,
@@ -1850,16 +1943,12 @@ function createAstromech(options) {
1850
1943
  const out = {};
1851
1944
  if (!options.config || options.config.syncScripts === false) return out;
1852
1945
  out.holocron = options.config.holocronScript ?? "holocron";
1853
- for (const entry of items()) {
1854
- const def = TASKS[entry.name];
1855
- const hasNoLocalRunner = def?.local === null && !def.linterGroup && !def.jobs;
1856
- if (entry.local === false || !KNOWN_TASKS.has(entry.name) || hasNoLocalRunner) continue;
1857
- out[entry.name] = `holocron run ${entry.name} --`;
1858
- }
1946
+ for (const name of runnableTaskNames()) out[name] = `holocron run ${name} --`;
1859
1947
  const hooks = options.config.hooks;
1860
1948
  if (hooks === true || typeof hooks === "object" && hooks.prePush !== false) out.prepare = "husky";
1861
1949
  return out;
1862
1950
  },
1951
+ runnableTasks: () => runnableTaskNames(),
1863
1952
  reusableTemplates: () => reusableTemplates(),
1864
1953
  requiredChecks: () => requiredChecks(options.config ?? {}),
1865
1954
  codecovConfig: (existing) => codecovConfig(options.cwd, existing),
@@ -1913,7 +2002,7 @@ function createTsconfig(options) {
1913
2002
  * `channel` defaults to `main` (a stable release); set a prerelease identifier
1914
2003
  * such as `alpha` to deploy those releases instead.
1915
2004
  *
1916
- * The shared `delivery.publish` workflow runs this (`holocron deploy-on-release`)
2005
+ * The shared `delivery.publish` workflow runs this (`holocron deploy on-release`)
1917
2006
  * as its own `deploy` job after the release job, so a deploy is a separate,
1918
2007
  * re-runnable check rather than a step buried in the release log. Each package
1919
2008
  * with such a task deploys when the release is on its `channel` and changes a file under its paths: the package itself plus its
@@ -1935,16 +2024,20 @@ const DEPLOY_TASK = "delivery.deploy";
1935
2024
  /** How long to wait for npm to serve the release's versions, and how often to ask. */
1936
2025
  const WAIT_TIMEOUT_MS = 3e5;
1937
2026
  const WAIT_INTERVAL_MS = 1e4;
1938
- /** Every package under `<repoRoot>/packages/*` with a readable, named `package.json`. */
1939
- function workspacePackages(repoRoot, { readJson, listDirs }) {
1940
- const packagesDir = join(repoRoot, "packages");
1941
- return listDirs(packagesDir).flatMap((folder) => {
2027
+ function scanWorkspaceDir(dirPath, { readJson, listDirs }) {
2028
+ let folders;
2029
+ try {
2030
+ folders = listDirs(dirPath);
2031
+ } catch {
2032
+ return [];
2033
+ }
2034
+ return folders.flatMap((folder) => {
1942
2035
  try {
1943
- const manifest = readJson(join(packagesDir, folder, "package.json"));
2036
+ const manifest = readJson(join(dirPath, folder, "package.json"));
1944
2037
  if (!manifest.name) return [];
1945
2038
  return [{
1946
2039
  name: manifest.name,
1947
- dir: join(packagesDir, folder),
2040
+ dir: join(dirPath, folder),
1948
2041
  version: manifest.version,
1949
2042
  dependencies: manifest.dependencies ?? {}
1950
2043
  }];
@@ -1953,6 +2046,14 @@ function workspacePackages(repoRoot, { readJson, listDirs }) {
1953
2046
  }
1954
2047
  });
1955
2048
  }
2049
+ /**
2050
+ * Every package under `<repoRoot>/packages/*` and `<repoRoot>/plugins/*`
2051
+ * with a readable, named `package.json` — `holocron`'s own layout splits
2052
+ * vendor plugin packages into `plugins/*`, sibling to `packages/*`.
2053
+ */
2054
+ function workspacePackages(repoRoot, tree) {
2055
+ return [...scanWorkspaceDir(join(repoRoot, "packages"), tree), ...scanWorkspaceDir(join(repoRoot, "plugins"), tree)];
2056
+ }
1956
2057
  /** The `workspace:*` dependencies of `pkg`, as workspace packages (with their current version). */
1957
2058
  function workspaceDependencies(pkg, all) {
1958
2059
  const names = new Set(Object.entries(pkg.dependencies).filter(([, spec]) => String(spec).startsWith("workspace:")).map(([name]) => name));
@@ -2149,4 +2250,4 @@ async function deployOnRelease(options, { run = defaultRun, readJson = defaultRe
2149
2250
  };
2150
2251
  }
2151
2252
  //#endregion
2152
- export { CI_ORDER, KNOWN_TASKS, KNOWN_WORKFLOWS, REUSABLE_ACTIONS, REUSABLE_WORKFLOWS, TASKS, WORKFLOW_CHECK_CONTEXTS, WORKFLOW_TEMPLATES, WORKFLOW_TEMPLATE_PROPERTIES, codecovComponentBlock, codecovConfig, createAstromech, createCodecovConfig, createTsconfig, deployOnRelease, deriveDeployPaths, ensureIfNotFound, extractPreviewConfig, generateCombinedDeployContent, generateThinCallerContent, mergeCodecovComponents, normalizeWorkflowWith, readWorkspacePackages, requiredChecks, reusableTemplates, runCi, runTask };
2253
+ export { CI_ORDER, KNOWN_TASKS, KNOWN_WORKFLOWS, REUSABLE_ACTIONS, REUSABLE_WORKFLOWS, TASKS, WORKFLOW_CHECK_CONTEXTS, WORKFLOW_TEMPLATES, WORKFLOW_TEMPLATE_PROPERTIES, codecovComponentBlock, codecovConfig, createAstromech, createCodecovConfig, createTsconfig, deployOnRelease, deriveDeployPaths, ensureIfNotFound, extractPreviewConfig, generateCombinedDeployContent, generateThinCallerContent, matchNamespace, mergeCodecovComponents, normalizeWorkflowWith, readWorkspacePackages, requiredChecks, reusableTemplates, runCi, runGroup, runTask };
@@ -58,11 +58,11 @@ interface TasksConfig {
58
58
  /**
59
59
  * Required status-check contexts not backed by a task — codecov gates,
60
60
  * a bundle-build check, … Appended to `astromech.requiredChecks()` after the
61
- * `required`-task contexts. (`DCO` is prepended by `holocron setup` itself.)
61
+ * `required`-task contexts. (`DCO` is prepended by `holocron repo setup` itself.)
62
62
  */
63
63
  extraRequiredChecks?: string[];
64
64
  /**
65
- * Git hooks `holocron setup` installs. `true` / `{ prePush: true }` writes
65
+ * Git hooks `holocron repo setup` installs. `true` / `{ prePush: true }` writes
66
66
  * `.husky/pre-push` (runs `holocron run ci`); `false` / `{ prePush: false }`
67
67
  * opts out. Omitted → on for `protection: "strict"` repos, off otherwise.
68
68
  * When enabled, `packageScripts()` also emits `prepare: "husky"`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theholocron/astromech",
3
- "version": "5.0.0-alpha.129",
3
+ "version": "5.0.0-alpha.133",
4
4
  "description": "The Holocron task runner — one task manifest drives `holocron run`, `holocron run ci`, the CI workflows, package.json scripts, linters, and required checks.",
5
5
  "keywords": [
6
6
  "ci",
@@ -37,7 +37,7 @@
37
37
  "dist"
38
38
  ],
39
39
  "dependencies": {
40
- "@theholocron/datapad": "5.0.0-alpha.129"
40
+ "@theholocron/datapad": "5.0.0-alpha.133"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@theholocron/eslint-config": "^8.7.1",
@@ -53,7 +53,7 @@
53
53
  "tsdown": "^0.22.14",
54
54
  "typescript": "^5.9.3",
55
55
  "vitest": "^4.1.11",
56
- "@theholocron/rollup-plugin-transform-template": "5.0.0-alpha.129"
56
+ "@theholocron/rollup-plugin-transform-template": "5.0.0-alpha.133"
57
57
  },
58
58
  "engines": {
59
59
  "node": ">=22"