@joshuafolkken/kit 1.921.0 → 1.947.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/.claude/skills/workflow-commands/background-commands.md +6 -0
  2. package/.claude/skills/workflow-commands/backlogrun-child.md +1 -1
  3. package/.claude/skills/workflow-commands/backlogrun-lanes.md +4 -3
  4. package/.claude/skills/workflow-commands/backlogrun-progress.md +13 -12
  5. package/.claude/skills/workflow-commands/backlogrun-steps.md +2 -1
  6. package/.claude/skills/workflow-commands/observation-filing.md +3 -3
  7. package/.claude/skills/workflow-commands/prerequisite.md +1 -1
  8. package/.github/workflows/ci.yml +26 -8
  9. package/.github/workflows/pr-classification.yml +76 -0
  10. package/README.md +47 -21
  11. package/dist/hooks/batch-guard.js +6 -6
  12. package/dist/hooks/{chunk-LC765SUA.js → chunk-3FWV6CFC.js} +119 -20
  13. package/dist/hooks/{chunk-UULARQ5Q.js → chunk-EYFJ74MJ.js} +13 -15
  14. package/dist/hooks/{chunk-O2FBZPSW.js → chunk-GIX5SAAB.js} +248 -231
  15. package/dist/hooks/{chunk-OLTAGGHH.js → chunk-IA7WC4NS.js} +1 -1
  16. package/dist/hooks/{chunk-UANRLZV7.js → chunk-IBFC25IX.js} +4 -4
  17. package/dist/hooks/{chunk-XMR3BS35.js → chunk-M4U4YNRE.js} +3 -3
  18. package/dist/hooks/{chunk-NWD47MW3.js → chunk-NKVLBB65.js} +3 -3
  19. package/dist/hooks/{chunk-OYU6KPRA.js → chunk-O3PEDF3M.js} +2 -2
  20. package/dist/hooks/{chunk-3HZ5MJIW.js → chunk-OM5VDM6F.js} +2 -2
  21. package/dist/hooks/{chunk-SSX23SJ2.js → chunk-RKUAD3I6.js} +1 -0
  22. package/dist/hooks/{chunk-77RLKZ5V.js → chunk-V7RH56HU.js} +2 -2
  23. package/dist/hooks/{chunk-FXAKJKTB.js → chunk-WPALEIRX.js} +1 -1
  24. package/dist/hooks/codex-hook-adapter.js +12 -12
  25. package/dist/hooks/duplicate-read-guard.js +7 -7
  26. package/dist/hooks/format-edited.js +3 -3
  27. package/dist/hooks/investigation-guard.js +7 -7
  28. package/dist/hooks/pretool-guard.js +11 -11
  29. package/dist/hooks/session-lang.js +2 -2
  30. package/dist/hooks/stop-guard.js +11 -5
  31. package/dist/josh.js +12 -14
  32. package/eslint/base.js +4 -1
  33. package/package.json +21 -6
  34. package/playwright.config.ts +9 -17
  35. package/ports/index.d.ts +1 -0
  36. package/ports/index.js +1 -0
  37. package/ports/web-server.d.ts +5 -0
  38. package/ports/web-server.js +73 -0
  39. package/prompts/collaboration-workflow/issue-template.md +1 -1
  40. package/scripts/agent/agent-role-profile.ts +11 -0
  41. package/scripts/ci/pr-classification.ts +27 -6
  42. package/scripts/document/document-byte-budget.ts +1 -1
  43. package/scripts/gate/hook-gate-reuse.ts +1 -1
  44. package/scripts/gate/project-checks.ts +60 -6
  45. package/scripts/gate/type-check-command.ts +43 -0
  46. package/scripts/git/constants.ts +4 -0
  47. package/scripts/git/git-command.ts +11 -5
  48. package/scripts/git/git-gh-pr-rollup.ts +56 -16
  49. package/scripts/git/git-staging.ts +6 -4
  50. package/scripts/git/git-stash.ts +73 -1
  51. package/scripts/git/stash-orphans.ts +24 -2
  52. package/scripts/git/stash-sweep-lock.ts +141 -0
  53. package/scripts/hooks/stop-guard.ts +2 -0
  54. package/scripts/init/init-actions.ts +3 -2
  55. package/scripts/init/init-ai-copy.ts +8 -5
  56. package/scripts/init/init-logic-migrate.ts +10 -1
  57. package/scripts/init/init-logic-templates.ts +27 -7
  58. package/scripts/init/init-logic-workspace.ts +89 -5
  59. package/scripts/init/init-logic.ts +7 -1
  60. package/scripts/init/init-static.ts +4 -1
  61. package/scripts/init/init.ts +60 -19
  62. package/scripts/init/project-profile.ts +14 -5
  63. package/scripts/issue/issue-merged.ts +75 -0
  64. package/scripts/issue/measure-rerun-cli.ts +2 -2
  65. package/scripts/josh/__snapshots__/josh-command-map.test.ts.snap +10 -0
  66. package/scripts/josh/josh-command-map.ts +1 -0
  67. package/scripts/josh/josh-command-types.ts +0 -3
  68. package/scripts/josh/josh-commands-ai.ts +6 -0
  69. package/scripts/josh/josh-commands-development.ts +6 -19
  70. package/scripts/lint/format.ts +68 -0
  71. package/scripts/lint/lint-parallel.ts +23 -36
  72. package/scripts/observations/observation-ledger-home.ts +22 -2
  73. package/scripts/observations/observation-ledger-line.ts +11 -0
  74. package/scripts/observations/observation-ledger-migrate.ts +146 -0
  75. package/scripts/observations/observation-ledger.ts +51 -3
  76. package/scripts/observations/observations-flush.ts +38 -7
  77. package/scripts/review/review-finding-ledger.ts +1 -1
  78. package/scripts/review/review-record-cli.ts +1 -7
  79. package/scripts/rules/delivered-rules.ts +10 -0
  80. package/scripts/rules/lane-background.ts +111 -0
  81. package/scripts/rules/stop-rules.ts +15 -2
  82. package/scripts/run/run-carry-flush.ts +2 -7
  83. package/scripts/run/run-hold-cli.ts +10 -2
  84. package/scripts/run/run-step-cli.ts +11 -1
  85. package/scripts/run/run-step.ts +36 -8
  86. package/scripts/run/run-tidy-cli.ts +50 -0
  87. package/scripts/run/run-tidy-lanes.ts +110 -0
  88. package/scripts/run/run-tidy-stashes.ts +160 -0
  89. package/scripts/run/run-tidy.ts +101 -0
  90. package/scripts/safe-chain/ci-installer-pin.ts +90 -0
  91. package/scripts/safe-chain/preinstall-command.ts +39 -0
  92. package/scripts/sync/sync.ts +5 -2
  93. package/scripts/test/pilot-files.ts +0 -1
  94. package/scripts/version/preinstall-version-update.ts +2 -0
  95. package/templates/pnpm-workspace.static.yaml +4 -0
  96. package/templates/workflows/ci.yml +21 -7
  97. package/tsconfig/base.json +4 -1
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  ESLINT_EDIT_CACHE_FLAGS,
7
7
  time_density_hook
8
- } from "./chunk-UULARQ5Q.js";
8
+ } from "./chunk-EYFJ74MJ.js";
9
9
 
10
10
  // scripts/hooks/format-edited-file.ts
11
11
  import { existsSync as existsSync2 } from "node:fs";
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  investigation_reads
3
- } from "./chunk-XMR3BS35.js";
3
+ } from "./chunk-M4U4YNRE.js";
4
4
  import {
5
5
  lane_guard_policy
6
- } from "./chunk-3HZ5MJIW.js";
6
+ } from "./chunk-OM5VDM6F.js";
7
7
  import {
8
8
  hook_decision
9
- } from "./chunk-OYU6KPRA.js";
9
+ } from "./chunk-O3PEDF3M.js";
10
10
  import {
11
11
  json_value,
12
12
  time_spans
13
- } from "./chunk-UULARQ5Q.js";
13
+ } from "./chunk-EYFJ74MJ.js";
14
14
 
15
15
  // scripts/delegation/duplicate-read-guard.ts
16
16
  import { statSync } from "node:fs";
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  time_batch_guard
3
- } from "./chunk-3HZ5MJIW.js";
3
+ } from "./chunk-OM5VDM6F.js";
4
4
  import {
5
5
  hook_decision
6
- } from "./chunk-OYU6KPRA.js";
6
+ } from "./chunk-O3PEDF3M.js";
7
7
  import {
8
8
  cost_blocks,
9
9
  cost_transcript,
10
10
  time_bundle_call,
11
11
  time_shell,
12
12
  time_spans
13
- } from "./chunk-UULARQ5Q.js";
13
+ } from "./chunk-EYFJ74MJ.js";
14
14
 
15
15
  // scripts/delegation/investigation-reads.ts
16
16
  import path from "node:path";
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  investigation_reads
3
- } from "./chunk-XMR3BS35.js";
3
+ } from "./chunk-M4U4YNRE.js";
4
4
  import {
5
5
  lane_guard_policy
6
- } from "./chunk-3HZ5MJIW.js";
6
+ } from "./chunk-OM5VDM6F.js";
7
7
  import {
8
8
  hook_decision
9
- } from "./chunk-OYU6KPRA.js";
9
+ } from "./chunk-O3PEDF3M.js";
10
10
 
11
11
  // scripts/delegation/investigation-guard.ts
12
12
  import { text } from "node:stream/consumers";
@@ -3,10 +3,10 @@ import {
3
3
  stamp_file,
4
4
  time_density_hook,
5
5
  time_hook_transcript
6
- } from "./chunk-UULARQ5Q.js";
6
+ } from "./chunk-EYFJ74MJ.js";
7
7
  import {
8
8
  josh_environment_file
9
- } from "./chunk-FXAKJKTB.js";
9
+ } from "./chunk-WPALEIRX.js";
10
10
 
11
11
  // scripts/josh/hook-decision.ts
12
12
  import { z } from "zod";
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  lane_child_marker
3
- } from "./chunk-OYU6KPRA.js";
3
+ } from "./chunk-O3PEDF3M.js";
4
4
  import {
5
5
  time_bundle_call,
6
6
  time_format,
7
7
  time_round_trips,
8
8
  time_spans,
9
9
  time_transcript_line
10
- } from "./chunk-UULARQ5Q.js";
10
+ } from "./chunk-EYFJ74MJ.js";
11
11
 
12
12
  // scripts/lane/lane-guard-policy.ts
13
13
  var DEFAULT_MODE = "refuse";
@@ -75,6 +75,7 @@ function load_environment_file(directory = process.cwd()) {
75
75
  }
76
76
  var ports = {
77
77
  load_environment_file,
78
+ resolve_project_directory,
78
79
  resolve_seed,
79
80
  resolve_lane,
80
81
  resolve_development_port,
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  lane_guard_policy,
3
3
  time_batch_guard
4
- } from "./chunk-3HZ5MJIW.js";
4
+ } from "./chunk-OM5VDM6F.js";
5
5
  import {
6
6
  hook_decision
7
- } from "./chunk-OYU6KPRA.js";
7
+ } from "./chunk-O3PEDF3M.js";
8
8
 
9
9
  // scripts/hooks/batch-guard.ts
10
10
  import { text } from "node:stream/consumers";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ENV_FILE_NAME
3
- } from "./chunk-SSX23SJ2.js";
3
+ } from "./chunk-RKUAD3I6.js";
4
4
 
5
5
  // scripts/josh/josh-environment-file.ts
6
6
  function load_environment_file() {
@@ -1,27 +1,27 @@
1
1
  #!/usr/bin/env tsx
2
2
  import {
3
3
  pretool_guard
4
- } from "./chunk-O2FBZPSW.js";
5
- import "./chunk-LC765SUA.js";
4
+ } from "./chunk-GIX5SAAB.js";
5
+ import "./chunk-3FWV6CFC.js";
6
6
  import {
7
7
  build_envelope,
8
8
  compose_context,
9
9
  format_edited_payload
10
- } from "./chunk-OLTAGGHH.js";
10
+ } from "./chunk-IA7WC4NS.js";
11
11
  import "./chunk-3V37IID6.js";
12
- import "./chunk-77RLKZ5V.js";
13
- import "./chunk-NWD47MW3.js";
14
- import "./chunk-UANRLZV7.js";
15
- import "./chunk-XMR3BS35.js";
16
- import "./chunk-3HZ5MJIW.js";
12
+ import "./chunk-V7RH56HU.js";
13
+ import "./chunk-NKVLBB65.js";
14
+ import "./chunk-IBFC25IX.js";
15
+ import "./chunk-M4U4YNRE.js";
16
+ import "./chunk-OM5VDM6F.js";
17
17
  import {
18
18
  hook_decision
19
- } from "./chunk-OYU6KPRA.js";
19
+ } from "./chunk-O3PEDF3M.js";
20
20
  import {
21
21
  time_density_hook
22
- } from "./chunk-UULARQ5Q.js";
23
- import "./chunk-FXAKJKTB.js";
24
- import "./chunk-SSX23SJ2.js";
22
+ } from "./chunk-EYFJ74MJ.js";
23
+ import "./chunk-WPALEIRX.js";
24
+ import "./chunk-RKUAD3I6.js";
25
25
 
26
26
  // scripts/hooks/codex-hook-adapter.ts
27
27
  import { text } from "node:stream/consumers";
@@ -9,13 +9,13 @@ import {
9
9
  is_enabled,
10
10
  notice_refusal_path,
11
11
  refusal_path
12
- } from "./chunk-UANRLZV7.js";
13
- import "./chunk-XMR3BS35.js";
14
- import "./chunk-3HZ5MJIW.js";
15
- import "./chunk-OYU6KPRA.js";
16
- import "./chunk-UULARQ5Q.js";
17
- import "./chunk-FXAKJKTB.js";
18
- import "./chunk-SSX23SJ2.js";
12
+ } from "./chunk-IBFC25IX.js";
13
+ import "./chunk-M4U4YNRE.js";
14
+ import "./chunk-OM5VDM6F.js";
15
+ import "./chunk-O3PEDF3M.js";
16
+ import "./chunk-EYFJ74MJ.js";
17
+ import "./chunk-WPALEIRX.js";
18
+ import "./chunk-RKUAD3I6.js";
19
19
  export {
20
20
  DISABLED_VALUES,
21
21
  SWITCH_ENV_KEY,
@@ -15,10 +15,10 @@ import {
15
15
  relative_to_root,
16
16
  resolve_invocations,
17
17
  select_invocation
18
- } from "./chunk-OLTAGGHH.js";
18
+ } from "./chunk-IA7WC4NS.js";
19
19
  import "./chunk-3V37IID6.js";
20
- import "./chunk-UULARQ5Q.js";
21
- import "./chunk-SSX23SJ2.js";
20
+ import "./chunk-EYFJ74MJ.js";
21
+ import "./chunk-RKUAD3I6.js";
22
22
  export {
23
23
  ESLINT_DAEMON,
24
24
  MAX_DIAGNOSTIC_CHARS,
@@ -10,13 +10,13 @@ import {
10
10
  is_enabled,
11
11
  load_environment_file,
12
12
  refusal_path
13
- } from "./chunk-NWD47MW3.js";
14
- import "./chunk-XMR3BS35.js";
15
- import "./chunk-3HZ5MJIW.js";
16
- import "./chunk-OYU6KPRA.js";
17
- import "./chunk-UULARQ5Q.js";
18
- import "./chunk-FXAKJKTB.js";
19
- import "./chunk-SSX23SJ2.js";
13
+ } from "./chunk-NKVLBB65.js";
14
+ import "./chunk-M4U4YNRE.js";
15
+ import "./chunk-OM5VDM6F.js";
16
+ import "./chunk-O3PEDF3M.js";
17
+ import "./chunk-EYFJ74MJ.js";
18
+ import "./chunk-WPALEIRX.js";
19
+ import "./chunk-RKUAD3I6.js";
20
20
  export {
21
21
  DISABLED_VALUES,
22
22
  NOTICE,
@@ -3,18 +3,18 @@ import {
3
3
  pretool_guard,
4
4
  pretool_outcome,
5
5
  pretool_outcome_async
6
- } from "./chunk-O2FBZPSW.js";
7
- import "./chunk-LC765SUA.js";
6
+ } from "./chunk-GIX5SAAB.js";
7
+ import "./chunk-3FWV6CFC.js";
8
8
  import "./chunk-3V37IID6.js";
9
- import "./chunk-77RLKZ5V.js";
10
- import "./chunk-NWD47MW3.js";
11
- import "./chunk-UANRLZV7.js";
12
- import "./chunk-XMR3BS35.js";
13
- import "./chunk-3HZ5MJIW.js";
14
- import "./chunk-OYU6KPRA.js";
15
- import "./chunk-UULARQ5Q.js";
16
- import "./chunk-FXAKJKTB.js";
17
- import "./chunk-SSX23SJ2.js";
9
+ import "./chunk-V7RH56HU.js";
10
+ import "./chunk-NKVLBB65.js";
11
+ import "./chunk-IBFC25IX.js";
12
+ import "./chunk-M4U4YNRE.js";
13
+ import "./chunk-OM5VDM6F.js";
14
+ import "./chunk-O3PEDF3M.js";
15
+ import "./chunk-EYFJ74MJ.js";
16
+ import "./chunk-WPALEIRX.js";
17
+ import "./chunk-RKUAD3I6.js";
18
18
  export {
19
19
  pretool_guard,
20
20
  pretool_outcome,
@@ -4,8 +4,8 @@ import {
4
4
  } from "./chunk-6V5OPIUU.js";
5
5
  import {
6
6
  josh_environment_file
7
- } from "./chunk-FXAKJKTB.js";
8
- import "./chunk-SSX23SJ2.js";
7
+ } from "./chunk-WPALEIRX.js";
8
+ import "./chunk-RKUAD3I6.js";
9
9
 
10
10
  // scripts/josh/session-language-cli.ts
11
11
  import { fileURLToPath } from "node:url";
@@ -5,6 +5,7 @@ import {
5
5
  filing_cap,
6
6
  git_gh_api_path,
7
7
  git_gh_exec,
8
+ lane_background,
8
9
  lane_child_invocation,
9
10
  lane_park,
10
11
  lane_registry,
@@ -15,22 +16,22 @@ import {
15
16
  run_hold,
16
17
  run_invocation,
17
18
  run_watcher_guard
18
- } from "./chunk-LC765SUA.js";
19
+ } from "./chunk-3FWV6CFC.js";
19
20
  import {
20
21
  session_language
21
22
  } from "./chunk-6V5OPIUU.js";
22
23
  import {
23
24
  hook_decision,
24
25
  lane_child_marker
25
- } from "./chunk-OYU6KPRA.js";
26
+ } from "./chunk-O3PEDF3M.js";
26
27
  import {
27
28
  PROJECT_ROOT,
28
29
  stamp_file,
29
30
  time_density_hook,
30
31
  time_hook_transcript
31
- } from "./chunk-UULARQ5Q.js";
32
- import "./chunk-FXAKJKTB.js";
33
- import "./chunk-SSX23SJ2.js";
32
+ } from "./chunk-EYFJ74MJ.js";
33
+ import "./chunk-WPALEIRX.js";
34
+ import "./chunk-RKUAD3I6.js";
34
35
 
35
36
  // scripts/hooks/stop-guard.ts
36
37
  import { text } from "node:stream/consumers";
@@ -1186,8 +1187,12 @@ function count_headless_refusals(tail) {
1186
1187
  const last_wait = Math.max(...HEADLESS_WAIT_CALLS.map((call) => tail.lastIndexOf(call)));
1187
1188
  return tail.slice(Math.max(last_wait, 0)).split(HEADLESS_WAIT_MARKER).length - 1;
1188
1189
  }
1190
+ function needs_background_wait(context) {
1191
+ return context.lane_child && context.background_pending;
1192
+ }
1189
1193
  function hold_reason(context) {
1190
1194
  if (needs_index_route(context)) return LANE_INDEX_REASON;
1195
+ if (needs_background_wait(context)) return lane_background.LANE_BACKGROUND_STOP_REASON;
1191
1196
  if (needs_notify(context)) return STOP_NOTIFY_REASON;
1192
1197
  if (needs_release(context)) return HOLD_RELEASE_REASON;
1193
1198
  return void 0;
@@ -1558,6 +1563,7 @@ async function build_context(transcript_path, payload_tail) {
1558
1563
  headless_waiting: await run_headless.must_keep_waiting(),
1559
1564
  headless_refusals: stop_rules.count_headless_refusals(tail),
1560
1565
  lane_child: lane_child_marker.is_child_of(process.cwd()),
1566
+ background_pending: lane_background.pending_background_ids(tail).length > 0,
1561
1567
  session_lang: session_lang()
1562
1568
  };
1563
1569
  }
package/dist/josh.js CHANGED
@@ -262,7 +262,6 @@ var ENV_FILE_NAME = ".env";
262
262
  // scripts/josh/josh-command-types.ts
263
263
  var OPTIONAL_ENV_FILE_FLAGS = [`--env-file-if-exists=${ENV_FILE_NAME}`];
264
264
  var GATE_COMMAND = "gate";
265
- var PE = ["pnpm", "exec"];
266
265
  var ESLINT_CACHE_FILE = ".eslintcache";
267
266
  var TS_BUILD_INFO_FILE = ".tsbuildinfo";
268
267
  var CSPELL_CACHE_FILE = ".cspellcache";
@@ -300,7 +299,6 @@ function content_cache_flags(cache_file) {
300
299
  var ESLINT_CACHE_FLAGS = content_cache_flags(ESLINT_CACHE_FILE);
301
300
  var ESLINT_EDIT_CACHE_FLAGS = content_cache_flags(ESLINT_EDIT_CACHE_FILE);
302
301
  var ESLINT_RELATED_CACHE_FLAGS = content_cache_flags(ESLINT_RELATED_CACHE_FILE);
303
- var TS_CACHE_FLAGS = ["--incremental", "--tsBuildInfoFile", TS_BUILD_INFO_FILE];
304
302
  var CSPELL_CACHE_FLAGS = content_cache_flags(CSPELL_CACHE_FILE);
305
303
 
306
304
  // scripts/josh/josh-commands-backlog.ts
@@ -659,6 +657,12 @@ var AI_COMMANDS = {
659
657
  reference: ["[issue|--force]", "automation", ["files"]],
660
658
  default_script_arguments: ["--release"]
661
659
  },
660
+ "run:tidy": {
661
+ script: "scripts/run/run-tidy-cli.ts",
662
+ description: "Close merged lanes and drop stashes whose issues are all merged",
663
+ category: "AI tools",
664
+ reference: ["", "automation", ["git", "network", "files"]]
665
+ },
662
666
  "run:carry": {
663
667
  script: "scripts/run/run-carry-cli.ts",
664
668
  description: "Carry one invocation\u2019s budget across its own session cuts",
@@ -855,7 +859,7 @@ var DEV_COMMANDS = {
855
859
  },
856
860
  lint: {
857
861
  script: "scripts/lint/lint-parallel.ts",
858
- description: "Check code with prettier and eslint",
862
+ description: "Check code with prettier and eslint (skips a tool a static project lacks)",
859
863
  category: "Development",
860
864
  reference: ["", "developer", ["processes"]]
861
865
  },
@@ -890,15 +894,8 @@ var DEV_COMMANDS = {
890
894
  reference: ["", "developer", ["none"]]
891
895
  },
892
896
  format: {
893
- // prettier first here, unlike `format:edited`, and deliberately: `eslint --fix` exits 1
894
- // whenever a non-autofixable error remains, so putting it first behind `&&` would mean one
895
- // unused variable anywhere in the tree stops prettier from running at all.
896
- shell: [
897
- "sh",
898
- "-c",
899
- `pnpm exec prettier --write . && pnpm exec eslint . --fix ${ESLINT_CACHE_FLAGS.join(" ")}`
900
- ],
901
- description: "Format code with prettier and eslint",
897
+ script: "scripts/lint/format.ts",
898
+ description: "Format code with prettier and eslint (skips a tool a static project lacks)",
902
899
  category: "Development",
903
900
  reference: ["", "developer", ["files", "processes"]]
904
901
  },
@@ -1010,8 +1007,8 @@ var DEV_COMMANDS = {
1010
1007
  argument_targets: ["test:unit", "test:e2e"]
1011
1008
  },
1012
1009
  check: {
1013
- shell: [...PE, "tsc", "--noEmit", ...TS_CACHE_FLAGS],
1014
- description: "Type-check TypeScript project",
1010
+ script: "scripts/gate/type-check-command.ts",
1011
+ description: "Type-check with tsc (skips a static project with no TypeScript to check)",
1015
1012
  category: "Development",
1016
1013
  reference: ["[arguments...]", "developer", ["processes"]]
1017
1014
  },
@@ -1509,6 +1506,7 @@ var ALIASES = {
1509
1506
  rh: "run:hold",
1510
1507
  rr: "run:release",
1511
1508
  rc: "run:carry",
1509
+ rtd: "run:tidy",
1512
1510
  rw: "run:wake",
1513
1511
  rct: "run:cut",
1514
1512
  rv: "run:liveness",
package/eslint/base.js CHANGED
@@ -203,7 +203,10 @@ export function create_base_config({ gitignore_path, tsconfig_root_dir }) {
203
203
  },
204
204
  },
205
205
  {
206
- files: ['**/*.js'],
206
+ // `.mjs` / `.cjs` too (joshuafolkken/kit#2693): the typed parser options above reach only
207
+ // TypeScript files, so a hand-authored module in either extension crashed the whole run on
208
+ // the first type-aware rule instead of being linted as JavaScript.
209
+ files: ['**/*.{js,mjs,cjs}'],
207
210
  ...ts.configs.disableTypeChecked,
208
211
  rules: {
209
212
  ...ts.configs.disableTypeChecked.rules,
package/package.json CHANGED
@@ -1,6 +1,17 @@
1
1
  {
2
- "version": "1.921.0",
2
+ "version": "1.947.0",
3
3
  "name": "@joshuafolkken/kit",
4
+ "description": "Development toolkit for AI-assisted projects: formatting, AI assistant rules and a Git/GitHub Issue workflow for any repository, plus lint, type check, tests and hooks for Node projects",
5
+ "keywords": [
6
+ "ai",
7
+ "claude-code",
8
+ "cli",
9
+ "developer-tools",
10
+ "eslint",
11
+ "prettier",
12
+ "toolkit",
13
+ "workflow"
14
+ ],
4
15
  "type": "module",
5
16
  "license": "MIT",
6
17
  "repository": {
@@ -78,6 +89,10 @@
78
89
  "types": "./ports/index.d.ts",
79
90
  "default": "./ports/index.js"
80
91
  },
92
+ "./web-server": {
93
+ "types": "./ports/web-server.d.ts",
94
+ "default": "./ports/web-server.js"
95
+ },
81
96
  "./prettier": {
82
97
  "types": "./prettier/index.d.ts",
83
98
  "default": "./prettier/index.js"
@@ -109,9 +124,9 @@
109
124
  }
110
125
  },
111
126
  "peerDependencies": {
112
- "@playwright/test": ">=1.0.0",
113
127
  "@eslint/compat": "^2.1.1",
114
128
  "@eslint/js": "^10.0.1",
129
+ "@playwright/test": ">=1.0.0",
115
130
  "@stylistic/eslint-plugin": "^5.10.0",
116
131
  "eslint": "^10.0.0",
117
132
  "eslint-config-prettier": "^10.1.8",
@@ -173,11 +188,12 @@
173
188
  "@eslint/compat": "^2.1.1",
174
189
  "@eslint/js": "^10.0.1",
175
190
  "@ianvs/prettier-plugin-sort-imports": "^4.7.1",
191
+ "@playwright/test": "^1.63.0",
176
192
  "@secretlint/secretlint-rule-preset-recommend": "^13.0.6",
177
193
  "@stylistic/eslint-plugin": "^5.10.0",
178
194
  "@types/node": "^26.6.3",
179
195
  "@types/semver": "^7.8.0",
180
- "cspell": "^10.3.4",
196
+ "cspell": "^10.3.5",
181
197
  "esbuild": "^0.28.2",
182
198
  "eslint": "^10.11.0",
183
199
  "eslint-config-prettier": "^10.1.8",
@@ -196,8 +212,8 @@
196
212
  "rollup-plugin-dts": "^6.5.1",
197
213
  "secretlint": "^13.0.6",
198
214
  "typescript": "^6.0.3",
199
- "vitest": "^5.0.2",
200
- "typescript-eslint": "^8.70.1"
215
+ "typescript-eslint": "^8.70.1",
216
+ "vitest": "^5.0.2"
201
217
  },
202
218
  "dependencies": {
203
219
  "execa": "^10.0.1",
@@ -217,7 +233,6 @@
217
233
  }
218
234
  },
219
235
  "scripts": {
220
- "preinstall": "pnpm dlx @aikidosec/safe-chain@1.5.20 setup-ci",
221
236
  "build": "tsx scripts/build/build-bin.ts && tsx scripts/build/build-hooks.ts && tsx scripts/build/build-version.ts && tsx scripts/build/build-config-merge.ts && tsx scripts/build/build-managed-marker.ts && tsx scripts/build/build-self-sync-guard.ts && tsx scripts/build/build-claude-md.ts",
222
237
  "josh": "tsx scripts/josh/josh.ts"
223
238
  }
@@ -1,5 +1,6 @@
1
1
  import { environment_flags } from '@joshuafolkken/kit/env'
2
2
  import { ports } from '@joshuafolkken/kit/ports'
3
+ import { web_server } from '@joshuafolkken/kit/web-server'
3
4
  import { defineConfig, devices, type ReporterDescription } from '@playwright/test'
4
5
 
5
6
  // Both ports come from kit's single definition (`@joshuafolkken/kit/ports`), offset by the personal
@@ -17,7 +18,7 @@ import { defineConfig, devices, type ReporterDescription } from '@playwright/tes
17
18
  // the file, and a project with no `.env` is untouched.
18
19
  //
19
20
  // The working directory is the anchor, and the loader ascends from it to the project root — the
20
- // same root `pnpm run` hands the `webServer` command, so both sides name one file from anywhere
21
+ // same root `node --run` hands the `webServer` command, so both sides name one file from anywhere
21
22
  // inside the project. The one layout that escapes that is a run whose working directory sits in a
22
23
  // *different* package from this config, as `playwright test --config ../../playwright.config.ts`
23
24
  // does in a workspace: Playwright would default `webServer.cwd` to this file's directory while the
@@ -31,13 +32,6 @@ const PREVIEW_PORT = ports.resolve_preview_port()
31
32
 
32
33
  const CI_TIMEOUT = 120_000
33
34
  const LOCAL_TIMEOUT = 30_000
34
- // pnpm 11.27.1+ places a script it runs without a controlling terminal in its own process group, so
35
- // Playwright's default teardown — SIGKILL to the webServer's group — no longer reaches the `vite dev`
36
- // / `preview` child: it survives holding Playwright's stdio pipes open, and Playwright blocks forever
37
- // on the `close` event (#2386). SIGTERM, unlike SIGKILL, is relayed by that pnpm to the child, so a
38
- // graceful shutdown lets the server exit and the pipes close. The timeout must stay well above the
39
- // observed ~40ms shutdown, or Playwright falls back to killProcess() (SIGKILL) and the hang returns.
40
- const SHUTDOWN_TIMEOUT = 10_000
41
35
  const CI_TEST_TIMEOUT = 30_000
42
36
  const ACTION_TIMEOUT = 10_000
43
37
  const NAV_TIMEOUT = 30_000
@@ -74,7 +68,7 @@ const IS_CI = environment_flags.is_ci_enabled(process.env['CI'])
74
68
  // run whose report is unreachable unless the developer already knows `playwright show-report`.
75
69
  // (`CI/1` in the Playwright user agent and the MCP headless force share the same root cause.)
76
70
  // Deleting the variable once this config has judged the run local is what makes every downstream
77
- // reader agree with that verdict, the `pnpm run dev` child process included: leaving `CI=0` set for
71
+ // reader agree with that verdict, the `dev` script's child process included: leaving `CI=0` set for
78
72
  // the child would only re-introduce the same bare-truthiness bug one process down. The guard is
79
73
  // what keeps this safe — a real provider value such as `CI=woodpecker` is never touched, and the
80
74
  // deletion cannot fire on the CI branch.
@@ -91,24 +85,22 @@ if (!IS_CI) delete process.env['CI']
91
85
  // application; a seed reduces how often a foreign server is on the port at all.
92
86
  const IS_REUSE_ENABLED = environment_flags.is_flag_enabled(process.env['PLAYWRIGHT_REUSE_SERVER'])
93
87
 
94
- // Both branches share one shutdown policy — see SHUTDOWN_TIMEOUT for why SIGTERM rather than the
95
- // SIGKILL default. `as const` keeps the signal a literal so it satisfies Playwright's signal union.
96
- const GRACEFUL_SHUTDOWN = { signal: 'SIGTERM', timeout: SHUTDOWN_TIMEOUT } as const
97
-
88
+ // The scripts run through `node --run` rather than `pnpm run`, so the server stays in the process
89
+ // group Playwright signals on teardown and its default SIGKILL reaches it directly — no package
90
+ // manager relays the signal, and no graceful-shutdown timeout has to be tuned around one (#2392).
91
+ // Each script's `pre` hook is chained in explicitly, since `node --run` does not run it.
98
92
  const web_server_config = IS_CI
99
93
  ? {
100
- command: 'pnpm run build && pnpm run preview',
94
+ command: web_server.script_command(['build', 'preview']),
101
95
  port: PREVIEW_PORT,
102
96
  timeout: CI_TIMEOUT,
103
97
  reuseExistingServer: IS_REUSE_ENABLED,
104
- gracefulShutdown: GRACEFUL_SHUTDOWN,
105
98
  }
106
99
  : {
107
- command: 'pnpm run dev',
100
+ command: web_server.script_command(['dev']),
108
101
  port: DEV_PORT,
109
102
  timeout: LOCAL_TIMEOUT,
110
103
  reuseExistingServer: IS_REUSE_ENABLED,
111
- gracefulShutdown: GRACEFUL_SHUTDOWN,
112
104
  }
113
105
 
114
106
  const env_config: EnvConfig = IS_CI
package/ports/index.d.ts CHANGED
@@ -7,6 +7,7 @@ declare const PROJECT_ENVIRONMENT_KEYS: ReadonlySet<string>
7
7
 
8
8
  declare const ports: {
9
9
  load_environment_file: (directory?: string) => boolean
10
+ resolve_project_directory: (directory: string) => string
10
11
  resolve_seed: (environment?: PortEnvironment) => number
11
12
  resolve_lane: (environment?: PortEnvironment) => number
12
13
  resolve_development_port: (environment?: PortEnvironment) => number
package/ports/index.js CHANGED
@@ -247,6 +247,7 @@ function load_environment_file(directory = process.cwd()) {
247
247
 
248
248
  const ports = {
249
249
  load_environment_file,
250
+ resolve_project_directory,
250
251
  resolve_seed,
251
252
  resolve_lane,
252
253
  resolve_development_port,
@@ -0,0 +1,5 @@
1
+ declare const web_server: {
2
+ script_command: (names: Array<string>, directory?: string) => string
3
+ }
4
+
5
+ export { web_server }