@joshuafolkken/kit 1.1471.0 → 1.1514.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.
- package/.claude/settings.json +6 -6
- package/.claude/skills/epic-commands/SKILL.md +2 -14
- package/.claude/skills/epic-commands/epic-bundle.md +9 -5
- package/.claude/skills/epic-commands/execution-waves.md +1 -2
- package/.claude/skills/verify-ui/SKILL.md +1 -2
- package/.claude/skills/workflow-commands/SKILL.md +7 -9
- package/.claude/skills/workflow-commands/background-commands.md +3 -7
- package/.claude/skills/workflow-commands/backlogrun-child.md +3 -10
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +6 -15
- package/.claude/skills/workflow-commands/backlogrun-park.md +2 -8
- package/.claude/skills/workflow-commands/backlogrun-progress.md +10 -19
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +8 -8
- package/.claude/skills/workflow-commands/backlogrun-steps.md +2 -10
- package/.claude/skills/workflow-commands/backlogrun.md +31 -50
- package/.claude/skills/workflow-commands/chain-rule.md +7 -6
- package/.claude/skills/workflow-commands/delegation.md +12 -8
- package/.claude/skills/workflow-commands/entry-sequence.md +1 -3
- package/.claude/skills/workflow-commands/followup.md +3 -6
- package/.claude/skills/workflow-commands/fullrun-steps.md +3 -5
- package/.claude/skills/workflow-commands/fullrun.md +4 -6
- package/.claude/skills/workflow-commands/halfrun.md +3 -7
- package/.claude/skills/workflow-commands/into-target.md +1 -2
- package/.claude/skills/workflow-commands/issue-comments.md +3 -3
- package/.claude/skills/workflow-commands/issue-scout.md +3 -2
- package/.claude/skills/workflow-commands/latest-gate.md +2 -6
- package/.claude/skills/workflow-commands/needs-human-review.md +2 -5
- package/.claude/skills/workflow-commands/observation-filing.md +0 -14
- package/.claude/skills/workflow-commands/observation-ledger.md +4 -9
- package/.claude/skills/workflow-commands/pre-gate-cut.md +11 -16
- package/.claude/skills/workflow-commands/prerequisite.md +1 -2
- package/.claude/skills/workflow-commands/progress-watcher.md +2 -7
- package/.claude/skills/workflow-commands/prrun.md +3 -5
- package/.claude/skills/workflow-commands/retrospective.md +4 -4
- package/.claude/skills/workflow-commands/split-assessment.md +1 -3
- package/.claude/skills/workflow-commands/target-repository.md +1 -2
- package/.claude/skills/workflow-commands/working-tree-hold.md +2 -4
- package/.codex/hooks.json +6 -6
- package/.github/actions/setup-node/action.yml +1 -1
- package/.github/workflows/ci.yml +1 -1
- package/.github/workflows/publish.yml +2 -2
- package/CLAUDE.md +1 -1
- package/cspell/index.yaml +7 -0
- package/dist/CLAUDE.md +1 -1
- package/dist/commands/document-section-cli.js +67 -34
- package/dist/hooks/batch-guard.js +6 -6
- package/dist/hooks/chunk-4KKD2UTK.js +66 -0
- package/dist/hooks/{chunk-J47HU5H5.js → chunk-6TS2JD6D.js} +3 -3
- package/dist/hooks/chunk-7DSBJVFH.js +50 -0
- package/dist/hooks/{chunk-YHBZAJSV.js → chunk-A65Y4YOR.js} +3 -3
- package/dist/hooks/{chunk-E7OIKX5Z.js → chunk-APUO6U4J.js} +85 -7
- package/dist/hooks/{chunk-IX6TTTI6.js → chunk-EFXE6C37.js} +8 -22
- package/dist/hooks/chunk-GP4IEC4O.js +20 -0
- package/dist/hooks/{chunk-SHGPANFB.js → chunk-JP45SOCJ.js} +3 -3
- package/dist/hooks/{chunk-K4EOONYM.js → chunk-LAOV7NLM.js} +1 -1
- package/dist/hooks/chunk-M4HGZV7U.js +83 -0
- package/dist/hooks/{chunk-KC5AK2GF.js → chunk-O6GDRNJB.js} +3 -3
- package/dist/hooks/{chunk-YYPI7SJZ.js → chunk-PF2NZL2A.js} +5 -5
- package/dist/hooks/{chunk-H5HVWYXK.js → chunk-PTICX4OL.js} +3 -4
- package/dist/hooks/{chunk-IIGFYXKC.js → chunk-RT27QRJW.js} +581 -1438
- package/dist/hooks/{chunk-43ZHT22P.js → chunk-SYOTDYCI.js} +1127 -1089
- package/dist/hooks/{chunk-AS74OU3D.js → chunk-TNUMY6NL.js} +1507 -1336
- package/dist/hooks/chunk-UPUZF3AN.js +279 -0
- package/dist/hooks/{chunk-EUMACUK2.js → chunk-WK6SMBIC.js} +1948 -806
- package/dist/hooks/codex-hook-adapter.js +17 -14
- package/dist/hooks/duplicate-read-guard.js +7 -7
- package/dist/hooks/format-edited.js +5 -4
- package/dist/hooks/inputs.json +317 -264
- package/dist/hooks/investigation-guard.js +8 -11
- package/dist/hooks/pretool-guard.js +16 -13
- package/dist/hooks/session-lang.js +370 -25
- package/dist/hooks/stop-guard.js +2576 -176
- package/dist/josh.js +2124 -277
- package/lefthook/base.yml +5 -3
- package/package.json +12 -10
- package/prompts/collaboration-workflow/file-edits.md +1 -3
- package/prompts/collaboration-workflow/gh-rest.md +1 -2
- package/prompts/collaboration-workflow/issue-citation.md +2 -4
- package/prompts/collaboration-workflow/issue-template.md +10 -2
- package/prompts/collaboration-workflow/lane-instructions.md +35 -0
- package/prompts/collaboration-workflow/operating-rules.md +2 -6
- package/prompts/collaboration-workflow/output-bounds.md +3 -3
- package/prompts/collaboration-workflow/overview.md +1 -1
- package/prompts/collaboration-workflow/principles.md +14 -8
- package/prompts/collaboration-workflow/report-format.md +9 -0
- package/prompts/collaboration-workflow/residency.md +12 -8
- package/prompts/collaboration-workflow/rule-delivery.md +3 -11
- package/prompts/collaboration-workflow/shell-body.md +6 -6
- package/prompts/collaboration-workflow/turn-batching.md +5 -5
- package/prompts/collaboration-workflow/upstream-interrupt.md +2 -2
- package/prompts/collaboration-workflow/wip-cap.md +6 -6
- package/prompts/collaboration-workflow.md +1 -0
- package/prompts/review.md +4 -5
- package/prompts/testing-guide.md +2 -2
- package/scripts/agent/agent-argv.ts +20 -4
- package/scripts/agent/agent-role-profile.ts +101 -45
- package/scripts/agent/agent-safe-text.ts +60 -0
- package/scripts/agent/claude-agent-argv.ts +14 -0
- package/scripts/agent/codex-agent-argv.ts +2 -0
- package/scripts/agent/lane-instructions.ts +144 -0
- package/scripts/backlog/backlog-budget.ts +4 -4
- package/scripts/backlog/backlog-drive-named.ts +1 -1
- package/scripts/backlog/backlog-drive-restore.ts +9 -1
- package/scripts/backlog/backlog-occupied.ts +56 -0
- package/scripts/backlog/backlog-ready.ts +47 -10
- package/scripts/delegation/duplicate-read-guard.ts +2 -2
- package/scripts/delegation/investigation-guard.ts +15 -65
- package/scripts/delegation/investigation-reads.ts +0 -1
- package/scripts/document/document-byte-budget.ts +6 -5
- package/scripts/document/document-section-cli.ts +17 -5
- package/scripts/document/entry-read-budget.ts +2 -2
- package/scripts/document/read-set-cli.ts +4 -1
- package/scripts/epic/epic-audit-orphans.ts +5 -8
- package/scripts/epic/epic-audit.ts +52 -1
- package/scripts/epic/epic-bundle-evidence.ts +49 -26
- package/scripts/epic/epic-bundle-referenced.ts +14 -3
- package/scripts/epic/epic-bundle.ts +17 -9
- package/scripts/followup/git-followup-workflow.ts +19 -1
- package/scripts/gate/check-inputs.ts +129 -0
- package/scripts/gate/check-reuse.ts +162 -0
- package/scripts/gate/core-budget.ts +93 -44
- package/scripts/gate/core-wait.ts +130 -0
- package/scripts/gate/free-cores.ts +49 -0
- package/scripts/gate/gate-ledger.ts +17 -3
- package/scripts/gate/gate-plan.ts +23 -1
- package/scripts/gate/gate-report.ts +15 -2
- package/scripts/gate/gate-run-steps.ts +150 -0
- package/scripts/gate/held-mark.ts +55 -0
- package/scripts/gate/machine-capacity.ts +70 -11
- package/scripts/gate/pre-commit-type-check.ts +14 -1
- package/scripts/gate/verification-gate.ts +58 -125
- package/scripts/gh/git-gh-issue-rest.ts +1 -0
- package/scripts/gh/git-gh-issue-write.ts +24 -2
- package/scripts/gh/git-pr.ts +13 -1
- package/scripts/git/main-merge-regenerate.ts +78 -0
- package/scripts/git/main-merge.ts +14 -5
- package/scripts/hooks/batch-guard.ts +5 -8
- package/scripts/hooks/pre-commit-lint.ts +91 -0
- package/scripts/hooks/pre-push-unit.ts +1 -1
- package/scripts/hooks/pretool-guard.ts +27 -52
- package/scripts/hooks/reserved-run.ts +1 -0
- package/scripts/hooks/run-hook.sh +10 -12
- package/scripts/hooks/stop-actions.ts +204 -0
- package/scripts/hooks/stop-guard.ts +62 -21
- package/scripts/init/hook-launch.ts +12 -7
- package/scripts/issue/expected-effect-lint.ts +59 -0
- package/scripts/issue/issue-cite-cli.ts +35 -15
- package/scripts/issue/issue-classification.ts +1 -1
- package/scripts/issue/issue-lint-cli.ts +5 -3
- package/scripts/issue/issue-scout-cli.ts +19 -14
- package/scripts/issue/markdown-section.ts +19 -5
- package/scripts/josh/command-usage.ts +110 -0
- package/scripts/josh/josh-command-map.ts +2 -0
- package/scripts/josh/josh-command-types.ts +55 -9
- package/scripts/josh/josh-commands-ai.ts +13 -0
- package/scripts/josh/josh-commands-development.ts +1 -1
- package/scripts/josh/josh-commands-hooks.ts +6 -0
- package/scripts/josh/josh-commands-lane.ts +10 -1
- package/scripts/josh/josh-commands-workflow.ts +5 -0
- package/scripts/josh/josh-logic.ts +6 -15
- package/scripts/josh/josh-usage-automation.ts +121 -0
- package/scripts/josh/josh-usage-backlog.ts +180 -0
- package/scripts/josh/josh-usage-developer.ts +230 -0
- package/scripts/josh/josh-usage-hooks.ts +38 -0
- package/scripts/josh/josh-usage-issue.ts +205 -0
- package/scripts/josh/josh-usage-review.ts +101 -0
- package/scripts/josh/josh-usage-run.ts +252 -0
- package/scripts/josh/josh-usage-session.ts +238 -0
- package/scripts/josh/josh-usage-workflow.ts +212 -0
- package/scripts/josh/josh.ts +14 -5
- package/scripts/josh/package-directory.ts +20 -0
- package/scripts/lane/lane-capacity.ts +8 -2
- package/scripts/lane/lane-check-stats.ts +56 -0
- package/scripts/lane/lane-child-invocation.ts +35 -4
- package/scripts/lane/lane-dispatch.ts +3 -3
- package/scripts/lane/lane-guard-policy.ts +2 -2
- package/scripts/lane/lane-handoff.ts +8 -1
- package/scripts/lane/lane-install.ts +12 -4
- package/scripts/lane/lane-ledger.ts +43 -1
- package/scripts/lane/lane-limit-cli.ts +8 -9
- package/scripts/lane/lane-measure-cli.ts +2 -0
- package/scripts/lane/lane-preserve.ts +29 -1
- package/scripts/lane/lane-registry.ts +9 -7
- package/scripts/lane/lane-restart.ts +5 -26
- package/scripts/lane/lane-session-action.ts +146 -0
- package/scripts/lane/lane-session-broker.ts +57 -138
- package/scripts/lane/lane-withdraw-cli.ts +71 -0
- package/scripts/lane/lane-withdraw.ts +182 -0
- package/scripts/lint/format.ts +4 -4
- package/scripts/lint/lint-parallel.ts +10 -3
- package/scripts/lint/lint-related-scope.ts +4 -1
- package/scripts/notify/telegram-test.ts +10 -5
- package/scripts/report/report-format-reference.ts +2 -0
- package/scripts/review/acceptance-map-check.ts +61 -0
- package/scripts/review/acceptance-map.ts +205 -0
- package/scripts/review/review-brief-cli.ts +1 -1
- package/scripts/rules/agent-model.ts +59 -0
- package/scripts/rules/delivered-rules.ts +11 -2
- package/scripts/rules/filing-cap.ts +1 -0
- package/scripts/rules/firing-point.ts +6 -5
- package/scripts/rules/guard-remedy.ts +117 -0
- package/scripts/rules/issue-comments.ts +67 -6
- package/scripts/rules/last-prompt.ts +50 -5
- package/scripts/rules/oracle-list-cli.ts +7 -0
- package/scripts/rules/piped-verification.ts +3 -1
- package/scripts/rules/rule-list.ts +4 -1
- package/scripts/rules/rule-registry-rows.ts +10 -0
- package/scripts/rules/rule-registry.ts +7 -4
- package/scripts/rules/rule-rewrite.ts +114 -0
- package/scripts/rules/rule-value.ts +7 -1
- package/scripts/rules/shell-segments.ts +15 -0
- package/scripts/rules/stop-decision.ts +77 -0
- package/scripts/rules/stop-rules.ts +147 -47
- package/scripts/rules/tail-commands.ts +15 -1
- package/scripts/run/board/run-board-cli.ts +2 -0
- package/scripts/run/board/run-board-closed.ts +8 -2
- package/scripts/run/board/run-board-github.ts +9 -1
- package/scripts/run/board/run-board-header.ts +4 -1
- package/scripts/run/board/run-board-labels.ts +2 -0
- package/scripts/run/board/run-board-layout.ts +1 -1
- package/scripts/run/board/run-board-read.ts +16 -0
- package/scripts/run/board/run-board-reason.ts +10 -1
- package/scripts/run/board/run-board-render-legend.ts +1 -0
- package/scripts/run/board/run-board-render-slot.ts +1 -1
- package/scripts/run/board/run-board-render-waits.ts +41 -0
- package/scripts/run/board/run-board-render.ts +6 -1
- package/scripts/run/board/run-board-row-yield.ts +1 -0
- package/scripts/run/board/run-board-state.ts +5 -0
- package/scripts/run/board/run-board-status.ts +72 -21
- package/scripts/run/board/run-board-tick.ts +5 -1
- package/scripts/run/cut/run-cut-cli.ts +3 -2
- package/scripts/run/cut/run-cut-report.ts +16 -0
- package/scripts/run/detached-launch.ts +23 -4
- package/scripts/run/entry/run-entry-cli.ts +8 -1
- package/scripts/run/event/run-event-render.ts +1 -0
- package/scripts/run/event/run-event-scope.ts +19 -1
- package/scripts/run/event/run-event-stream-emit.ts +13 -6
- package/scripts/run/event/run-event-stream.ts +4 -0
- package/scripts/run/hold/run-hold-session.ts +46 -0
- package/scripts/run/hold/run-hold.ts +7 -1
- package/scripts/run/launch-priority.ts +32 -0
- package/scripts/run/merge/run-merge-cli.ts +16 -65
- package/scripts/run/merge/run-merge-signals.ts +99 -0
- package/scripts/run/merge/run-merge-steps.ts +11 -1
- package/scripts/run/merge/run-merge.ts +21 -9
- package/scripts/run/run-liveness.ts +1 -1
- package/scripts/run/run-poll-hook.ts +157 -0
- package/scripts/run/run-step-cli.ts +22 -15
- package/scripts/run/run-step-section.ts +85 -0
- package/scripts/run/ship/run-ship-cli.ts +5 -12
- package/scripts/run/ship/run-ship-detach.ts +9 -0
- package/scripts/run/ship/run-ship-next.ts +10 -2
- package/scripts/run/ship/run-ship-overlap.ts +195 -0
- package/scripts/run/ship/run-ship-pre-detach.ts +33 -15
- package/scripts/run/ship/run-ship-preflight.ts +28 -2
- package/scripts/run/ship/run-ship-return.ts +31 -7
- package/scripts/run/ship/run-ship-review-steps.ts +12 -10
- package/scripts/run/ship/run-ship-steps.ts +1 -1
- package/scripts/run/ship/run-ship-stop-context.ts +206 -0
- package/scripts/run/ship/run-ship-sync.ts +14 -6
- package/scripts/test/test-e2e-guard.ts +30 -5
- package/scripts/test/test-unit-guard.ts +16 -1
- package/scripts/test/unit-worker-share.ts +26 -4
- package/scripts/time-runtime/time-shell.ts +29 -4
- package/scripts/time-runtime/time-spans.ts +1 -0
- package/scripts/time-runtime/time-tool-call.ts +7 -0
- package/templates/gitignore +6 -2
- package/dist/hooks/chunk-K4LMBQC2.js +0 -68
|
@@ -1,92 +1,99 @@
|
|
|
1
1
|
import {
|
|
2
2
|
duplicate_read_outcome
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-PF2NZL2A.js";
|
|
4
4
|
import {
|
|
5
5
|
ALREADY_DONE_LABEL,
|
|
6
6
|
CONTEXT_CUT_THRESHOLD,
|
|
7
7
|
IN_PROGRESS_LABEL,
|
|
8
8
|
NEEDS_DECISION_LABEL,
|
|
9
|
-
NEEDS_HUMAN_REVIEW_LABEL,
|
|
10
9
|
bash_triggers,
|
|
10
|
+
cost_cli,
|
|
11
|
+
cost_verdict,
|
|
11
12
|
filing_cap,
|
|
12
|
-
git_gh_api_path,
|
|
13
13
|
git_gh_command,
|
|
14
|
-
git_gh_exec,
|
|
15
14
|
git_gh_issue_read,
|
|
16
|
-
git_gh_pr_read,
|
|
17
15
|
has_any_label,
|
|
18
|
-
|
|
16
|
+
interactive_ask,
|
|
19
17
|
issue_watch_diff,
|
|
20
18
|
lane_background,
|
|
21
19
|
lane_park,
|
|
22
|
-
|
|
23
|
-
read_json_listing,
|
|
20
|
+
pre_gate_cut,
|
|
24
21
|
repo_party,
|
|
25
22
|
run_cut,
|
|
26
23
|
run_cut_handoff,
|
|
27
|
-
|
|
24
|
+
run_liveness,
|
|
28
25
|
run_tail_rule,
|
|
29
|
-
session_cite,
|
|
30
26
|
shell_segments,
|
|
31
27
|
tail_commands
|
|
32
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-SYOTDYCI.js";
|
|
33
29
|
import {
|
|
34
|
-
ancestor_directories,
|
|
35
30
|
find_local_bin_upwards,
|
|
36
31
|
json_object_schema,
|
|
37
32
|
string_array_schema,
|
|
38
33
|
string_record_schema,
|
|
39
34
|
vscode_settings_schema
|
|
40
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-EFXE6C37.js";
|
|
36
|
+
import {
|
|
37
|
+
distributed_paths
|
|
38
|
+
} from "./chunk-M4HGZV7U.js";
|
|
41
39
|
import {
|
|
42
|
-
agent_role_profile,
|
|
43
|
-
agent_session_role,
|
|
44
40
|
git_common_directory,
|
|
41
|
+
git_gh_api_path,
|
|
42
|
+
git_gh_exec,
|
|
43
|
+
has_stdout_field,
|
|
45
44
|
issue_cite,
|
|
46
45
|
lane_registry,
|
|
46
|
+
read_json_listing,
|
|
47
47
|
repo_origin,
|
|
48
48
|
run_event_scope,
|
|
49
49
|
run_event_stream,
|
|
50
50
|
run_event_stream_emit,
|
|
51
51
|
run_headless,
|
|
52
|
+
run_hold,
|
|
53
|
+
run_preflight,
|
|
54
|
+
session_cite,
|
|
52
55
|
session_language
|
|
53
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-WK6SMBIC.js";
|
|
57
|
+
import {
|
|
58
|
+
ancestor_directories
|
|
59
|
+
} from "./chunk-GP4IEC4O.js";
|
|
54
60
|
import {
|
|
55
61
|
error_text
|
|
56
62
|
} from "./chunk-CDY4NFQG.js";
|
|
57
63
|
import {
|
|
58
64
|
batch_outcome
|
|
59
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-A65Y4YOR.js";
|
|
60
66
|
import {
|
|
61
67
|
investigation_outcome
|
|
62
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-7DSBJVFH.js";
|
|
63
69
|
import {
|
|
64
70
|
investigation_reads
|
|
65
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-PTICX4OL.js";
|
|
72
|
+
import {
|
|
73
|
+
agent_role_profile,
|
|
74
|
+
agent_session_role
|
|
75
|
+
} from "./chunk-UPUZF3AN.js";
|
|
66
76
|
import {
|
|
67
77
|
lane_guard_policy
|
|
68
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-JP45SOCJ.js";
|
|
69
79
|
import {
|
|
70
80
|
hook_decision
|
|
71
|
-
} from "./chunk-
|
|
81
|
+
} from "./chunk-6TS2JD6D.js";
|
|
72
82
|
import {
|
|
73
|
-
cost_attribute,
|
|
74
83
|
cost_blocks,
|
|
75
|
-
open_issue_schema,
|
|
76
84
|
time_batch_guard,
|
|
77
85
|
time_density_hook,
|
|
78
|
-
|
|
79
|
-
|
|
86
|
+
time_hook_transcript,
|
|
87
|
+
time_shell,
|
|
88
|
+
time_spans
|
|
89
|
+
} from "./chunk-TNUMY6NL.js";
|
|
80
90
|
import {
|
|
81
91
|
lane_child_marker
|
|
82
|
-
} from "./chunk-
|
|
92
|
+
} from "./chunk-LAOV7NLM.js";
|
|
83
93
|
import {
|
|
84
94
|
GIT_LOCATION_VARIABLES,
|
|
85
95
|
PORCELAIN_FLAG,
|
|
86
96
|
UNTRACKED_FILES_FLAG,
|
|
87
|
-
cli_flags,
|
|
88
|
-
cost_transcript,
|
|
89
|
-
cost_usage,
|
|
90
97
|
file_reader,
|
|
91
98
|
git_command,
|
|
92
99
|
git_diff_reads,
|
|
@@ -94,11 +101,10 @@ import {
|
|
|
94
101
|
issue_number_shape,
|
|
95
102
|
json_value,
|
|
96
103
|
lane_paths,
|
|
97
|
-
|
|
104
|
+
open_issue_schema,
|
|
98
105
|
run_carry
|
|
99
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-APUO6U4J.js";
|
|
100
107
|
import {
|
|
101
|
-
PLATFORM_TEMP_ROOT,
|
|
102
108
|
PROBE_TIMEOUT_MS,
|
|
103
109
|
PROJECT_ROOT,
|
|
104
110
|
package_path,
|
|
@@ -116,9 +122,9 @@ var HEADER_BODY_SEPARATOR = /\r?\n\r?\n/u;
|
|
|
116
122
|
var ETAG_HEADER = /^etag: *(?<etag>[^\r\n]+)/imu;
|
|
117
123
|
var UNCHANGED = { kind: "unchanged" };
|
|
118
124
|
var UNREADABLE = { kind: "unreadable" };
|
|
119
|
-
function to_args(
|
|
125
|
+
function to_args(path13, etag) {
|
|
120
126
|
const header = etag === void 0 ? [] : [HEADER_FLAG, `${IF_NONE_MATCH}${etag}`];
|
|
121
|
-
return ["api", INCLUDE_FLAG, ...header,
|
|
127
|
+
return ["api", INCLUDE_FLAG, ...header, path13];
|
|
122
128
|
}
|
|
123
129
|
function to_changed(output) {
|
|
124
130
|
const [headers = "", ...rest] = output.split(HEADER_BODY_SEPARATOR);
|
|
@@ -132,9 +138,9 @@ function failure_status(error) {
|
|
|
132
138
|
const cause = error instanceof Error ? error.cause : void 0;
|
|
133
139
|
return has_stdout_field(cause) ? git_gh_exec.parse_status_line(cause.stdout) : void 0;
|
|
134
140
|
}
|
|
135
|
-
async function read_conditional(
|
|
141
|
+
async function read_conditional(path13, etag, timeout_ms) {
|
|
136
142
|
try {
|
|
137
|
-
return to_read(await git_gh_exec.exec_gh_command(to_args(
|
|
143
|
+
return to_read(await git_gh_exec.exec_gh_command(to_args(path13, etag), timeout_ms));
|
|
138
144
|
} catch (error) {
|
|
139
145
|
return failure_status(error) === NOT_MODIFIED_STATUS ? UNCHANGED : UNREADABLE;
|
|
140
146
|
}
|
|
@@ -178,16 +184,16 @@ async function read_snapshot(request2, body, etag) {
|
|
|
178
184
|
return comments === void 0 ? UNREADABLE2 : { kind: "read", snapshot: { body, comments }, etag };
|
|
179
185
|
}
|
|
180
186
|
async function fetch_issue(request2) {
|
|
181
|
-
const
|
|
187
|
+
const read2 = await git_gh_conditional.read_conditional(
|
|
182
188
|
git_gh_api_path.issue_api_path(request2.issue),
|
|
183
189
|
request2.etag,
|
|
184
190
|
request2.timeout_ms
|
|
185
191
|
);
|
|
186
|
-
if (
|
|
187
|
-
const fields = json_value.parse_with(
|
|
192
|
+
if (read2.kind !== "changed") return read2;
|
|
193
|
+
const fields = json_value.parse_with(read2.body, issue_schema);
|
|
188
194
|
if (fields === void 0) return UNREADABLE2;
|
|
189
195
|
if (fields.state === CLOSED_STATE) return { kind: "closed" };
|
|
190
|
-
return await read_snapshot(request2, fields.body ?? "",
|
|
196
|
+
return await read_snapshot(request2, fields.body ?? "", read2.etag);
|
|
191
197
|
}
|
|
192
198
|
function fresh_record(issue, fetched, now, acknowledged_at = now.toISOString()) {
|
|
193
199
|
const baseline = issue_watch_diff.baseline_of(fetched.snapshot);
|
|
@@ -542,12 +548,41 @@ async function mark_implement(directory = process.cwd(), source = process.env) {
|
|
|
542
548
|
}
|
|
543
549
|
var lane_phase = { mark_implement };
|
|
544
550
|
|
|
551
|
+
// scripts/rules/agent-model.ts
|
|
552
|
+
var SUBAGENT_TOOLS = /* @__PURE__ */ new Set(["Agent", "Task"]);
|
|
553
|
+
var GENERAL_PURPOSE = "general-purpose";
|
|
554
|
+
function is_general_purpose(call) {
|
|
555
|
+
if (!SUBAGENT_TOOLS.has(call.name) || !json_value.is_record(call.input)) return false;
|
|
556
|
+
const type = call.input["subagent_type"];
|
|
557
|
+
return type === void 0 || type === GENERAL_PURPOSE;
|
|
558
|
+
}
|
|
559
|
+
function names_model(call) {
|
|
560
|
+
const model = json_value.is_record(call.input) ? call.input["model"] : void 0;
|
|
561
|
+
return typeof model === "string" && model.length > 0;
|
|
562
|
+
}
|
|
563
|
+
function is_unnamed_model(call) {
|
|
564
|
+
return is_general_purpose(call) && !names_model(call);
|
|
565
|
+
}
|
|
566
|
+
function keeps_model(call) {
|
|
567
|
+
return is_general_purpose(call) && names_model(call);
|
|
568
|
+
}
|
|
569
|
+
var AGENT_MODEL_REASON = "\u26D4 agent model: a `general-purpose` subagent with no `model` inherits the parent model. Reissue the call with `model` set \u2014 `sonnet` for routine work, `opus` for judgment such as a review. It fires on every occurrence (`.claude/skills/workflow-commands/delegation.md`).";
|
|
570
|
+
var ROW = {
|
|
571
|
+
id: "agent-model",
|
|
572
|
+
is_trigger: is_unnamed_model,
|
|
573
|
+
reason: AGENT_MODEL_REASON,
|
|
574
|
+
decide: () => true,
|
|
575
|
+
keeps: keeps_model,
|
|
576
|
+
reaches: is_general_purpose
|
|
577
|
+
};
|
|
578
|
+
var agent_model = { AGENT_MODEL_REASON, ROW, is_unnamed_model };
|
|
579
|
+
|
|
545
580
|
// scripts/rules/direct-filing.ts
|
|
546
581
|
var DIRECT_FILING_REASON = '\u26D4 direct filing: an Issue is filed with `pnpm josh issue:file "<title>" --body-file <path> --depth <0|1|2>`, never with `gh api \u2026/issues` or `gh issue create` \u2014 it runs the scout, the lint, the labels and `epic:bundle` itself. It fires on every occurrence (`docs/josh-commands-backlog.md` \u2192 "`josh issue:file`").';
|
|
547
582
|
function is_any_filing(command) {
|
|
548
583
|
return bash_triggers.is_direct_filing(command) || bash_triggers.is_issue_filing(command);
|
|
549
584
|
}
|
|
550
|
-
var
|
|
585
|
+
var ROW2 = {
|
|
551
586
|
id: "direct-filing",
|
|
552
587
|
is_trigger: bash_triggers.on_bash_command(bash_triggers.is_direct_filing),
|
|
553
588
|
reason: DIRECT_FILING_REASON,
|
|
@@ -555,7 +590,7 @@ var ROW = {
|
|
|
555
590
|
keeps: bash_triggers.on_bash_command(bash_triggers.is_issue_filing),
|
|
556
591
|
reaches: bash_triggers.on_bash_command(is_any_filing)
|
|
557
592
|
};
|
|
558
|
-
var direct_filing = { DIRECT_FILING_REASON, ROW };
|
|
593
|
+
var direct_filing = { DIRECT_FILING_REASON, ROW: ROW2 };
|
|
559
594
|
|
|
560
595
|
// scripts/run/progress/run-progress.ts
|
|
561
596
|
var DEFAULT_INTERVAL_MINUTES = 20;
|
|
@@ -892,12 +927,12 @@ function landing_ms(command, now_ms, last_report_ms) {
|
|
|
892
927
|
const lands_ms = now_ms + duration_ms;
|
|
893
928
|
return run_progress.is_due(last_report_ms, lands_ms, interval_ms) ? lands_ms : void 0;
|
|
894
929
|
}
|
|
895
|
-
function decide(call,
|
|
930
|
+
function decide(call, run, can_record) {
|
|
896
931
|
const last_report_ms = run_progress_clock.read_last_report_sync();
|
|
897
932
|
if (last_report_ms === void 0) return false;
|
|
898
|
-
const target = ARM_RECORD.path(
|
|
899
|
-
if (is_armed(target,
|
|
900
|
-
const lands_ms = landing_ms(time_shell.bash_command(call.input),
|
|
933
|
+
const target = ARM_RECORD.path(run.transcript);
|
|
934
|
+
if (is_armed(target, run.now_ms)) return true;
|
|
935
|
+
const lands_ms = landing_ms(time_shell.bash_command(call.input), run.now_ms, last_report_ms);
|
|
901
936
|
if (lands_ms === void 0) return true;
|
|
902
937
|
if (can_record) ARM_RECORD.record(target, lands_ms);
|
|
903
938
|
return false;
|
|
@@ -1001,7 +1036,7 @@ function carries_a_file_body(command, has_file = existsSync) {
|
|
|
1001
1036
|
);
|
|
1002
1037
|
}
|
|
1003
1038
|
var FILE_BODY_REASON = "\u26D4 file body in a shell command: this carries a file's new text inline, which is re-read on every later request. Edit a region with the Edit tool, rewrite a whole file with the Write tool, and pass a body by path (`--body-file <path>`); a new-file `cat > <new-file> <<EOF` stays allowed. This rule fires on every occurrence (`prompts/collaboration-workflow/file-edits.md`).";
|
|
1004
|
-
var
|
|
1039
|
+
var ROW3 = {
|
|
1005
1040
|
id: "file-body",
|
|
1006
1041
|
is_trigger: bash_triggers.on_bash_command((command) => carries_a_file_body(command)),
|
|
1007
1042
|
reason: FILE_BODY_REASON,
|
|
@@ -1009,7 +1044,7 @@ var ROW2 = {
|
|
|
1009
1044
|
};
|
|
1010
1045
|
var file_body = {
|
|
1011
1046
|
FILE_BODY_REASON,
|
|
1012
|
-
ROW:
|
|
1047
|
+
ROW: ROW3,
|
|
1013
1048
|
carries_a_file_body
|
|
1014
1049
|
};
|
|
1015
1050
|
|
|
@@ -1112,7 +1147,7 @@ function is_force_or_delete(command) {
|
|
|
1112
1147
|
return shell_segments.segments_of(command).some((segment) => is_destructive_segment(segment));
|
|
1113
1148
|
}
|
|
1114
1149
|
var GIT_FORCE_REASON = "\u26D4 force push or branch delete: this rewrites or removes shared history, which is Tier C and needs explicit current-turn user instruction. Push with `pnpm josh git`; leave a force push or branch delete to the user's own terminal. This rule fires on every occurrence (`prompts/collaboration-workflow/operating-rules.md`).";
|
|
1115
|
-
var
|
|
1150
|
+
var ROW4 = {
|
|
1116
1151
|
id: "git-force",
|
|
1117
1152
|
is_trigger: bash_triggers.on_bash_command(is_force_or_delete),
|
|
1118
1153
|
reason: GIT_FORCE_REASON,
|
|
@@ -1120,376 +1155,10 @@ var ROW3 = {
|
|
|
1120
1155
|
};
|
|
1121
1156
|
var git_force = {
|
|
1122
1157
|
GIT_FORCE_REASON,
|
|
1123
|
-
ROW:
|
|
1158
|
+
ROW: ROW4,
|
|
1124
1159
|
is_force_or_delete
|
|
1125
1160
|
};
|
|
1126
1161
|
|
|
1127
|
-
// scripts/cost-runtime/cost-cli.ts
|
|
1128
|
-
import { fileURLToPath } from "node:url";
|
|
1129
|
-
|
|
1130
|
-
// scripts/cost-runtime/codex-usage.ts
|
|
1131
|
-
import { globSync, readFileSync as readFileSync2 } from "node:fs";
|
|
1132
|
-
import path2 from "node:path";
|
|
1133
|
-
import { z as z4 } from "zod";
|
|
1134
|
-
var THREAD_ID_PATTERN = /^[A-Za-z0-9-]+$/u;
|
|
1135
|
-
var SESSION_META_SCHEMA = z4.looseObject({
|
|
1136
|
-
type: z4.literal("session_meta"),
|
|
1137
|
-
payload: z4.looseObject({ id: z4.string(), cwd: z4.string() })
|
|
1138
|
-
});
|
|
1139
|
-
var TOTAL_USAGE_SCHEMA = z4.looseObject({ input_tokens: z4.number().nonnegative() });
|
|
1140
|
-
var TOKEN_COUNT_SCHEMA = z4.looseObject({
|
|
1141
|
-
type: z4.literal("event_msg"),
|
|
1142
|
-
payload: z4.looseObject({
|
|
1143
|
-
type: z4.literal("token_count"),
|
|
1144
|
-
info: z4.looseObject({
|
|
1145
|
-
total_token_usage: TOTAL_USAGE_SCHEMA,
|
|
1146
|
-
last_token_usage: TOTAL_USAGE_SCHEMA
|
|
1147
|
-
})
|
|
1148
|
-
})
|
|
1149
|
-
});
|
|
1150
|
-
function same_project(cwd, target) {
|
|
1151
|
-
return cost_transcript.session_cwd(cwd) === cost_transcript.session_cwd(target);
|
|
1152
|
-
}
|
|
1153
|
-
function billed_per_request(usages) {
|
|
1154
|
-
return usages.map((usage) => usage.last_token_usage.input_tokens);
|
|
1155
|
-
}
|
|
1156
|
-
function measurement_from(content, target, thread_id) {
|
|
1157
|
-
const values = content.split("\n").map((line) => json_value.parse_or_undefined(line));
|
|
1158
|
-
const metadata = values.flatMap((value) => {
|
|
1159
|
-
const parsed = SESSION_META_SCHEMA.safeParse(value);
|
|
1160
|
-
return parsed.success ? [parsed.data] : [];
|
|
1161
|
-
});
|
|
1162
|
-
const usages = values.flatMap((value) => {
|
|
1163
|
-
const parsed = TOKEN_COUNT_SCHEMA.safeParse(value);
|
|
1164
|
-
return parsed.success ? [parsed.data.payload.info] : [];
|
|
1165
|
-
});
|
|
1166
|
-
const session = metadata.find((entry) => entry.payload.id === thread_id);
|
|
1167
|
-
if (session === void 0 || usages.length === 0 || !same_project(session.payload.cwd, target)) {
|
|
1168
|
-
return void 0;
|
|
1169
|
-
}
|
|
1170
|
-
return { billed_input_per_request: billed_per_request(usages) };
|
|
1171
|
-
}
|
|
1172
|
-
function rollout_files(home, thread_id) {
|
|
1173
|
-
if (!THREAD_ID_PATTERN.test(thread_id)) return [];
|
|
1174
|
-
return globSync(`sessions/**/*${thread_id}.jsonl`, { cwd: home }).map(
|
|
1175
|
-
(file) => path2.join(home, file)
|
|
1176
|
-
);
|
|
1177
|
-
}
|
|
1178
|
-
function read_measurement(file, target, thread_id) {
|
|
1179
|
-
try {
|
|
1180
|
-
return measurement_from(readFileSync2(file, "utf8"), target, thread_id);
|
|
1181
|
-
} catch {
|
|
1182
|
-
return void 0;
|
|
1183
|
-
}
|
|
1184
|
-
}
|
|
1185
|
-
function latest_measurement(files, target, thread_id) {
|
|
1186
|
-
for (const file of files.toReversed()) {
|
|
1187
|
-
const measured = read_measurement(file, target, thread_id);
|
|
1188
|
-
if (measured !== void 0) return measured;
|
|
1189
|
-
}
|
|
1190
|
-
return void 0;
|
|
1191
|
-
}
|
|
1192
|
-
function measurement(target, default_home, environment = process.env) {
|
|
1193
|
-
const thread_id = environment["CODEX_THREAD_ID"];
|
|
1194
|
-
if (thread_id === void 0) return void 0;
|
|
1195
|
-
const home = environment["CODEX_HOME"] ?? path2.join(default_home, ".codex");
|
|
1196
|
-
return latest_measurement(rollout_files(home, thread_id), target, thread_id);
|
|
1197
|
-
}
|
|
1198
|
-
var codex_usage = { measurement };
|
|
1199
|
-
|
|
1200
|
-
// scripts/cost-runtime/cost-corpus.ts
|
|
1201
|
-
function accumulate_missing(sessions) {
|
|
1202
|
-
return {
|
|
1203
|
-
no_usage_lines: sessions.reduce((sum, session) => sum + session.no_usage_lines, 0),
|
|
1204
|
-
malformed_lines: sessions.reduce((sum, session) => sum + session.malformed_lines, 0),
|
|
1205
|
-
unreadable_sessions: sessions.filter((session) => !session.is_readable).length,
|
|
1206
|
-
// Filled by the attribution, which is the only step that knows a unit could not follow its
|
|
1207
|
-
// parent; a per-session tally cannot see it, so it is zero here and set for an issue scope below.
|
|
1208
|
-
unattributed_sessions: 0
|
|
1209
|
-
};
|
|
1210
|
-
}
|
|
1211
|
-
function load_corpus(cwd) {
|
|
1212
|
-
const files = cost_transcript.list_sessions_across(cost_transcript.transcript_directories(cwd));
|
|
1213
|
-
const sessions = files.map((file) => cost_transcript.read_session(file));
|
|
1214
|
-
return { sessions, files, missing: accumulate_missing(sessions) };
|
|
1215
|
-
}
|
|
1216
|
-
function session_meta(corpus) {
|
|
1217
|
-
return new Map(
|
|
1218
|
-
corpus.files.map((file) => [
|
|
1219
|
-
file.session_id,
|
|
1220
|
-
{ is_delegated: file.is_delegated, owner: cost_transcript.owning_session_id(file) }
|
|
1221
|
-
])
|
|
1222
|
-
);
|
|
1223
|
-
}
|
|
1224
|
-
function issue_set(records) {
|
|
1225
|
-
const issues = cost_attribute.group_by_issue(records).map((group) => group.issue).filter((issue) => issue !== cost_attribute.UNATTRIBUTED_KEY);
|
|
1226
|
-
return new Set(issues);
|
|
1227
|
-
}
|
|
1228
|
-
function sole_of(issues) {
|
|
1229
|
-
if (issues.size !== 1) return cost_attribute.UNATTRIBUTED_KEY;
|
|
1230
|
-
return [...issues][0] ?? cost_attribute.UNATTRIBUTED_KEY;
|
|
1231
|
-
}
|
|
1232
|
-
function owner_sets(corpus, meta) {
|
|
1233
|
-
const own = corpus.sessions.filter(
|
|
1234
|
-
(session) => meta.get(session.session_id)?.is_delegated !== true
|
|
1235
|
-
);
|
|
1236
|
-
return new Map(own.map((session) => [session.session_id, issue_set(session.records)]));
|
|
1237
|
-
}
|
|
1238
|
-
function pairs_with_inherited(session, inherited, is_delegated) {
|
|
1239
|
-
return cost_attribute.group_by_issue(session.records).flatMap(
|
|
1240
|
-
(group) => group.records.map((record2) => ({
|
|
1241
|
-
record: record2,
|
|
1242
|
-
issue: group.issue === cost_attribute.UNATTRIBUTED_KEY ? inherited : group.issue,
|
|
1243
|
-
baseline_tokens: session.baseline_tokens,
|
|
1244
|
-
session_id: session.session_id,
|
|
1245
|
-
is_delegated
|
|
1246
|
-
}))
|
|
1247
|
-
);
|
|
1248
|
-
}
|
|
1249
|
-
var NO_ISSUES = /* @__PURE__ */ new Set();
|
|
1250
|
-
function parent_issues(session, meta, owners) {
|
|
1251
|
-
const entry = meta.get(session.session_id);
|
|
1252
|
-
if (entry?.is_delegated !== true) return NO_ISSUES;
|
|
1253
|
-
return owners.get(entry.owner) ?? NO_ISSUES;
|
|
1254
|
-
}
|
|
1255
|
-
function pairs_of_session(session, meta, owners) {
|
|
1256
|
-
const is_delegated = meta.get(session.session_id)?.is_delegated === true;
|
|
1257
|
-
const candidates = parent_issues(session, meta, owners);
|
|
1258
|
-
const inherited = is_delegated ? sole_of(candidates) : cost_attribute.UNATTRIBUTED_KEY;
|
|
1259
|
-
const pairs = pairs_with_inherited(session, inherited, is_delegated);
|
|
1260
|
-
const has_unattributed = pairs.some((pair) => pair.issue === cost_attribute.UNATTRIBUTED_KEY);
|
|
1261
|
-
if (!is_delegated || !has_unattributed) return { pairs };
|
|
1262
|
-
return { pairs, unattributed_candidates: candidates };
|
|
1263
|
-
}
|
|
1264
|
-
function attribute_corpus(corpus) {
|
|
1265
|
-
const meta = session_meta(corpus);
|
|
1266
|
-
const owners = owner_sets(corpus, meta);
|
|
1267
|
-
const per_session = corpus.sessions.map((session) => pairs_of_session(session, meta, owners));
|
|
1268
|
-
return {
|
|
1269
|
-
pairs: per_session.flatMap((one) => one.pairs),
|
|
1270
|
-
unattributed: per_session.flatMap(
|
|
1271
|
-
(one) => one.unattributed_candidates === void 0 ? [] : [one.unattributed_candidates]
|
|
1272
|
-
)
|
|
1273
|
-
};
|
|
1274
|
-
}
|
|
1275
|
-
function floor_for_issue(unattributed, issue_number) {
|
|
1276
|
-
return unattributed.filter((set) => set.size === 0 || set.has(issue_number)).length;
|
|
1277
|
-
}
|
|
1278
|
-
function is_better(candidate, existing) {
|
|
1279
|
-
const { UNATTRIBUTED_KEY } = cost_attribute;
|
|
1280
|
-
return existing.issue === UNATTRIBUTED_KEY && candidate.issue !== UNATTRIBUTED_KEY;
|
|
1281
|
-
}
|
|
1282
|
-
function values_of(best) {
|
|
1283
|
-
const collected = [];
|
|
1284
|
-
for (const [, pair] of best) collected.push(pair);
|
|
1285
|
-
return collected;
|
|
1286
|
-
}
|
|
1287
|
-
function dedupe_across_sessions(pairs) {
|
|
1288
|
-
const best = /* @__PURE__ */ new Map();
|
|
1289
|
-
for (const pair of pairs) {
|
|
1290
|
-
const existing = best.get(pair.record.request_id);
|
|
1291
|
-
if (existing === void 0 || is_better(pair, existing)) {
|
|
1292
|
-
best.set(pair.record.request_id, pair);
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
return values_of(best);
|
|
1296
|
-
}
|
|
1297
|
-
function attributed(corpus) {
|
|
1298
|
-
return dedupe_across_sessions(attribute_corpus(corpus).pairs);
|
|
1299
|
-
}
|
|
1300
|
-
function mainline_records(pairs) {
|
|
1301
|
-
const groups = /* @__PURE__ */ new Map();
|
|
1302
|
-
for (const pair of pairs) {
|
|
1303
|
-
if (pair.is_delegated) continue;
|
|
1304
|
-
groups.set(pair.session_id, [...groups.get(pair.session_id) ?? [], pair.record]);
|
|
1305
|
-
}
|
|
1306
|
-
return [...groups.values()];
|
|
1307
|
-
}
|
|
1308
|
-
var cost_corpus = {
|
|
1309
|
-
load_corpus,
|
|
1310
|
-
attribute_corpus,
|
|
1311
|
-
floor_for_issue,
|
|
1312
|
-
attributed,
|
|
1313
|
-
mainline_records
|
|
1314
|
-
};
|
|
1315
|
-
|
|
1316
|
-
// scripts/cost-runtime/cost-verdict.ts
|
|
1317
|
-
var FAILURE_EXIT_CODE = 1;
|
|
1318
|
-
var OVER_VERDICT = "over";
|
|
1319
|
-
var UNDER_VERDICT = "under";
|
|
1320
|
-
function per_request_cost(measurement2) {
|
|
1321
|
-
return measurement2.billed_input_per_request.at(-1) ?? 0;
|
|
1322
|
-
}
|
|
1323
|
-
function classify(measurement2, limit) {
|
|
1324
|
-
return per_request_cost(measurement2) > limit ? OVER_VERDICT : UNDER_VERDICT;
|
|
1325
|
-
}
|
|
1326
|
-
function over_summary(measurement2, limit) {
|
|
1327
|
-
const total = measurement2.billed_input_per_request.length;
|
|
1328
|
-
return `${String(per_request_cost(measurement2))} billed input tokens per request, on the newest of ${String(total)} request(s); limit ${String(limit)}`;
|
|
1329
|
-
}
|
|
1330
|
-
function report_over(measurement2, limit) {
|
|
1331
|
-
if (measurement2 === void 0 || measurement2.billed_input_per_request.length === 0) {
|
|
1332
|
-
console.error("No requests in this session; there is nothing to hand off.");
|
|
1333
|
-
return FAILURE_EXIT_CODE;
|
|
1334
|
-
}
|
|
1335
|
-
console.info(classify(measurement2, limit));
|
|
1336
|
-
console.error(over_summary(measurement2, limit));
|
|
1337
|
-
return 0;
|
|
1338
|
-
}
|
|
1339
|
-
var cost_verdict = {
|
|
1340
|
-
OVER_VERDICT,
|
|
1341
|
-
UNDER_VERDICT,
|
|
1342
|
-
classify,
|
|
1343
|
-
per_request_cost,
|
|
1344
|
-
report_over
|
|
1345
|
-
};
|
|
1346
|
-
|
|
1347
|
-
// scripts/cost-runtime/transcript-cwd.ts
|
|
1348
|
-
import path3 from "node:path";
|
|
1349
|
-
function resolve(target, cwd) {
|
|
1350
|
-
return target === void 0 ? cwd : path3.resolve(target);
|
|
1351
|
-
}
|
|
1352
|
-
var transcript_cwd = { resolve };
|
|
1353
|
-
|
|
1354
|
-
// scripts/cost-runtime/cost-cli.ts
|
|
1355
|
-
var ARGV_OFFSET = 2;
|
|
1356
|
-
var FAILURE_EXIT_CODE2 = 1;
|
|
1357
|
-
var USAGE = "Usage: josh cost (--cut | --over <tokens-per-request>) [--path <dir>]";
|
|
1358
|
-
var UNMEASURABLE_VERDICT = "unmeasurable";
|
|
1359
|
-
function to_threshold(raw) {
|
|
1360
|
-
if (raw === void 0 || raw.trim() === "") return void 0;
|
|
1361
|
-
const parsed = Number(raw);
|
|
1362
|
-
return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : void 0;
|
|
1363
|
-
}
|
|
1364
|
-
function is_unparsed(raw, parsed) {
|
|
1365
|
-
return parsed === void 0 && raw !== void 0;
|
|
1366
|
-
}
|
|
1367
|
-
function selected_threshold(values) {
|
|
1368
|
-
if (values.cut === true) return CONTEXT_CUT_THRESHOLD;
|
|
1369
|
-
return to_threshold(values.over);
|
|
1370
|
-
}
|
|
1371
|
-
function threshold_option(over) {
|
|
1372
|
-
return over === void 0 ? {} : { over };
|
|
1373
|
-
}
|
|
1374
|
-
function path_option(path16) {
|
|
1375
|
-
return path16 === void 0 ? {} : { path: path16 };
|
|
1376
|
-
}
|
|
1377
|
-
function to_options(values) {
|
|
1378
|
-
if (values.cut === true && values.over !== void 0) return void 0;
|
|
1379
|
-
const over = selected_threshold(values);
|
|
1380
|
-
if (is_unparsed(values.over, over)) return void 0;
|
|
1381
|
-
return { ...threshold_option(over), ...path_option(values.path) };
|
|
1382
|
-
}
|
|
1383
|
-
var PARSE_ARGS_OPTIONS = {
|
|
1384
|
-
cut: { type: "boolean" },
|
|
1385
|
-
over: { type: "string" },
|
|
1386
|
-
path: { type: "string" }
|
|
1387
|
-
};
|
|
1388
|
-
function parse_options(argv) {
|
|
1389
|
-
const values = cli_flags.values_of(argv, PARSE_ARGS_OPTIONS);
|
|
1390
|
-
return values === void 0 ? void 0 : to_options(values);
|
|
1391
|
-
}
|
|
1392
|
-
function report_empty(cwd, session_id) {
|
|
1393
|
-
const searched = cost_transcript.searched_directories(cost_transcript.transcript_directories(cwd));
|
|
1394
|
-
for (const line of cost_transcript.missing_message(searched, session_id)) console.error(line);
|
|
1395
|
-
return FAILURE_EXIT_CODE2;
|
|
1396
|
-
}
|
|
1397
|
-
function provider_of(environment) {
|
|
1398
|
-
const resolved = agent_role_profile.resolve_provider(environment);
|
|
1399
|
-
if (resolved.kind !== "provider" || resolved.is_default === true) return void 0;
|
|
1400
|
-
return resolved.provider;
|
|
1401
|
-
}
|
|
1402
|
-
function measurement_of(session) {
|
|
1403
|
-
return {
|
|
1404
|
-
billed_input_per_request: session.records.map(
|
|
1405
|
-
(record2) => cost_usage.billed_input(record2.totals)
|
|
1406
|
-
)
|
|
1407
|
-
};
|
|
1408
|
-
}
|
|
1409
|
-
function anthropic_own(target, environment) {
|
|
1410
|
-
const corpus = cost_corpus.load_corpus(target);
|
|
1411
|
-
const selection = own_session.select_own_session(corpus.files, environment);
|
|
1412
|
-
if (selection.kind === "absent") return { kind: "absent", session_id: selection.session_id };
|
|
1413
|
-
const session = corpus.sessions[selection.index];
|
|
1414
|
-
if (session === void 0) return { kind: "empty" };
|
|
1415
|
-
return { kind: "measured", measurement: measurement_of(session) };
|
|
1416
|
-
}
|
|
1417
|
-
function anthropic_measurement(target, environment) {
|
|
1418
|
-
const own = anthropic_own(target, environment);
|
|
1419
|
-
return own.kind === "measured" ? own.measurement : void 0;
|
|
1420
|
-
}
|
|
1421
|
-
function same_openai_project(target, cwd) {
|
|
1422
|
-
return cost_transcript.session_cwd(target) === cost_transcript.session_cwd(cwd);
|
|
1423
|
-
}
|
|
1424
|
-
function reject_openai_cross_project(context, target, cwd) {
|
|
1425
|
-
if (context.provider !== "openai" || context.path === void 0 || same_openai_project(target, cwd)) {
|
|
1426
|
-
return false;
|
|
1427
|
-
}
|
|
1428
|
-
console.error(
|
|
1429
|
-
"OpenAI --path cannot select a thread from another project; run josh cost in that project."
|
|
1430
|
-
);
|
|
1431
|
-
return true;
|
|
1432
|
-
}
|
|
1433
|
-
function measure(target, provider, environment) {
|
|
1434
|
-
return provider === "openai" ? codex_usage.measurement(target, cost_transcript.home_directory(), environment) : anthropic_measurement(target, environment);
|
|
1435
|
-
}
|
|
1436
|
-
function run_over_anthropic(own, target, limit) {
|
|
1437
|
-
if (own.kind === "measured") return cost_verdict.report_over(own.measurement, limit);
|
|
1438
|
-
return report_empty(target, own.kind === "absent" ? own.session_id : void 0);
|
|
1439
|
-
}
|
|
1440
|
-
function run_over_codex(target, limit, environment) {
|
|
1441
|
-
const measurement2 = measure(target, "openai", environment);
|
|
1442
|
-
if (measurement2 !== void 0) return cost_verdict.report_over(measurement2, limit);
|
|
1443
|
-
console.error(`No Codex usage found for the current OpenAI thread under ${target}.`);
|
|
1444
|
-
return FAILURE_EXIT_CODE2;
|
|
1445
|
-
}
|
|
1446
|
-
function run_over(target, limit, provider, environment) {
|
|
1447
|
-
if (provider === "anthropic") {
|
|
1448
|
-
return run_over_anthropic(anthropic_own(target, environment), target, limit);
|
|
1449
|
-
}
|
|
1450
|
-
return run_over_codex(target, limit, environment);
|
|
1451
|
-
}
|
|
1452
|
-
function verdict_of(measurement2) {
|
|
1453
|
-
if (measurement2 === void 0 || measurement2.billed_input_per_request.length === 0) {
|
|
1454
|
-
return UNMEASURABLE_VERDICT;
|
|
1455
|
-
}
|
|
1456
|
-
return cost_verdict.classify(measurement2, CONTEXT_CUT_THRESHOLD);
|
|
1457
|
-
}
|
|
1458
|
-
function session_verdict(cwd = process.cwd(), environment = process.env) {
|
|
1459
|
-
const provider = provider_of(environment);
|
|
1460
|
-
if (provider === void 0) return UNMEASURABLE_VERDICT;
|
|
1461
|
-
return verdict_of(measure(cwd, provider, environment));
|
|
1462
|
-
}
|
|
1463
|
-
function run_context(argv, environment) {
|
|
1464
|
-
const options = parse_options(argv);
|
|
1465
|
-
if (options?.over === void 0) return void 0;
|
|
1466
|
-
const provider = provider_of(environment);
|
|
1467
|
-
if (provider === void 0) return void 0;
|
|
1468
|
-
return { over: options.over, path: options.path, provider };
|
|
1469
|
-
}
|
|
1470
|
-
function run(argv, cwd = process.cwd(), environment = process.env) {
|
|
1471
|
-
const context = run_context(argv, environment);
|
|
1472
|
-
if (context === void 0) {
|
|
1473
|
-
console.error(USAGE);
|
|
1474
|
-
return FAILURE_EXIT_CODE2;
|
|
1475
|
-
}
|
|
1476
|
-
const target = transcript_cwd.resolve(context.path, cwd);
|
|
1477
|
-
if (reject_openai_cross_project(context, target, cwd)) return FAILURE_EXIT_CODE2;
|
|
1478
|
-
return run_over(target, context.over, context.provider, environment);
|
|
1479
|
-
}
|
|
1480
|
-
function main(argv) {
|
|
1481
|
-
process.exitCode = run(argv);
|
|
1482
|
-
}
|
|
1483
|
-
var cost_cli = {
|
|
1484
|
-
UNMEASURABLE_VERDICT,
|
|
1485
|
-
USAGE,
|
|
1486
|
-
parse_options,
|
|
1487
|
-
to_threshold,
|
|
1488
|
-
run,
|
|
1489
|
-
session_verdict
|
|
1490
|
-
};
|
|
1491
|
-
if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(ARGV_OFFSET));
|
|
1492
|
-
|
|
1493
1162
|
// scripts/cost-runtime/cost-format.ts
|
|
1494
1163
|
var USD_DECIMALS = 4;
|
|
1495
1164
|
var PERCENT_SCALE = 100;
|
|
@@ -1511,9 +1180,9 @@ var cost_format = {
|
|
|
1511
1180
|
};
|
|
1512
1181
|
|
|
1513
1182
|
// scripts/run/cut/run-cut-decline.ts
|
|
1514
|
-
import { z as
|
|
1183
|
+
import { z as z4 } from "zod";
|
|
1515
1184
|
var DECLINE_PREFIX = "josh-run-cut-decline-";
|
|
1516
|
-
var decline_schema =
|
|
1185
|
+
var decline_schema = z4.object({ issue: z4.string(), hold_taken_at: z4.string().optional() });
|
|
1517
1186
|
function decline_path(git_directory) {
|
|
1518
1187
|
return stamp_file.stamp_path(DECLINE_PREFIX, git_directory);
|
|
1519
1188
|
}
|
|
@@ -1567,14 +1236,14 @@ function read_tree_sync() {
|
|
|
1567
1236
|
const reference = git_spawn_sync.read(git_diff_reads.DEFAULT_BRANCH_ARGUMENTS);
|
|
1568
1237
|
return tree_of(status, git_diff_reads.default_branch_of(reference));
|
|
1569
1238
|
}
|
|
1570
|
-
function is_ready_sync(
|
|
1571
|
-
const tree =
|
|
1239
|
+
function is_ready_sync(read2 = read_tree_sync) {
|
|
1240
|
+
const tree = read2();
|
|
1572
1241
|
return tree === void 0 || is_ready(tree);
|
|
1573
1242
|
}
|
|
1574
1243
|
var run_cut_ready = { is_lane_branch, is_ready, is_ready_sync, tree_of };
|
|
1575
1244
|
|
|
1576
1245
|
// scripts/rules/implementation-cut-verdict.ts
|
|
1577
|
-
import { z as
|
|
1246
|
+
import { z as z5 } from "zod";
|
|
1578
1247
|
var VERDICT_CACHE_PREFIX = "josh-impl-cut-verdict-";
|
|
1579
1248
|
var VERDICT_REUSE_MS = 5e3;
|
|
1580
1249
|
var VERDICT_VALUES = [
|
|
@@ -1582,7 +1251,7 @@ var VERDICT_VALUES = [
|
|
|
1582
1251
|
"under",
|
|
1583
1252
|
"unmeasurable"
|
|
1584
1253
|
];
|
|
1585
|
-
var cache_schema =
|
|
1254
|
+
var cache_schema = z5.object({ read_at_ms: z5.number(), verdict: z5.enum(VERDICT_VALUES) });
|
|
1586
1255
|
function cache_path(directory) {
|
|
1587
1256
|
return stamp_file.stamp_path(VERDICT_CACHE_PREFIX, directory);
|
|
1588
1257
|
}
|
|
@@ -1593,11 +1262,11 @@ function cached_verdict(target, now_ms) {
|
|
|
1593
1262
|
if (cached === void 0) return void 0;
|
|
1594
1263
|
return now_ms - cached.read_at_ms < VERDICT_REUSE_MS ? cached.verdict : void 0;
|
|
1595
1264
|
}
|
|
1596
|
-
function reused_verdict(
|
|
1265
|
+
function reused_verdict(read2, directory = process.cwd(), now_ms = Date.now()) {
|
|
1597
1266
|
const target = cache_path(directory);
|
|
1598
1267
|
const cached = cached_verdict(target, now_ms);
|
|
1599
1268
|
if (cached !== void 0) return cached;
|
|
1600
|
-
const value =
|
|
1269
|
+
const value = read2();
|
|
1601
1270
|
stamp_file.replace_stamp(target, { read_at_ms: now_ms, verdict: value });
|
|
1602
1271
|
return value;
|
|
1603
1272
|
}
|
|
@@ -1670,10 +1339,10 @@ var REISSUE_WINDOW_MS = 9e4;
|
|
|
1670
1339
|
function is_reissued_refusal(now_ms, delivered_at_ms) {
|
|
1671
1340
|
return now_ms - delivered_at_ms < REISSUE_WINDOW_MS;
|
|
1672
1341
|
}
|
|
1673
|
-
function decide2(_call,
|
|
1674
|
-
return !is_reissued_refusal(
|
|
1342
|
+
function decide2(_call, run, _can_record, delivered_at_ms) {
|
|
1343
|
+
return !is_reissued_refusal(run.now_ms, delivered_at_ms);
|
|
1675
1344
|
}
|
|
1676
|
-
var
|
|
1345
|
+
var ROW5 = {
|
|
1677
1346
|
id: "implementation-cut",
|
|
1678
1347
|
is_trigger: is_over_threshold_edit,
|
|
1679
1348
|
reason: IMPLEMENTATION_CUT_REASON,
|
|
@@ -1688,7 +1357,7 @@ var ROW4 = {
|
|
|
1688
1357
|
var implementation_cut = {
|
|
1689
1358
|
IMPLEMENTATION_CUT_REASON,
|
|
1690
1359
|
REISSUE_WINDOW_MS,
|
|
1691
|
-
ROW:
|
|
1360
|
+
ROW: ROW5,
|
|
1692
1361
|
decide: decide2,
|
|
1693
1362
|
is_over_threshold_edit,
|
|
1694
1363
|
is_reissued_refusal,
|
|
@@ -1815,19 +1484,48 @@ function is_body_only_issue_read(command) {
|
|
|
1815
1484
|
function reads_issue_comments(command) {
|
|
1816
1485
|
return shell_segments.segments_of(command).some((segment) => fetches_issue_comments(segment));
|
|
1817
1486
|
}
|
|
1818
|
-
var
|
|
1819
|
-
var
|
|
1487
|
+
var RULE_DOC = "`.claude/skills/workflow-commands/issue-comments.md`";
|
|
1488
|
+
var COMMENTS_FALLBACK = "gh api repos/{owner}/{repo}/issues/<N>/comments";
|
|
1489
|
+
var ISSUE_COMMENTS_REASON = `\u26D4 issue comments: pnpm josh issue:read <N>
|
|
1490
|
+
Run that in place of this read \u2014 an Issue's comments are part of it, and a later comment supersedes the body it contradicts; refused until that command is on the transcript. Without josh, read \`${COMMENTS_FALLBACK}\` beside the body (${RULE_DOC}).`;
|
|
1491
|
+
var COMMENTS_JQ = String.raw`'.[] | "— \(.user.login) \(.created_at)\n\(.body)\n"'`;
|
|
1492
|
+
var COMMENTS_NOTE = `\u21BB issue comments: this read returned only the Issue's body, so the Issue's comments were fetched on the same line \u2014 a later comment supersedes the body it contradicts (${RULE_DOC}).`;
|
|
1493
|
+
function rewritable_path(command) {
|
|
1494
|
+
const read2 = shell_segments.first_of(command);
|
|
1495
|
+
if (read2 === void 0 || ISSUE_VIEW_COMMAND.test(read2)) return void 0;
|
|
1496
|
+
return is_body_read_segment(read2) ? ISSUE_BODY_PATH.exec(read2)?.[0] : void 0;
|
|
1497
|
+
}
|
|
1498
|
+
function comments_command(command) {
|
|
1499
|
+
if (!is_body_only_issue_read(command)) return void 0;
|
|
1500
|
+
const path13 = rewritable_path(command);
|
|
1501
|
+
if (path13 === void 0) return void 0;
|
|
1502
|
+
return `gh api --paginate ${path13}/comments --jq ${COMMENTS_JQ}
|
|
1503
|
+
${command}`;
|
|
1504
|
+
}
|
|
1505
|
+
function comments_input(call, tail) {
|
|
1506
|
+
if (call.name !== cost_blocks.BASH_TOOL || !json_value.is_record(call.input)) return void 0;
|
|
1507
|
+
const command = comments_command(time_shell.bash_command(call.input));
|
|
1508
|
+
if (command === void 0 || prior_comment_read.already_read_for_call(tail(), call)) {
|
|
1509
|
+
return void 0;
|
|
1510
|
+
}
|
|
1511
|
+
return { ...call.input, command };
|
|
1512
|
+
}
|
|
1513
|
+
var ROW6 = {
|
|
1820
1514
|
id: "issue-comments",
|
|
1821
1515
|
is_trigger: bash_triggers.on_bash_command(is_body_only_issue_read),
|
|
1822
1516
|
reason: ISSUE_COMMENTS_REASON,
|
|
1823
1517
|
already_satisfied: prior_comment_read.already_read_for_call,
|
|
1824
1518
|
keeps: bash_triggers.on_bash_command(reads_issue_comments),
|
|
1519
|
+
rewrite: comments_input,
|
|
1520
|
+
rewrite_note: COMMENTS_NOTE,
|
|
1825
1521
|
// The opening the reason carried before it led with the command.
|
|
1826
1522
|
former_reasons: ["\u26D4 an Issue's comments are part of the Issue: read them before implementing"]
|
|
1827
1523
|
};
|
|
1828
1524
|
var issue_comments = {
|
|
1525
|
+
COMMENTS_NOTE,
|
|
1829
1526
|
ISSUE_COMMENTS_REASON,
|
|
1830
|
-
ROW:
|
|
1527
|
+
ROW: ROW6,
|
|
1528
|
+
comments_input,
|
|
1831
1529
|
is_body_only_issue_read
|
|
1832
1530
|
};
|
|
1833
1531
|
|
|
@@ -1845,7 +1543,7 @@ function is_bare_josh_git(command) {
|
|
|
1845
1543
|
return shell_segments.segments_of(command).some((segment) => is_bare_segment(segment));
|
|
1846
1544
|
}
|
|
1847
1545
|
var JOSH_GIT_BARE_REASON = '\u26D4 bare `pnpm josh git`: this prompts to confirm the staging, and with no TTY the prompt falls to its cancel branch. Run `pnpm josh git -y "<title> #<N>"`, or `pnpm josh git -y --skip-commit --skip-push` to open the PR for a push that already landed. It fires on every occurrence.';
|
|
1848
|
-
var
|
|
1546
|
+
var ROW7 = {
|
|
1849
1547
|
id: "josh-git-bare",
|
|
1850
1548
|
is_trigger: bash_triggers.on_bash_command(is_bare_josh_git),
|
|
1851
1549
|
reason: JOSH_GIT_BARE_REASON,
|
|
@@ -1853,7 +1551,7 @@ var ROW6 = {
|
|
|
1853
1551
|
};
|
|
1854
1552
|
var josh_git_bare = {
|
|
1855
1553
|
JOSH_GIT_BARE_REASON,
|
|
1856
|
-
ROW:
|
|
1554
|
+
ROW: ROW7,
|
|
1857
1555
|
is_bare_josh_git
|
|
1858
1556
|
};
|
|
1859
1557
|
|
|
@@ -1878,7 +1576,7 @@ function is_carry_conflict(command, is_lane_child = lane_child_marker.is_child_o
|
|
|
1878
1576
|
return is_lane_child;
|
|
1879
1577
|
}
|
|
1880
1578
|
var LANE_CARRY_CONFLICT_REASON = "\u26D4 lane child carry conflict: this session is a dispatched lane child, and `run:merge` / `run:carry` are the parent budget commands; the live record belongs to the parent, not to a competing run. Continue implementing this Issue: no `needs-decision`, no Telegram. Live `run:carry` evidence takes a fresh `JOSH_TEMP_ROOT`; `run:merge` is refused under any root, on every occurrence.";
|
|
1881
|
-
var
|
|
1579
|
+
var ROW8 = {
|
|
1882
1580
|
id: "lane-carry-conflict",
|
|
1883
1581
|
is_trigger: bash_triggers.on_bash_command(is_carry_conflict),
|
|
1884
1582
|
reason: LANE_CARRY_CONFLICT_REASON,
|
|
@@ -1886,66 +1584,24 @@ var ROW7 = {
|
|
|
1886
1584
|
};
|
|
1887
1585
|
var lane_carry_conflict = {
|
|
1888
1586
|
LANE_CARRY_CONFLICT_REASON,
|
|
1889
|
-
ROW:
|
|
1587
|
+
ROW: ROW8,
|
|
1890
1588
|
invokes_budget_command,
|
|
1891
1589
|
is_carry_conflict
|
|
1892
1590
|
};
|
|
1893
1591
|
|
|
1894
|
-
// scripts/agent/interactive-ask.ts
|
|
1895
|
-
import { z as z7 } from "zod";
|
|
1896
|
-
var INTERACTIVE_TOOLS = /* @__PURE__ */ new Set(["AskUserQuestion"]);
|
|
1897
|
-
function is_interactive_tool(name) {
|
|
1898
|
-
return INTERACTIVE_TOOLS.has(name);
|
|
1899
|
-
}
|
|
1900
|
-
var OPTION_SCHEMA = z7.looseObject({ label: z7.string().optional() });
|
|
1901
|
-
var QUESTION_SCHEMA = z7.looseObject({
|
|
1902
|
-
question: z7.string().optional(),
|
|
1903
|
-
options: z7.array(OPTION_SCHEMA).optional()
|
|
1904
|
-
});
|
|
1905
|
-
var ASK_INPUT_SCHEMA = z7.looseObject({ questions: z7.array(QUESTION_SCHEMA).optional() });
|
|
1906
|
-
var DENIAL_SCHEMA = z7.looseObject({
|
|
1907
|
-
tool_name: z7.string().optional(),
|
|
1908
|
-
tool_input: z7.unknown().optional()
|
|
1909
|
-
});
|
|
1910
|
-
var UNKNOWN_QUESTION = "(question text unavailable)";
|
|
1911
|
-
var OPTION_SEPARATOR = " / ";
|
|
1912
|
-
var QUESTION_SEPARATOR = "; ";
|
|
1913
|
-
function labels_of(question) {
|
|
1914
|
-
return (question.options ?? []).map((option) => option.label ?? "").filter((label) => label !== "");
|
|
1915
|
-
}
|
|
1916
|
-
function render_question(question) {
|
|
1917
|
-
const labels = labels_of(question);
|
|
1918
|
-
const text = question.question ?? UNKNOWN_QUESTION;
|
|
1919
|
-
return labels.length === 0 ? text : `${text} [${labels.join(OPTION_SEPARATOR)}]`;
|
|
1920
|
-
}
|
|
1921
|
-
function interactive_input(raw) {
|
|
1922
|
-
const denial = DENIAL_SCHEMA.safeParse(raw);
|
|
1923
|
-
if (!denial.success || !is_interactive_tool(denial.data.tool_name ?? "")) return void 0;
|
|
1924
|
-
const input = ASK_INPUT_SCHEMA.safeParse(denial.data.tool_input);
|
|
1925
|
-
return input.success ? input.data : void 0;
|
|
1926
|
-
}
|
|
1927
|
-
function refused_ask_of(permission_denials) {
|
|
1928
|
-
if (!Array.isArray(permission_denials)) return void 0;
|
|
1929
|
-
const input = permission_denials.map((raw) => interactive_input(raw)).find((one) => one !== void 0);
|
|
1930
|
-
const questions = input?.questions ?? [];
|
|
1931
|
-
if (questions.length === 0) return void 0;
|
|
1932
|
-
return questions.map((question) => render_question(question)).join(QUESTION_SEPARATOR);
|
|
1933
|
-
}
|
|
1934
|
-
var interactive_ask = { is_interactive_tool, refused_ask_of };
|
|
1935
|
-
|
|
1936
1592
|
// scripts/rules/lane-interactive-ask.ts
|
|
1937
1593
|
function is_interactive_ask(call, is_lane_child = lane_child_marker.is_child_of(process.cwd())) {
|
|
1938
1594
|
if (!interactive_ask.is_interactive_tool(call.name)) return false;
|
|
1939
1595
|
return is_lane_child;
|
|
1940
1596
|
}
|
|
1941
1597
|
var LANE_INTERACTIVE_ASK_REASON = "\u26D4 lane child interactive ask: this session is a dispatched lane child and cannot ask a person, so park instead: `gh api repos/{owner}/{repo}/issues/<N>/labels -f 'labels[]=needs-decision'`, `pnpm josh issue:comment <N> --body-file <path>`, the `confirmation` Telegram, stop. It fires on every occurrence (`.claude/skills/workflow-commands/pre-gate-cut.md`, `backlogrun-park.md`).";
|
|
1942
|
-
var
|
|
1598
|
+
var ROW9 = {
|
|
1943
1599
|
id: "lane-interactive-ask",
|
|
1944
1600
|
is_trigger: is_interactive_ask,
|
|
1945
1601
|
reason: LANE_INTERACTIVE_ASK_REASON,
|
|
1946
1602
|
decide: () => true
|
|
1947
1603
|
};
|
|
1948
|
-
var lane_interactive_ask = { LANE_INTERACTIVE_ASK_REASON, ROW:
|
|
1604
|
+
var lane_interactive_ask = { LANE_INTERACTIVE_ASK_REASON, ROW: ROW9, is_interactive_ask };
|
|
1949
1605
|
|
|
1950
1606
|
// scripts/rules/lane-split-park.ts
|
|
1951
1607
|
var EPIC_COMMANDS = /* @__PURE__ */ new Set(["epic"]);
|
|
@@ -1989,13 +1645,13 @@ function is_candidate(command) {
|
|
|
1989
1645
|
if (!is_park_of(command, issue) && !is_notify_of(command, issue)) return false;
|
|
1990
1646
|
return lane_child_marker.is_child_of(process.cwd());
|
|
1991
1647
|
}
|
|
1992
|
-
function decide3(_call,
|
|
1648
|
+
function decide3(_call, run) {
|
|
1993
1649
|
const issue = lane_child_marker.marked_issue();
|
|
1994
|
-
const commands = tail_commands.prior_bash_commands(time_density_hook.read_tail(
|
|
1650
|
+
const commands = tail_commands.prior_bash_commands(time_density_hook.read_tail(run.transcript));
|
|
1995
1651
|
return issue !== void 0 && promoted_issues(commands).has(issue);
|
|
1996
1652
|
}
|
|
1997
1653
|
var LANE_SPLIT_PARK_REASON = '\u26D4 lane split park: this session is a dispatched lane child that promoted its own Issue to an epic this run, and a split is not a park: no `needs-decision` on the epic, no `confirmation` Telegram, on every occurrence. Park a child issue if the rest needs a person, else end the turn (`.claude/skills/workflow-commands/backlogrun-park.md` \u2192 "Splitting a child mid-run").';
|
|
1998
|
-
var
|
|
1654
|
+
var ROW10 = {
|
|
1999
1655
|
id: "lane-split-park",
|
|
2000
1656
|
is_trigger: bash_triggers.on_bash_command(is_candidate),
|
|
2001
1657
|
reason: LANE_SPLIT_PARK_REASON,
|
|
@@ -2003,7 +1659,7 @@ var ROW9 = {
|
|
|
2003
1659
|
};
|
|
2004
1660
|
var lane_split_park = {
|
|
2005
1661
|
LANE_SPLIT_PARK_REASON,
|
|
2006
|
-
ROW:
|
|
1662
|
+
ROW: ROW10,
|
|
2007
1663
|
promoted_issues
|
|
2008
1664
|
};
|
|
2009
1665
|
|
|
@@ -2037,7 +1693,7 @@ function is_switch_away_from_lane(command, is_lane_child = lane_child_marker.is_
|
|
|
2037
1693
|
return switch_targets(command).some((target) => target !== own_branch);
|
|
2038
1694
|
}
|
|
2039
1695
|
var LANE_SWITCH_MAIN_REASON = "\u26D4 lane child on `git switch main`: this session is a dispatched lane child, and switching to the default branch here always fails (`already used by worktree`: the primary checkout holds it). Skip this step and keep implementing on the current branch; `pnpm josh main:merge` brings the default in during the gate. Refused on every occurrence (`backlogrun-lanes.md`, `backlogrun-child.md`).";
|
|
2040
|
-
var
|
|
1696
|
+
var ROW11 = {
|
|
2041
1697
|
id: "lane-switch-main",
|
|
2042
1698
|
is_trigger: bash_triggers.on_bash_command(is_switch_away_from_lane),
|
|
2043
1699
|
reason: LANE_SWITCH_MAIN_REASON,
|
|
@@ -2045,7 +1701,7 @@ var ROW10 = {
|
|
|
2045
1701
|
};
|
|
2046
1702
|
var lane_switch_main = {
|
|
2047
1703
|
LANE_SWITCH_MAIN_REASON,
|
|
2048
|
-
ROW:
|
|
1704
|
+
ROW: ROW11,
|
|
2049
1705
|
is_switch_away_from_lane,
|
|
2050
1706
|
switch_target,
|
|
2051
1707
|
switch_targets
|
|
@@ -2615,7 +2271,7 @@ function is_destructive_command(command) {
|
|
|
2615
2271
|
return shell_segments.segments_of(command).some((segment) => is_destructive_segment2(segment));
|
|
2616
2272
|
}
|
|
2617
2273
|
var DESTRUCTIVE_COMMAND_REASON = "\u26D4 destructive command: a recursive forced `rm`, a `gh repo delete` / `archive` / visibility edit, `gh pr close` or a `gh api -X DELETE` cannot be undone, which is Tier C. Remove one path at a time without `-f`, or ask the user to run it. It fires on every occurrence (`prompts/collaboration-workflow/operating-rules.md`).";
|
|
2618
|
-
var
|
|
2274
|
+
var ROW12 = {
|
|
2619
2275
|
id: "destructive-command",
|
|
2620
2276
|
is_trigger: bash_triggers.on_bash_command(is_destructive_command),
|
|
2621
2277
|
reason: DESTRUCTIVE_COMMAND_REASON,
|
|
@@ -2623,7 +2279,7 @@ var ROW11 = {
|
|
|
2623
2279
|
// The opening the reason carried before it was cut to the action and the next command.
|
|
2624
2280
|
former_reasons: ["\u26D4 destructive command: a recursive forced `rm` (`rm -rf`"]
|
|
2625
2281
|
};
|
|
2626
|
-
var destructive_command = { DESTRUCTIVE_COMMAND_REASON, ROW:
|
|
2282
|
+
var destructive_command = { DESTRUCTIVE_COMMAND_REASON, ROW: ROW12, is_destructive_command };
|
|
2627
2283
|
|
|
2628
2284
|
// scripts/rules/direct-pr-create.ts
|
|
2629
2285
|
var GH_COMMAND2 = "gh";
|
|
@@ -2678,13 +2334,13 @@ function is_direct_pr_create(command) {
|
|
|
2678
2334
|
return shell_segments.segments_of(command).some((segment) => is_pr_create_segment(segment));
|
|
2679
2335
|
}
|
|
2680
2336
|
var DIRECT_PR_CREATE_REASON = "\u26D4 direct PR creation: `gh pr create` (or a `gh api` POST to `repos/<o>/<r>/pulls`) bypasses `build_body`, which writes the `closes #N` line \u2014 the Issue would stay open after the merge (`CLAUDE.md` \u2192 Git Rules). Open the PR with `pnpm josh pr` instead; after a failed push, fix, push, then run `pnpm josh pr`. **This rule fires on every occurrence, not once per run.**";
|
|
2681
|
-
var
|
|
2337
|
+
var ROW13 = {
|
|
2682
2338
|
id: "direct-pr-create",
|
|
2683
2339
|
is_trigger: bash_triggers.on_bash_command(is_direct_pr_create),
|
|
2684
2340
|
reason: DIRECT_PR_CREATE_REASON,
|
|
2685
2341
|
decide: () => true
|
|
2686
2342
|
};
|
|
2687
|
-
var direct_pr_create = { DIRECT_PR_CREATE_REASON, ROW:
|
|
2343
|
+
var direct_pr_create = { DIRECT_PR_CREATE_REASON, ROW: ROW13, is_direct_pr_create };
|
|
2688
2344
|
|
|
2689
2345
|
// scripts/rules/worktree-guard.ts
|
|
2690
2346
|
var CHECKOUT_SUBCOMMAND = "checkout";
|
|
@@ -2746,14 +2402,14 @@ function is_unauthorized_worktree_change(command) {
|
|
|
2746
2402
|
return shell_segments.segments_of(command).some((segment) => is_unauthorized_segment(segment));
|
|
2747
2403
|
}
|
|
2748
2404
|
var WORKTREE_MUTATION_REASON = '\u26D4 unauthorized working-tree change: `git checkout --`, `git restore`, `git clean -f`, `git stash`. A documented flow stashes with `git stash push -u -m "<message>"`; a handed-over stash is `pnpm josh stash:pop "<message>"`; record the substitution on the Issue (Tier A) unless the plan says why the owner keeps the stash: then stop and confirm. It fires on every occurrence (`operating-rules.md`).';
|
|
2749
|
-
var
|
|
2405
|
+
var ROW14 = {
|
|
2750
2406
|
id: "worktree-mutation",
|
|
2751
2407
|
is_trigger: bash_triggers.on_bash_command(is_unauthorized_worktree_change),
|
|
2752
2408
|
reason: WORKTREE_MUTATION_REASON,
|
|
2753
2409
|
decide: () => true
|
|
2754
2410
|
};
|
|
2755
2411
|
var worktree_guard = {
|
|
2756
|
-
ROW:
|
|
2412
|
+
ROW: ROW14,
|
|
2757
2413
|
WORKTREE_MUTATION_REASON,
|
|
2758
2414
|
is_unauthorized_worktree_change,
|
|
2759
2415
|
touches_worktree
|
|
@@ -2782,45 +2438,45 @@ function is_index_mutation(command) {
|
|
|
2782
2438
|
return shell_segments.segments_of(command).some((segment) => is_index_segment(segment));
|
|
2783
2439
|
}
|
|
2784
2440
|
var INDEX_MUTATION_REASON = "\u26D4 git index mutation: `git add` / `stage` / `commit` / `reset` / `rm` / `mv` and `git restore --staged` overwrite the user's staged snapshot. Commit with `pnpm josh git -y`; any other staging is the user's, on explicit instruction. It fires on every occurrence (`prompts/collaboration-workflow/operating-rules.md` \u2192 \"no-self-staging\").";
|
|
2785
|
-
var
|
|
2441
|
+
var ROW15 = {
|
|
2786
2442
|
id: "index-mutation",
|
|
2787
2443
|
is_trigger: bash_triggers.on_bash_command(is_index_mutation),
|
|
2788
2444
|
reason: INDEX_MUTATION_REASON,
|
|
2789
2445
|
decide: () => true
|
|
2790
2446
|
};
|
|
2791
|
-
var index_guard = { INDEX_MUTATION_REASON, ROW:
|
|
2447
|
+
var index_guard = { INDEX_MUTATION_REASON, ROW: ROW15, is_index_mutation };
|
|
2792
2448
|
|
|
2793
2449
|
// scripts/rules/protected-files.ts
|
|
2794
|
-
import
|
|
2450
|
+
import path3 from "node:path";
|
|
2795
2451
|
|
|
2796
2452
|
// scripts/doctor/doctor-consumer.ts
|
|
2797
2453
|
import { existsSync as existsSync2 } from "node:fs";
|
|
2798
|
-
import
|
|
2454
|
+
import path2 from "node:path";
|
|
2799
2455
|
|
|
2800
2456
|
// scripts/version/kit-descriptor.ts
|
|
2801
2457
|
var KIT_PACKAGE_NAME = "@joshuafolkken/kit";
|
|
2802
2458
|
|
|
2803
2459
|
// scripts/doctor/doctor-consumer.ts
|
|
2804
|
-
import { z as
|
|
2460
|
+
import { z as z6 } from "zod";
|
|
2805
2461
|
var NODE_MODULES = "node_modules";
|
|
2806
|
-
var SETTINGS_PATH =
|
|
2462
|
+
var SETTINGS_PATH = path2.join(".claude", "settings.json");
|
|
2807
2463
|
var CLAUDE_MD = "CLAUDE.md";
|
|
2808
2464
|
var PLUGIN_ID = "kit@kit";
|
|
2809
2465
|
var CLAUDE_MD_POINTER = `@${NODE_MODULES}/${KIT_PACKAGE_NAME}/dist/${CLAUDE_MD}`;
|
|
2810
|
-
var SECRETLINT_BIN =
|
|
2811
|
-
var manifest_schema =
|
|
2812
|
-
name:
|
|
2813
|
-
dependencies:
|
|
2814
|
-
devDependencies:
|
|
2466
|
+
var SECRETLINT_BIN = path2.join(NODE_MODULES, ".bin", "secretlint");
|
|
2467
|
+
var manifest_schema = z6.object({
|
|
2468
|
+
name: z6.string().optional(),
|
|
2469
|
+
dependencies: z6.record(z6.string(), z6.string()).optional(),
|
|
2470
|
+
devDependencies: z6.record(z6.string(), z6.string()).optional()
|
|
2815
2471
|
});
|
|
2816
|
-
var settings_schema =
|
|
2817
|
-
enabledPlugins:
|
|
2472
|
+
var settings_schema = z6.object({
|
|
2473
|
+
enabledPlugins: z6.record(z6.string(), z6.boolean()).optional()
|
|
2818
2474
|
});
|
|
2819
2475
|
var STATE_OK = "ok";
|
|
2820
2476
|
var STATE_TARGET_MISSING = "target-missing";
|
|
2821
2477
|
var STATE_MISSING = "missing";
|
|
2822
2478
|
function parse_manifest(root) {
|
|
2823
|
-
const content = file_reader.read_if_readable(
|
|
2479
|
+
const content = file_reader.read_if_readable(path2.join(root, "package.json"));
|
|
2824
2480
|
if (content === void 0) return void 0;
|
|
2825
2481
|
const parsed = manifest_schema.safeParse(json_value.parse_or_undefined(content));
|
|
2826
2482
|
return parsed.success ? parsed.data : void 0;
|
|
@@ -2832,10 +2488,10 @@ function lists_kit_dependency(manifest) {
|
|
|
2832
2488
|
function is_kit_consumer(root) {
|
|
2833
2489
|
const manifest = parse_manifest(root);
|
|
2834
2490
|
if (manifest?.name === KIT_PACKAGE_NAME) return false;
|
|
2835
|
-
return lists_kit_dependency(manifest) || existsSync2(
|
|
2491
|
+
return lists_kit_dependency(manifest) || existsSync2(path2.join(root, NODE_MODULES, KIT_PACKAGE_NAME));
|
|
2836
2492
|
}
|
|
2837
2493
|
function is_plugin_declared(root) {
|
|
2838
|
-
const content = file_reader.read_if_readable(
|
|
2494
|
+
const content = file_reader.read_if_readable(path2.join(root, SETTINGS_PATH));
|
|
2839
2495
|
if (content === void 0) return false;
|
|
2840
2496
|
const parsed = settings_schema.safeParse(json_value.parse_or_undefined(content));
|
|
2841
2497
|
return parsed.success && parsed.data.enabledPlugins?.[PLUGIN_ID] === true;
|
|
@@ -2847,13 +2503,13 @@ function configured_hooks_path(root) {
|
|
|
2847
2503
|
return value === "" ? void 0 : value;
|
|
2848
2504
|
}
|
|
2849
2505
|
function claude_md_state(root) {
|
|
2850
|
-
const content = file_reader.read_if_readable(
|
|
2506
|
+
const content = file_reader.read_if_readable(path2.join(root, CLAUDE_MD));
|
|
2851
2507
|
if (content === void 0) return STATE_MISSING;
|
|
2852
2508
|
if (!content.includes(CLAUDE_MD_POINTER)) return STATE_OK;
|
|
2853
|
-
return existsSync2(
|
|
2509
|
+
return existsSync2(path2.join(root, NODE_MODULES, KIT_PACKAGE_NAME, "dist", CLAUDE_MD)) ? STATE_OK : STATE_TARGET_MISSING;
|
|
2854
2510
|
}
|
|
2855
2511
|
function is_secretlint_runnable(root) {
|
|
2856
|
-
return existsSync2(
|
|
2512
|
+
return existsSync2(path2.join(root, SECRETLINT_BIN));
|
|
2857
2513
|
}
|
|
2858
2514
|
function status_line(is_ok, ok_text, warn_text) {
|
|
2859
2515
|
return is_ok ? ` \u2713 ${ok_text}` : ` \u26A0 ${warn_text}`;
|
|
@@ -2919,7 +2575,7 @@ var EDIT_TOOLS2 = /* @__PURE__ */ new Set(["Edit", "Write"]);
|
|
|
2919
2575
|
var SECRET_FILES = /* @__PURE__ */ new Set([".env", ".dev.vars"]);
|
|
2920
2576
|
var ENVIRONMENT_VARIANT_PREFIX = ".env.";
|
|
2921
2577
|
var TRACKED_VARIANTS = /* @__PURE__ */ new Set([".env.example", ".env.test"]);
|
|
2922
|
-
var SETTINGS_FILE =
|
|
2578
|
+
var SETTINGS_FILE = path3.join(".claude", "settings.json");
|
|
2923
2579
|
var WHITESPACE3 = /\s+/u;
|
|
2924
2580
|
var TOKEN_QUOTES = /["']/gu;
|
|
2925
2581
|
var INPUT_REDIRECT = "<";
|
|
@@ -2949,7 +2605,7 @@ function file_path_of(call) {
|
|
|
2949
2605
|
return typeof value === "string" ? value : "";
|
|
2950
2606
|
}
|
|
2951
2607
|
function is_environment_path(token) {
|
|
2952
|
-
const name =
|
|
2608
|
+
const name = path3.basename(token.replaceAll(TOKEN_QUOTES, ""));
|
|
2953
2609
|
if (TRACKED_VARIANTS.has(name)) return false;
|
|
2954
2610
|
return SECRET_FILES.has(name) || name.startsWith(ENVIRONMENT_VARIANT_PREFIX);
|
|
2955
2611
|
}
|
|
@@ -2970,15 +2626,15 @@ function is_environment_read(call) {
|
|
|
2970
2626
|
}
|
|
2971
2627
|
function is_consumer_settings_edit(call, is_kit_consumer2) {
|
|
2972
2628
|
if (!EDIT_TOOLS2.has(call.name)) return false;
|
|
2973
|
-
const file_path =
|
|
2974
|
-
if (!file_path.endsWith(`${
|
|
2975
|
-
return is_kit_consumer2(
|
|
2629
|
+
const file_path = path3.resolve(file_path_of(call));
|
|
2630
|
+
if (!file_path.endsWith(`${path3.sep}${SETTINGS_FILE}`)) return false;
|
|
2631
|
+
return is_kit_consumer2(path3.dirname(path3.dirname(file_path)));
|
|
2976
2632
|
}
|
|
2977
2633
|
function is_protected_file_call(call, is_kit_consumer2 = doctor_consumer.is_kit_consumer) {
|
|
2978
2634
|
return is_environment_read(call) || is_consumer_settings_edit(call, is_kit_consumer2);
|
|
2979
2635
|
}
|
|
2980
2636
|
var PROTECTED_FILE_REASON = "\u26D4 protected file: `.env`, a `.env.*` variant and `.dev.vars` hold secrets, and a consumer `.claude/settings.json` is owned by `josh sync` (a change belongs upstream in kit). Leave these files alone, or ask the user. It fires on every occurrence.";
|
|
2981
|
-
var
|
|
2637
|
+
var ROW16 = {
|
|
2982
2638
|
id: "protected-file",
|
|
2983
2639
|
is_trigger: is_protected_file_call,
|
|
2984
2640
|
reason: PROTECTED_FILE_REASON,
|
|
@@ -2986,7 +2642,7 @@ var ROW15 = {
|
|
|
2986
2642
|
// The opening the reason carried before it was cut to the action and the next command.
|
|
2987
2643
|
former_reasons: ["\u26D4 protected file: `.env` holds the Telegram bot token"]
|
|
2988
2644
|
};
|
|
2989
|
-
var protected_files = { ROW:
|
|
2645
|
+
var protected_files = { ROW: ROW16, is_protected_file_call };
|
|
2990
2646
|
|
|
2991
2647
|
// scripts/rules/permission-guards.ts
|
|
2992
2648
|
var ROWS2 = [
|
|
@@ -3037,7 +2693,7 @@ function keeps_verdict_intact(command) {
|
|
|
3037
2693
|
var PIPEFAIL_OPEN = "(set -o pipefail; ";
|
|
3038
2694
|
var PIPEFAIL_CLOSE = ")";
|
|
3039
2695
|
var COMMENT_START = /(?:^|\s)#/u;
|
|
3040
|
-
var FULL_READING_FILTER = /^(?:tail|grep)\b/u;
|
|
2696
|
+
var FULL_READING_FILTER = /^(?:tail|grep|cut|sort|uniq|wc)\b/u;
|
|
3041
2697
|
var EARLY_EXIT_GREP = /^grep\b.*\s(?:-[a-zA-Z]*[lLmq]|--(?:quiet|silent|max-count|files-with(?:out)?-match))/u;
|
|
3042
2698
|
var ALLOWED_OPERATORS = /2>&1|&&/gu;
|
|
3043
2699
|
var SIDE_EFFECT_SYNTAX = /[&<>`]|\$\(/u;
|
|
@@ -3124,7 +2780,7 @@ function is_poll_loop(command) {
|
|
|
3124
2780
|
return LOOP_KEYWORD2.test(plain) && SLEEP_COMMAND.test(plain);
|
|
3125
2781
|
}
|
|
3126
2782
|
var POLL_LOOP_REASON = "\u26D4 output poll loop: this hand-writes a `while`/`until` wait loop over a command's output, a marker file or a process, and the loop does not know when the command finished. Issue the long command with `run_in_background` set and end the turn \u2014 its exit re-invokes you; for CI, `pnpm josh followup` (`.claude/skills/workflow-commands/background-commands.md`). It fires on every occurrence.";
|
|
3127
|
-
var
|
|
2783
|
+
var ROW17 = {
|
|
3128
2784
|
id: "poll-loop",
|
|
3129
2785
|
is_trigger: bash_triggers.on_bash_command(is_poll_loop),
|
|
3130
2786
|
reason: POLL_LOOP_REASON,
|
|
@@ -3132,86 +2788,23 @@ var ROW16 = {
|
|
|
3132
2788
|
};
|
|
3133
2789
|
var poll_loop = {
|
|
3134
2790
|
POLL_LOOP_REASON,
|
|
3135
|
-
ROW:
|
|
2791
|
+
ROW: ROW17,
|
|
3136
2792
|
is_poll_loop
|
|
3137
2793
|
};
|
|
3138
2794
|
|
|
3139
|
-
// scripts/rules/pre-gate-cut.ts
|
|
3140
|
-
var GATE_COMMANDS = /* @__PURE__ */ new Set(["gate"]);
|
|
3141
|
-
var CUT_COMMANDS2 = /* @__PURE__ */ new Set(["run:cut"]);
|
|
3142
|
-
var CUT_MODE_FLAG = /(?:^|\s)--(?:resume|end|json)(?:[=\s]|$)/u;
|
|
3143
|
-
var HOLD_COMMANDS = /* @__PURE__ */ new Set(["run:hold"]);
|
|
3144
|
-
var HOLD_MODE_FLAG = /(?:^|\s)--release(?:[=\s]|$)/u;
|
|
3145
|
-
function invokes_josh(command, names, mode_flag) {
|
|
3146
|
-
return shell_segments.segments_of(command).some(
|
|
3147
|
-
(segment) => shell_segments.is_josh_command(segment, names) && mode_flag?.test(segment) !== true
|
|
3148
|
-
);
|
|
3149
|
-
}
|
|
3150
|
-
function runs_the_gate(command) {
|
|
3151
|
-
return invokes_josh(command, GATE_COMMANDS);
|
|
3152
|
-
}
|
|
3153
|
-
function takes_the_cut(command) {
|
|
3154
|
-
return invokes_josh(command, CUT_COMMANDS2, CUT_MODE_FLAG);
|
|
3155
|
-
}
|
|
3156
|
-
function claims_the_hold(command) {
|
|
3157
|
-
return invokes_josh(command, HOLD_COMMANDS, HOLD_MODE_FLAG);
|
|
3158
|
-
}
|
|
3159
|
-
function asks_about_the_cut(command) {
|
|
3160
|
-
return invokes_josh(command, CUT_COMMANDS2);
|
|
3161
|
-
}
|
|
3162
|
-
function current_state2() {
|
|
3163
|
-
return {
|
|
3164
|
-
directory: process.cwd(),
|
|
3165
|
-
carried: run_cut.carried_cut_sync,
|
|
3166
|
-
marked_issue: lane_child_marker.marked_issue(),
|
|
3167
|
-
is_reviewer: agent_session_role.is_reviewer(),
|
|
3168
|
-
context_verdict: cost_cli.session_verdict
|
|
3169
|
-
};
|
|
3170
|
-
}
|
|
3171
|
-
function dispatched_issue(state) {
|
|
3172
|
-
return state.is_reviewer ? void 0 : state.marked_issue;
|
|
3173
|
-
}
|
|
3174
|
-
function uncut_lane_issue(state) {
|
|
3175
|
-
const issue = lane_paths.lane_issue_of(state.directory);
|
|
3176
|
-
if (issue === void 0 || dispatched_issue(state) !== issue) return void 0;
|
|
3177
|
-
return state.carried()?.issue === issue ? void 0 : issue;
|
|
3178
|
-
}
|
|
3179
|
-
function warrants_the_cut2(verdict) {
|
|
3180
|
-
return verdict !== cost_verdict.UNDER_VERDICT;
|
|
3181
|
-
}
|
|
3182
|
-
function is_uncut_gate(command, state = current_state2()) {
|
|
3183
|
-
if (!runs_the_gate(command) || uncut_lane_issue(state) === void 0) return false;
|
|
3184
|
-
return warrants_the_cut2(state.context_verdict());
|
|
3185
|
-
}
|
|
3186
|
-
var PRE_GATE_CUT_REASON = "\u26D4 pre-gate cut: this checkout is a lane dispatched for this issue and the gate is the boundary to cut at. Issue `pnpm josh run:cut <N>`: on `cut`, end the turn immediately \u2014 no Telegram is owed; on any other verdict (`not-a-lane`, `busy`, \u2026), reissue the gate \u2014 this fires once per run (`.claude/skills/workflow-commands/pre-gate-cut.md`).";
|
|
3187
|
-
function reaches_the_pre_gate_boundary(call, _turn, run2) {
|
|
3188
|
-
if (!bash_triggers.on_bash_command(asks_about_the_cut)(call)) return false;
|
|
3189
|
-
return run2.some((issued) => bash_triggers.on_bash_command(claims_the_hold)(issued));
|
|
3190
|
-
}
|
|
3191
|
-
var pre_gate_cut = {
|
|
3192
|
-
PRE_GATE_CUT_REASON,
|
|
3193
|
-
asks_about_the_cut,
|
|
3194
|
-
claims_the_hold,
|
|
3195
|
-
is_uncut_gate,
|
|
3196
|
-
reaches_the_pre_gate_boundary,
|
|
3197
|
-
runs_the_gate,
|
|
3198
|
-
takes_the_cut,
|
|
3199
|
-
uncut_lane_issue
|
|
3200
|
-
};
|
|
3201
|
-
|
|
3202
2795
|
// scripts/rules/raw-field-body.ts
|
|
3203
2796
|
var RAW_FIELD_BODY_AT = /(?:^|\s)(?:-f|--raw-field)[\s=]+['"]?body=['"]?@/u;
|
|
3204
2797
|
function posts_at_path_literally(command) {
|
|
3205
2798
|
return RAW_FIELD_BODY_AT.test(command);
|
|
3206
2799
|
}
|
|
3207
2800
|
var RAW_FIELD_BODY_REASON = "\u26D4 literal @path body: this passes `body=@<path>` to `gh api` with a raw field flag (`-f` / `--raw-field`), which posts the string `@<path>` rather than the file. Post the comment with `pnpm josh issue:comment <N> --body-file <path>`; this rule fires on every occurrence (`prompts/collaboration-workflow/shell-body.md`).";
|
|
3208
|
-
var
|
|
2801
|
+
var ROW18 = {
|
|
3209
2802
|
id: "raw-field-body",
|
|
3210
2803
|
is_trigger: bash_triggers.on_bash_command(posts_at_path_literally),
|
|
3211
2804
|
reason: RAW_FIELD_BODY_REASON,
|
|
3212
2805
|
decide: () => true
|
|
3213
2806
|
};
|
|
3214
|
-
var raw_field_body = { RAW_FIELD_BODY_REASON, ROW:
|
|
2807
|
+
var raw_field_body = { RAW_FIELD_BODY_REASON, ROW: ROW18, posts_at_path_literally };
|
|
3215
2808
|
|
|
3216
2809
|
// scripts/rules/rule-body-guard.ts
|
|
3217
2810
|
var EDIT_TOOL = "Edit";
|
|
@@ -3238,10 +2831,10 @@ function string_field2(input, key) {
|
|
|
3238
2831
|
function read_existing(file_path) {
|
|
3239
2832
|
return file_reader.read_file_or_empty(file_path);
|
|
3240
2833
|
}
|
|
3241
|
-
function texts_of(name, input,
|
|
2834
|
+
function texts_of(name, input, read2) {
|
|
3242
2835
|
if (name === WRITE_TOOL) {
|
|
3243
2836
|
return {
|
|
3244
|
-
old_text:
|
|
2837
|
+
old_text: read2(string_field2(input, "file_path")),
|
|
3245
2838
|
new_text: string_field2(input, "content")
|
|
3246
2839
|
};
|
|
3247
2840
|
}
|
|
@@ -3257,10 +2850,10 @@ function rule_document_input(call) {
|
|
|
3257
2850
|
if (!is_edit_tool2(call.name) || !json_value.is_record(call.input)) return void 0;
|
|
3258
2851
|
return is_rule_document(string_field2(call.input, "file_path")) ? call.input : void 0;
|
|
3259
2852
|
}
|
|
3260
|
-
function writes_rule_prose(call,
|
|
2853
|
+
function writes_rule_prose(call, read2 = read_existing) {
|
|
3261
2854
|
const input = rule_document_input(call);
|
|
3262
2855
|
if (input === void 0) return false;
|
|
3263
|
-
const { old_text, new_text } = texts_of(call.name, input,
|
|
2856
|
+
const { old_text, new_text } = texts_of(call.name, input, read2);
|
|
3264
2857
|
return adds_rule_prose(old_text, new_text);
|
|
3265
2858
|
}
|
|
3266
2859
|
var RULE_BODY_REASON = "\u26D4 rule written into prose: this edit adds rule text to CLAUDE.md, a `prompts/**` doc or a skill body. Answer question 0 (`pnpm josh oracle:list`) and the ordering question (`pnpm josh run:step`) of `prompts/collaboration-workflow/residency.md`; refused until both commands are on the transcript, then reissue this as a trigger-plus-pointer line (`prompts/collaboration-workflow/rule-delivery.md`).";
|
|
@@ -3282,7 +2875,7 @@ function runs_placement_oracle(command) {
|
|
|
3282
2875
|
(names) => shell_segments.segments_of(command).some((segment) => shell_segments.is_josh_command(segment, names))
|
|
3283
2876
|
);
|
|
3284
2877
|
}
|
|
3285
|
-
var
|
|
2878
|
+
var ROW19 = {
|
|
3286
2879
|
id: "rule-body",
|
|
3287
2880
|
is_trigger: writes_rule_prose,
|
|
3288
2881
|
reason: RULE_BODY_REASON,
|
|
@@ -3291,7 +2884,7 @@ var ROW18 = {
|
|
|
3291
2884
|
};
|
|
3292
2885
|
var rule_body_guard = {
|
|
3293
2886
|
RULE_BODY_REASON,
|
|
3294
|
-
ROW:
|
|
2887
|
+
ROW: ROW19,
|
|
3295
2888
|
answered_placement,
|
|
3296
2889
|
is_rule_document,
|
|
3297
2890
|
writes_rule_prose
|
|
@@ -3368,12 +2961,12 @@ var shell_body_trigger = {
|
|
|
3368
2961
|
};
|
|
3369
2962
|
|
|
3370
2963
|
// scripts/gate/project-checks.ts
|
|
3371
|
-
import { existsSync as existsSync7, globSync
|
|
3372
|
-
import
|
|
2964
|
+
import { existsSync as existsSync7, globSync, readFileSync as readFileSync5 } from "node:fs";
|
|
2965
|
+
import path11 from "node:path";
|
|
3373
2966
|
|
|
3374
2967
|
// scripts/init/own-formatter.ts
|
|
3375
2968
|
import { existsSync as existsSync3 } from "node:fs";
|
|
3376
|
-
import
|
|
2969
|
+
import path4 from "node:path";
|
|
3377
2970
|
var OWN_FORMATTER_CONFIGS = [
|
|
3378
2971
|
"biome.json",
|
|
3379
2972
|
"biome.jsonc",
|
|
@@ -3383,18 +2976,18 @@ var OWN_FORMATTER_CONFIGS = [
|
|
|
3383
2976
|
".dprint.jsonc"
|
|
3384
2977
|
];
|
|
3385
2978
|
function find_config(root) {
|
|
3386
|
-
return OWN_FORMATTER_CONFIGS.find((name) => existsSync3(
|
|
2979
|
+
return OWN_FORMATTER_CONFIGS.find((name) => existsSync3(path4.join(root, name)));
|
|
3387
2980
|
}
|
|
3388
2981
|
var own_formatter = { find_config };
|
|
3389
2982
|
|
|
3390
2983
|
// scripts/init/project-profile.ts
|
|
3391
|
-
import { existsSync as existsSync6, readdirSync, readFileSync as
|
|
3392
|
-
import
|
|
2984
|
+
import { existsSync as existsSync6, readdirSync, readFileSync as readFileSync4 } from "node:fs";
|
|
2985
|
+
import path10 from "node:path";
|
|
3393
2986
|
|
|
3394
2987
|
// scripts/safe-chain/pack-hook.ts
|
|
3395
|
-
import { z as
|
|
2988
|
+
import { z as z7 } from "zod";
|
|
3396
2989
|
var PACK_HOOK_FILE = ".pnpmfile.mjs";
|
|
3397
|
-
var manifest_schema2 =
|
|
2990
|
+
var manifest_schema2 = z7.looseObject({ private: z7.boolean().optional() });
|
|
3398
2991
|
var MESSAGES = {
|
|
3399
2992
|
written: ` \u2714 synced ${PACK_HOOK_FILE} (run \`pnpm install\` to refresh pnpmfileChecksum)`,
|
|
3400
2993
|
unchanged: ` \u2714 unchanged ${PACK_HOOK_FILE}`,
|
|
@@ -3430,15 +3023,15 @@ var yaml_document = { is_mapping_document, parse_yaml, parse_yaml_documents };
|
|
|
3430
3023
|
|
|
3431
3024
|
// scripts/version/release-age.ts
|
|
3432
3025
|
import semver from "semver";
|
|
3433
|
-
import { z as
|
|
3434
|
-
var workspace_age_schema =
|
|
3435
|
-
var release_times_schema =
|
|
3026
|
+
import { z as z8 } from "zod";
|
|
3027
|
+
var workspace_age_schema = z8.object({ minimumReleaseAge: z8.number().int().nonnegative() });
|
|
3028
|
+
var release_times_schema = z8.record(z8.string(), z8.string());
|
|
3436
3029
|
|
|
3437
3030
|
// scripts/safe-chain/project-config.ts
|
|
3438
3031
|
import { dump } from "js-yaml";
|
|
3439
|
-
import { z as
|
|
3032
|
+
import { z as z9 } from "zod";
|
|
3440
3033
|
var PROJECT_CONFIG_FILE = ".aikido";
|
|
3441
|
-
var workspace_schema =
|
|
3034
|
+
var workspace_schema = z9.object({ minimumReleaseAgeExclude: z9.array(z9.string()).optional() });
|
|
3442
3035
|
|
|
3443
3036
|
// scripts/config-merge/json-format.ts
|
|
3444
3037
|
var PRINT_WIDTH = 100;
|
|
@@ -3483,9 +3076,9 @@ function inline_short_arrays(text) {
|
|
|
3483
3076
|
const output = [];
|
|
3484
3077
|
let index = 0;
|
|
3485
3078
|
while (index < lines.length) {
|
|
3486
|
-
const
|
|
3487
|
-
output.push(...
|
|
3488
|
-
index =
|
|
3079
|
+
const rewrite3 = rewrite_at(lines, index, lines[index] ?? "");
|
|
3080
|
+
output.push(...rewrite3.lines);
|
|
3081
|
+
index = rewrite3.next;
|
|
3489
3082
|
}
|
|
3490
3083
|
return output.join("\n");
|
|
3491
3084
|
}
|
|
@@ -3520,86 +3113,6 @@ var safe_chain_preinstall = {
|
|
|
3520
3113
|
migrate_preinstall
|
|
3521
3114
|
};
|
|
3522
3115
|
|
|
3523
|
-
// scripts/init/distributed-paths.ts
|
|
3524
|
-
var KIT_PACKAGE_PATH_PREFIX = "node_modules/@joshuafolkken/kit/";
|
|
3525
|
-
var PROMPTS_PACKAGE_PREFIX = `${KIT_PACKAGE_PATH_PREFIX}prompts/`;
|
|
3526
|
-
var ESLINT_PACKAGE_PREFIX = `${KIT_PACKAGE_PATH_PREFIX}eslint/`;
|
|
3527
|
-
var GITHUB_REPO_BLOB_BASE = "https://github.com/joshuafolkken/kit/blob/main/";
|
|
3528
|
-
var GITHUB_REPO_TREE_BASE = "https://github.com/joshuafolkken/kit/tree/main/";
|
|
3529
|
-
var CLAUDE_MD_IMPORT_LINE = "@node_modules/@joshuafolkken/kit/dist/CLAUDE.md";
|
|
3530
|
-
var OLD_CLAUDE_MD_BOOTSTRAP = "> Fresh checkout: if kit is not installed, run `pnpm install` first, then reread this file before doing any other work.";
|
|
3531
|
-
var CLAUDE_MD_BOOTSTRAP = '> Fresh checkout: before `pnpm install`, run `pnpm config get "@joshuafolkken:registry"` from the project root to check the effective registry, including user-level settings. If it points to GitHub Packages, [set up authentication](https://github.com/joshuafolkken/kit/blob/main/docs/authentication.md#1-get-a-token-from-the-gh-cli) first. Then run `pnpm install` and reread this file before doing any other work.';
|
|
3532
|
-
function transform_prompt_paths(content) {
|
|
3533
|
-
return content.replaceAll(
|
|
3534
|
-
/`prompts\/([^`*]+)`/gu,
|
|
3535
|
-
(_match, prompt_path) => `\`${PROMPTS_PACKAGE_PREFIX}${prompt_path}\``
|
|
3536
|
-
);
|
|
3537
|
-
}
|
|
3538
|
-
function transform_eslint_paths(content) {
|
|
3539
|
-
return content.replaceAll(
|
|
3540
|
-
/`eslint\/([^`*]+)`/gu,
|
|
3541
|
-
(_match, eslint_path) => `\`${ESLINT_PACKAGE_PREFIX}${eslint_path}\``
|
|
3542
|
-
);
|
|
3543
|
-
}
|
|
3544
|
-
function transform_test_file_paths(content) {
|
|
3545
|
-
return content.replaceAll(
|
|
3546
|
-
/`([^`*]+\.(?:test|spec)\.ts)`/gu,
|
|
3547
|
-
(_match, test_path) => `\`${GITHUB_REPO_BLOB_BASE}${test_path}\``
|
|
3548
|
-
);
|
|
3549
|
-
}
|
|
3550
|
-
function github_url_base(reference_path) {
|
|
3551
|
-
return reference_path.endsWith("/") ? GITHUB_REPO_TREE_BASE : GITHUB_REPO_BLOB_BASE;
|
|
3552
|
-
}
|
|
3553
|
-
function transform_documentation_paths(content) {
|
|
3554
|
-
return content.replaceAll(
|
|
3555
|
-
/`(docs\/[^`*]*)`/gu,
|
|
3556
|
-
(_match, documentation_path) => `\`${github_url_base(documentation_path)}${documentation_path}\``
|
|
3557
|
-
);
|
|
3558
|
-
}
|
|
3559
|
-
function transform_distributed_paths(content) {
|
|
3560
|
-
const with_prompts = transform_prompt_paths(content);
|
|
3561
|
-
const with_eslint = transform_eslint_paths(with_prompts);
|
|
3562
|
-
const with_tests = transform_test_file_paths(with_eslint);
|
|
3563
|
-
return transform_documentation_paths(with_tests);
|
|
3564
|
-
}
|
|
3565
|
-
function ensure_claude_md_import(existing) {
|
|
3566
|
-
if (existing === void 0) return `${CLAUDE_MD_BOOTSTRAP}
|
|
3567
|
-
|
|
3568
|
-
${CLAUDE_MD_IMPORT_LINE}
|
|
3569
|
-
`;
|
|
3570
|
-
const updated = existing.replace(OLD_CLAUDE_MD_BOOTSTRAP, () => CLAUDE_MD_BOOTSTRAP);
|
|
3571
|
-
if (updated.includes(CLAUDE_MD_IMPORT_LINE)) {
|
|
3572
|
-
if (updated.includes(CLAUDE_MD_BOOTSTRAP)) return updated;
|
|
3573
|
-
return `${CLAUDE_MD_BOOTSTRAP}
|
|
3574
|
-
|
|
3575
|
-
${updated}`;
|
|
3576
|
-
}
|
|
3577
|
-
return `${CLAUDE_MD_BOOTSTRAP}
|
|
3578
|
-
|
|
3579
|
-
${CLAUDE_MD_IMPORT_LINE}
|
|
3580
|
-
|
|
3581
|
-
${updated}`;
|
|
3582
|
-
}
|
|
3583
|
-
var FULL_CLAUDE_MD_LINES = /* @__PURE__ */ new Set([
|
|
3584
|
-
CLAUDE_MD_BOOTSTRAP,
|
|
3585
|
-
OLD_CLAUDE_MD_BOOTSTRAP,
|
|
3586
|
-
CLAUDE_MD_IMPORT_LINE
|
|
3587
|
-
]);
|
|
3588
|
-
function remove_claude_md_import(content) {
|
|
3589
|
-
const lines = content.split("\n");
|
|
3590
|
-
return lines.filter((line, index) => {
|
|
3591
|
-
if (FULL_CLAUDE_MD_LINES.has(line)) return false;
|
|
3592
|
-
return line !== "" || !FULL_CLAUDE_MD_LINES.has(lines[index - 1] ?? "");
|
|
3593
|
-
}).join("\n");
|
|
3594
|
-
}
|
|
3595
|
-
var distributed_paths = {
|
|
3596
|
-
transform_prompt_paths,
|
|
3597
|
-
transform_distributed_paths,
|
|
3598
|
-
ensure_claude_md_import,
|
|
3599
|
-
remove_claude_md_import,
|
|
3600
|
-
CLAUDE_MD_IMPORT_LINE
|
|
3601
|
-
};
|
|
3602
|
-
|
|
3603
3116
|
// scripts/init/init-logic-deploy-vps.ts
|
|
3604
3117
|
import semver2 from "semver";
|
|
3605
3118
|
var PNPM_INSTALL_PATTERN = /npm install -g pnpm@\d[\d.]{0,19}/gu;
|
|
@@ -3881,10 +3394,10 @@ function set_json_key(content, key, value) {
|
|
|
3881
3394
|
const indented = fit_value(content, value_text, line_indent(content, existing.offset));
|
|
3882
3395
|
return with_trailing_newline(replace_range(content, existing, indented));
|
|
3883
3396
|
}
|
|
3884
|
-
function resolve_parent(content,
|
|
3397
|
+
function resolve_parent(content, path13) {
|
|
3885
3398
|
const root = parse_root(content);
|
|
3886
3399
|
if (root === void 0) return void 0;
|
|
3887
|
-
const parent =
|
|
3400
|
+
const parent = path13.length > 1 ? findNodeAtLocation(root, path13.slice(0, -1)) : root;
|
|
3888
3401
|
return parent?.type === "object" ? parent : void 0;
|
|
3889
3402
|
}
|
|
3890
3403
|
function cut_ranges(content, parent, ranges) {
|
|
@@ -3895,24 +3408,24 @@ function cut_ranges(content, parent, ranges) {
|
|
|
3895
3408
|
}
|
|
3896
3409
|
return next;
|
|
3897
3410
|
}
|
|
3898
|
-
function rebalance_new_last(content,
|
|
3899
|
-
const parent = resolve_parent(content,
|
|
3411
|
+
function rebalance_new_last(content, path13) {
|
|
3412
|
+
const parent = resolve_parent(content, path13);
|
|
3900
3413
|
const last = parent?.children?.at(-1);
|
|
3901
3414
|
if (parent === void 0 || last === void 0) return content;
|
|
3902
3415
|
return rebalance(content, last, has_separator_after(content, parent.offset, parent.offset));
|
|
3903
3416
|
}
|
|
3904
|
-
function cut_property(content, parent,
|
|
3905
|
-
const index = property_index(parent,
|
|
3417
|
+
function cut_property(content, parent, path13) {
|
|
3418
|
+
const index = property_index(parent, path13.at(-1) ?? "");
|
|
3906
3419
|
const ranges = removal_ranges(content, parent, index);
|
|
3907
3420
|
if (ranges.length === 0) return content;
|
|
3908
3421
|
const cut = cut_ranges(content, parent, ranges);
|
|
3909
3422
|
const did_end_object = index === (parent.children ?? []).length - 1;
|
|
3910
|
-
return did_end_object ? rebalance_new_last(cut,
|
|
3423
|
+
return did_end_object ? rebalance_new_last(cut, path13) : cut;
|
|
3911
3424
|
}
|
|
3912
|
-
function remove_json_path(content,
|
|
3913
|
-
const parent = resolve_parent(content,
|
|
3425
|
+
function remove_json_path(content, path13) {
|
|
3426
|
+
const parent = resolve_parent(content, path13);
|
|
3914
3427
|
if (parent === void 0) return content;
|
|
3915
|
-
const next = cut_property(content, parent,
|
|
3428
|
+
const next = cut_property(content, parent, path13);
|
|
3916
3429
|
return next === content ? content : with_trailing_newline(next);
|
|
3917
3430
|
}
|
|
3918
3431
|
function remove_json_key(content, key) {
|
|
@@ -4143,13 +3656,13 @@ var kit_base_preset = {
|
|
|
4143
3656
|
|
|
4144
3657
|
// scripts/init/tsconfig-preset-migration.ts
|
|
4145
3658
|
import { existsSync as existsSync4 } from "node:fs";
|
|
4146
|
-
import
|
|
3659
|
+
import path5 from "node:path";
|
|
4147
3660
|
var LEGACY_PRESET_ENTRY = /@joshuafolkken\/[^/]+\/tsconfig\/[^/]+\.jsonc$/u;
|
|
4148
3661
|
var LEGACY_SUFFIX = ".jsonc";
|
|
4149
3662
|
var CURRENT_SUFFIX = ".json";
|
|
4150
3663
|
var EXTENDS_FIELD = "extends";
|
|
4151
3664
|
function is_migration_target_present(base_directory, entry) {
|
|
4152
|
-
return existsSync4(
|
|
3665
|
+
return existsSync4(path5.resolve(base_directory, entry));
|
|
4153
3666
|
}
|
|
4154
3667
|
function migrate_entry(base_directory, entry) {
|
|
4155
3668
|
if (!LEGACY_PRESET_ENTRY.test(entry)) return entry;
|
|
@@ -4381,15 +3894,15 @@ var init_logic_json_merge = {
|
|
|
4381
3894
|
};
|
|
4382
3895
|
|
|
4383
3896
|
// scripts/init/kit-development-versions.ts
|
|
4384
|
-
import { readFileSync as
|
|
4385
|
-
import { z as
|
|
3897
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
3898
|
+
import { z as z10 } from "zod";
|
|
4386
3899
|
var PACKAGE_JSON = "package.json";
|
|
4387
|
-
var kit_manifest_schema =
|
|
4388
|
-
peerDependencies:
|
|
4389
|
-
devDependencies:
|
|
3900
|
+
var kit_manifest_schema = z10.object({
|
|
3901
|
+
peerDependencies: z10.record(z10.string(), z10.string()).default({}),
|
|
3902
|
+
devDependencies: z10.record(z10.string(), z10.string())
|
|
4390
3903
|
});
|
|
4391
3904
|
function read_kit_manifest() {
|
|
4392
|
-
const content =
|
|
3905
|
+
const content = readFileSync2(package_path(PACKAGE_JSON), "utf8");
|
|
4393
3906
|
return kit_manifest_schema.parse(JSON.parse(content));
|
|
4394
3907
|
}
|
|
4395
3908
|
function versions_of(names) {
|
|
@@ -4550,9 +4063,9 @@ function merge_sonar_properties(existing, template_content) {
|
|
|
4550
4063
|
return key !== void 0 && !existing_keys.has(key);
|
|
4551
4064
|
});
|
|
4552
4065
|
if (lines_to_add.length === 0) return merged_existing;
|
|
4553
|
-
const
|
|
4066
|
+
const normalized = merged_existing.endsWith("\n") ? merged_existing : `${merged_existing}
|
|
4554
4067
|
`;
|
|
4555
|
-
return `${
|
|
4068
|
+
return `${normalized}
|
|
4556
4069
|
${lines_to_add.join("\n")}
|
|
4557
4070
|
`;
|
|
4558
4071
|
}
|
|
@@ -4565,8 +4078,8 @@ var init_logic_sonar = {
|
|
|
4565
4078
|
};
|
|
4566
4079
|
|
|
4567
4080
|
// scripts/init/init-logic-templates.ts
|
|
4568
|
-
import { existsSync as existsSync5, readFileSync as
|
|
4569
|
-
import
|
|
4081
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "node:fs";
|
|
4082
|
+
import path6 from "node:path";
|
|
4570
4083
|
var ESLINT_VANILLA = `import { create_vanilla_config } from '@joshuafolkken/kit/eslint/vanilla'
|
|
4571
4084
|
|
|
4572
4085
|
export default create_vanilla_config({
|
|
@@ -4651,7 +4164,7 @@ function merge_eslint_config(existing) {
|
|
|
4651
4164
|
return apply_rules_template(rules_blocks.join(",\n"));
|
|
4652
4165
|
}
|
|
4653
4166
|
function detect_tailwind_stylesheet(project_root2) {
|
|
4654
|
-
return existsSync5(
|
|
4167
|
+
return existsSync5(path6.join(project_root2, DEFAULT_TAILWIND_STYLESHEET)) ? DEFAULT_TAILWIND_STYLESHEET : void 0;
|
|
4655
4168
|
}
|
|
4656
4169
|
function generate_prettier_config(stylesheet) {
|
|
4657
4170
|
const stylesheet_line = stylesheet === void 0 ? "" : ` tailwindStylesheet: '${stylesheet}',
|
|
@@ -4665,14 +4178,14 @@ ${stylesheet_line}}
|
|
|
4665
4178
|
}
|
|
4666
4179
|
function existing_stylesheet(existing, project_root2) {
|
|
4667
4180
|
const named = TAILWIND_STYLESHEET_PATTERN.exec(existing)?.[1];
|
|
4668
|
-
return named !== void 0 && existsSync5(
|
|
4181
|
+
return named !== void 0 && existsSync5(path6.resolve(project_root2, named)) ? named : void 0;
|
|
4669
4182
|
}
|
|
4670
4183
|
function merge_prettier_config(existing, project_root2) {
|
|
4671
4184
|
const stylesheet = existing_stylesheet(existing, project_root2) ?? detect_tailwind_stylesheet(project_root2);
|
|
4672
4185
|
return generate_prettier_config(stylesheet);
|
|
4673
4186
|
}
|
|
4674
4187
|
function generate_playwright_config() {
|
|
4675
|
-
return
|
|
4188
|
+
return readFileSync3(PLAYWRIGHT_TEMPLATE_PATH, "utf8");
|
|
4676
4189
|
}
|
|
4677
4190
|
var init_logic_templates = {
|
|
4678
4191
|
generate_eslint_config,
|
|
@@ -4744,9 +4257,9 @@ function extract_yaml_block(content, key) {
|
|
|
4744
4257
|
}
|
|
4745
4258
|
function append_user_blocks(base, user_keys, existing) {
|
|
4746
4259
|
const user_blocks = user_keys.map((k) => extract_yaml_block(existing, k)).filter(Boolean).join("\n");
|
|
4747
|
-
const
|
|
4260
|
+
const normalized = base.endsWith("\n") ? base : `${base}
|
|
4748
4261
|
`;
|
|
4749
|
-
return `${
|
|
4262
|
+
return `${normalized}
|
|
4750
4263
|
${user_blocks}
|
|
4751
4264
|
`;
|
|
4752
4265
|
}
|
|
@@ -4839,9 +4352,9 @@ function carry_npmrc_settings(template, npmrc) {
|
|
|
4839
4352
|
}
|
|
4840
4353
|
function merge_workspace_yaml(existing, template) {
|
|
4841
4354
|
if (!existing.trim()) return template;
|
|
4842
|
-
const
|
|
4355
|
+
const normalized = existing.endsWith("\n") ? existing : `${existing}
|
|
4843
4356
|
`;
|
|
4844
|
-
const answered = answer_build_placeholders(remove_deprecated_yaml_keys(
|
|
4357
|
+
const answered = answer_build_placeholders(remove_deprecated_yaml_keys(normalized), template);
|
|
4845
4358
|
const cleaned = add_missing_build_entries(answered, template);
|
|
4846
4359
|
if (!cleaned.trim()) return template;
|
|
4847
4360
|
const existing_keys = new Set(extract_yaml_top_level_keys(cleaned));
|
|
@@ -5180,23 +4693,23 @@ var AI_COPY_DIRECTORIES_LIST = "AI_COPY_DIRECTORIES";
|
|
|
5180
4693
|
var SYNCED_PATHS_LIST = "SYNCED_PATHS";
|
|
5181
4694
|
var PLUGIN_SKILL_DIRECTORIES_LIST = "PLUGIN_SKILL_DIRECTORIES";
|
|
5182
4695
|
var PATH_SEPARATOR = "/";
|
|
5183
|
-
function is_inside(
|
|
5184
|
-
return
|
|
4696
|
+
function is_inside(path13, directory) {
|
|
4697
|
+
return path13 === directory || path13.startsWith(`${directory}${PATH_SEPARATOR}`);
|
|
5185
4698
|
}
|
|
5186
|
-
function matches_file(
|
|
5187
|
-
return init_logic.get_ai_copy_files().includes(
|
|
4699
|
+
function matches_file(path13) {
|
|
4700
|
+
return init_logic.get_ai_copy_files().includes(path13);
|
|
5188
4701
|
}
|
|
5189
|
-
function matches_mapping(
|
|
5190
|
-
return init_logic.get_ai_copy_file_mappings().some((mapping) => mapping.src ===
|
|
4702
|
+
function matches_mapping(path13) {
|
|
4703
|
+
return init_logic.get_ai_copy_file_mappings().some((mapping) => mapping.src === path13 || mapping.dest === path13);
|
|
5191
4704
|
}
|
|
5192
|
-
function matches_directory(
|
|
5193
|
-
return init_logic.get_ai_copy_directories().some((directory) => is_inside(
|
|
4705
|
+
function matches_directory(path13) {
|
|
4706
|
+
return init_logic.get_ai_copy_directories().some((directory) => is_inside(path13, directory));
|
|
5194
4707
|
}
|
|
5195
|
-
function matches_plugin_skill(
|
|
5196
|
-
return PLUGIN_SKILL_DIRECTORIES.some((directory) => is_inside(
|
|
4708
|
+
function matches_plugin_skill(path13) {
|
|
4709
|
+
return PLUGIN_SKILL_DIRECTORIES.some((directory) => is_inside(path13, directory));
|
|
5197
4710
|
}
|
|
5198
|
-
function matches_synced_path(
|
|
5199
|
-
return synced_paths.get_synced_paths().includes(
|
|
4711
|
+
function matches_synced_path(path13) {
|
|
4712
|
+
return synced_paths.get_synced_paths().includes(path13);
|
|
5200
4713
|
}
|
|
5201
4714
|
var MATCHERS = [
|
|
5202
4715
|
{ list: AI_COPY_FILES_LIST, matches: matches_file },
|
|
@@ -5205,18 +4718,18 @@ var MATCHERS = [
|
|
|
5205
4718
|
{ list: PLUGIN_SKILL_DIRECTORIES_LIST, matches: matches_plugin_skill },
|
|
5206
4719
|
{ list: SYNCED_PATHS_LIST, matches: matches_synced_path }
|
|
5207
4720
|
];
|
|
5208
|
-
function find_list(
|
|
5209
|
-
return MATCHERS.find((matcher) => matcher.matches(
|
|
4721
|
+
function find_list(path13) {
|
|
4722
|
+
return MATCHERS.find((matcher) => matcher.matches(path13))?.list;
|
|
5210
4723
|
}
|
|
5211
|
-
function to_hit(
|
|
5212
|
-
const list = find_list(
|
|
5213
|
-
return list === void 0 ? void 0 : { path:
|
|
4724
|
+
function to_hit(path13) {
|
|
4725
|
+
const list = find_list(path13);
|
|
4726
|
+
return list === void 0 ? void 0 : { path: path13, list };
|
|
5214
4727
|
}
|
|
5215
4728
|
function find_managed_paths(paths) {
|
|
5216
|
-
return paths.flatMap((
|
|
4729
|
+
return paths.flatMap((path13) => to_hit(path13) ?? []);
|
|
5217
4730
|
}
|
|
5218
4731
|
function has_managed_path(paths) {
|
|
5219
|
-
return paths.some((
|
|
4732
|
+
return paths.some((path13) => find_list(path13) !== void 0);
|
|
5220
4733
|
}
|
|
5221
4734
|
function format_hit(hit) {
|
|
5222
4735
|
return `${hit.path} (${hit.list})`;
|
|
@@ -5232,8 +4745,8 @@ var managed_config_scope = {
|
|
|
5232
4745
|
};
|
|
5233
4746
|
|
|
5234
4747
|
// scripts/init/session-language-environment.ts
|
|
5235
|
-
import
|
|
5236
|
-
var CLAUDE_SETTINGS_PATH =
|
|
4748
|
+
import path7 from "node:path";
|
|
4749
|
+
var CLAUDE_SETTINGS_PATH = path7.join(".claude", "settings.json");
|
|
5237
4750
|
var KEY_LINE_PATTERN = new RegExp(
|
|
5238
4751
|
String.raw`^\s*(?:export\s+)?${session_language.ENV_KEY}\s*=`,
|
|
5239
4752
|
"mu"
|
|
@@ -5243,8 +4756,8 @@ var KEY_LINE_PATTERN = new RegExp(
|
|
|
5243
4756
|
import { findNodeAtLocation as findNodeAtLocation2, getNodeValue as getNodeValue2, parseTree as parseTree3 } from "jsonc-parser";
|
|
5244
4757
|
|
|
5245
4758
|
// scripts/init/vscode-tasks.ts
|
|
5246
|
-
import { z as
|
|
5247
|
-
var task_array_schema =
|
|
4759
|
+
import { z as z11 } from "zod";
|
|
4760
|
+
var task_array_schema = z11.array(json_object_schema);
|
|
5248
4761
|
|
|
5249
4762
|
// scripts/init/init-actions.ts
|
|
5250
4763
|
var BASIC_PRETTIER_CONFIG = "prettier.config.mjs";
|
|
@@ -5254,11 +4767,11 @@ var MARKER_TOKEN = "josh-managed-workflow:";
|
|
|
5254
4767
|
var MARKER_PREFIX = `# ${MARKER_TOKEN}`;
|
|
5255
4768
|
|
|
5256
4769
|
// scripts/init/claude-plugin-config.ts
|
|
5257
|
-
import
|
|
4770
|
+
import path8 from "node:path";
|
|
5258
4771
|
var MARKETPLACE_NAME = "kit";
|
|
5259
4772
|
var PLUGIN_ID2 = "kit@kit";
|
|
5260
4773
|
var MARKETPLACE_PATH = "./node_modules/@joshuafolkken/kit";
|
|
5261
|
-
var CLAUDE_SETTINGS_DESTINATION =
|
|
4774
|
+
var CLAUDE_SETTINGS_DESTINATION = path8.join(".claude", "settings.json");
|
|
5262
4775
|
var PLUGIN_SETTINGS = {
|
|
5263
4776
|
extraKnownMarketplaces: {
|
|
5264
4777
|
[MARKETPLACE_NAME]: { source: { source: "directory", path: MARKETPLACE_PATH } }
|
|
@@ -5282,9 +4795,9 @@ var claude_plugin_config = {
|
|
|
5282
4795
|
// scripts/init/hook-launch.ts
|
|
5283
4796
|
var HOOK_DIST_DIR = "dist/hooks";
|
|
5284
4797
|
var RUN_HOOK_SCRIPT = "scripts/hooks/run-hook.sh";
|
|
5285
|
-
var
|
|
4798
|
+
var LOCATION_VARIABLES = GIT_LOCATION_VARIABLES.join(" ");
|
|
5286
4799
|
var ROOT_LOOKUP = "git rev-parse --show-toplevel";
|
|
5287
|
-
var PROJECT_ROOT_PREFIX = `project_root="$(
|
|
4800
|
+
var PROJECT_ROOT_PREFIX = `if project_root="$(unset ${LOCATION_VARIABLES}; ${ROOT_LOOKUP} 2>/dev/null)"; then unset ${LOCATION_VARIABLES}; else project_root="$(${ROOT_LOOKUP})"; fi && cd "$project_root" && `;
|
|
5288
4801
|
function hook_launch_command(name) {
|
|
5289
4802
|
return `${PROJECT_ROOT_PREFIX}sh ${RUN_HOOK_SCRIPT} ${name}`;
|
|
5290
4803
|
}
|
|
@@ -5320,7 +4833,7 @@ var PLAIN_KIT_COMMANDS = new Set(
|
|
|
5320
4833
|
var PROJECT_ROOT_PREFIX2 = JSON.stringify(hook_launch.PROJECT_ROOT_PREFIX).slice(1, -1);
|
|
5321
4834
|
|
|
5322
4835
|
// scripts/init/security-policy.ts
|
|
5323
|
-
import
|
|
4836
|
+
import path9 from "node:path";
|
|
5324
4837
|
var SECURITY_MD = "SECURITY.md";
|
|
5325
4838
|
var SECURITY_TEMPLATE = "templates/SECURITY.md";
|
|
5326
4839
|
var REPOSITORY_PLACEHOLDER = "{{REPOSITORY}}";
|
|
@@ -5336,15 +4849,15 @@ function apply_repository(content, repository) {
|
|
|
5336
4849
|
return content.replaceAll(REPOSITORY_PLACEHOLDER, () => repository);
|
|
5337
4850
|
}
|
|
5338
4851
|
function apply_repository_for_destination(destination_path, content) {
|
|
5339
|
-
if (
|
|
5340
|
-
const repository = repository_at(
|
|
4852
|
+
if (path9.basename(destination_path) !== SECURITY_MD) return content;
|
|
4853
|
+
const repository = repository_at(path9.dirname(destination_path));
|
|
5341
4854
|
if (repository === void 0) {
|
|
5342
4855
|
throw new Error(`${SECURITY_MD} needs a GitHub origin to name the repository it reports to`);
|
|
5343
4856
|
}
|
|
5344
4857
|
return apply_repository(content, repository);
|
|
5345
4858
|
}
|
|
5346
4859
|
function does_report_to_kit(root) {
|
|
5347
|
-
const existing = file_reader.read_if_readable(
|
|
4860
|
+
const existing = file_reader.read_if_readable(path9.join(root, SECURITY_MD)) ?? "";
|
|
5348
4861
|
return new Set(existing.split(LINK_DELIMITER)).has(KIT_ADVISORY_URL);
|
|
5349
4862
|
}
|
|
5350
4863
|
function unresolved_warning(root) {
|
|
@@ -5464,9 +4977,9 @@ function requested_profile(args, usage = "josh init [--profile basic|full]") {
|
|
|
5464
4977
|
throw new Error("Profile must be basic or full");
|
|
5465
4978
|
}
|
|
5466
4979
|
function read_manifest(root) {
|
|
5467
|
-
const filename =
|
|
4980
|
+
const filename = path10.join(root, "package.json");
|
|
5468
4981
|
if (!existsSync6(filename)) return void 0;
|
|
5469
|
-
const parsed = JSON.parse(
|
|
4982
|
+
const parsed = JSON.parse(readFileSync4(filename, "utf8"));
|
|
5470
4983
|
if (!json_value.is_record(parsed)) throw new Error("package.json must contain an object");
|
|
5471
4984
|
return parsed;
|
|
5472
4985
|
}
|
|
@@ -5507,12 +5020,12 @@ function should_visit(entry) {
|
|
|
5507
5020
|
function scan_directory(directory, pending) {
|
|
5508
5021
|
const entries = readdirSync(directory, { withFileTypes: true });
|
|
5509
5022
|
pending.push(
|
|
5510
|
-
...entries.filter((entry) => should_visit(entry)).map((entry) =>
|
|
5023
|
+
...entries.filter((entry) => should_visit(entry)).map((entry) => path10.join(directory, entry.name))
|
|
5511
5024
|
);
|
|
5512
|
-
return entries.filter((entry) => entry.isFile()).map((entry) =>
|
|
5025
|
+
return entries.filter((entry) => entry.isFile()).map((entry) => path10.join(directory, entry.name));
|
|
5513
5026
|
}
|
|
5514
5027
|
function is_project_file(root, file) {
|
|
5515
|
-
const relative_path =
|
|
5028
|
+
const relative_path = path10.relative(root, file).split(path10.sep).join(path10.posix.sep);
|
|
5516
5029
|
return !kit_written_paths.is_kit_written(relative_path);
|
|
5517
5030
|
}
|
|
5518
5031
|
function list_files(root) {
|
|
@@ -5524,7 +5037,7 @@ function list_files(root) {
|
|
|
5524
5037
|
return files;
|
|
5525
5038
|
}
|
|
5526
5039
|
function file_extensions(root) {
|
|
5527
|
-
return list_files(root).filter((file) => is_project_file(root, file)).map((file) =>
|
|
5040
|
+
return list_files(root).filter((file) => is_project_file(root, file)).map((file) => path10.extname(file));
|
|
5528
5041
|
}
|
|
5529
5042
|
function scan_files(root) {
|
|
5530
5043
|
const extensions = file_extensions(root);
|
|
@@ -5538,7 +5051,7 @@ function has_github_remote(root) {
|
|
|
5538
5051
|
return url !== void 0 && repo_origin.parse_origin_url(url) !== void 0;
|
|
5539
5052
|
}
|
|
5540
5053
|
function has_git(root) {
|
|
5541
|
-
return existsSync6(
|
|
5054
|
+
return existsSync6(path10.join(root, ".git"));
|
|
5542
5055
|
}
|
|
5543
5056
|
function has_workflow(root) {
|
|
5544
5057
|
return workflow_mark.is_requested() || workflow_mark.is_recorded(read_manifest(root));
|
|
@@ -5571,7 +5084,7 @@ var SKIP_MARKER = "\u2014 skipping";
|
|
|
5571
5084
|
var NOT_USED_MARKER = "which this project does not use";
|
|
5572
5085
|
|
|
5573
5086
|
// scripts/gate/project-checks.ts
|
|
5574
|
-
import { z as
|
|
5087
|
+
import { z as z12 } from "zod";
|
|
5575
5088
|
var PACKAGE_JSON2 = "package.json";
|
|
5576
5089
|
var IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
5577
5090
|
"node_modules",
|
|
@@ -5606,11 +5119,11 @@ var CSPELL_CONFIGS = [
|
|
|
5606
5119
|
];
|
|
5607
5120
|
var TYPE_CONFIGS = ["tsconfig.json", "jsconfig.json"];
|
|
5608
5121
|
var DEPENDENCY_FIELDS = ["dependencies", "devDependencies"];
|
|
5609
|
-
var object_schema =
|
|
5122
|
+
var object_schema = z12.record(z12.string(), z12.unknown());
|
|
5610
5123
|
function project_root(directory) {
|
|
5611
5124
|
return ancestor_directories.nearest(
|
|
5612
5125
|
directory,
|
|
5613
|
-
(candidate) => existsSync7(
|
|
5126
|
+
(candidate) => existsSync7(path11.join(candidate, PACKAGE_JSON2))
|
|
5614
5127
|
) ?? directory;
|
|
5615
5128
|
}
|
|
5616
5129
|
function is_kit_repository(directory) {
|
|
@@ -5620,10 +5133,10 @@ function is_ignored(entry) {
|
|
|
5620
5133
|
return entry.split(/[/\\]/u).some((part) => IGNORED_DIRS.has(part));
|
|
5621
5134
|
}
|
|
5622
5135
|
function has_files(directory, pattern) {
|
|
5623
|
-
return
|
|
5136
|
+
return globSync(pattern, { cwd: project_root(directory), exclude: is_ignored }).length > 0;
|
|
5624
5137
|
}
|
|
5625
5138
|
function has_config(directory, names) {
|
|
5626
|
-
return names.some((name) => existsSync7(
|
|
5139
|
+
return names.some((name) => existsSync7(path11.join(project_root(directory), name)));
|
|
5627
5140
|
}
|
|
5628
5141
|
function has_bin(directory, bin_name) {
|
|
5629
5142
|
return find_local_bin_upwards(directory, bin_name) !== void 0;
|
|
@@ -5638,8 +5151,8 @@ function is_basic_manifest(manifest) {
|
|
|
5638
5151
|
}
|
|
5639
5152
|
function read_manifest2(directory) {
|
|
5640
5153
|
try {
|
|
5641
|
-
const manifest_path =
|
|
5642
|
-
return json_value.parse_or_undefined(
|
|
5154
|
+
const manifest_path = path11.join(project_root(directory), PACKAGE_JSON2);
|
|
5155
|
+
return json_value.parse_or_undefined(readFileSync5(manifest_path, "utf8"));
|
|
5643
5156
|
} catch {
|
|
5644
5157
|
return void 0;
|
|
5645
5158
|
}
|
|
@@ -5659,11 +5172,11 @@ function missing_tool_reason(directory, package_name, bin_name) {
|
|
|
5659
5172
|
if (has_bin(directory, bin_name) || is_declared2(directory, package_name)) return void 0;
|
|
5660
5173
|
return `${package_name} is not installed`;
|
|
5661
5174
|
}
|
|
5662
|
-
function skip_notice(
|
|
5663
|
-
return `josh ${
|
|
5175
|
+
function skip_notice(check3, reason) {
|
|
5176
|
+
return `josh ${check3}: ${reason} ${SKIP_MARKER} ${check3}, ${NOT_USED_MARKER}.`;
|
|
5664
5177
|
}
|
|
5665
|
-
function ran_notice(
|
|
5666
|
-
return `josh ${
|
|
5178
|
+
function ran_notice(check3) {
|
|
5179
|
+
return `josh ${check3}: ran and reported no problems.`;
|
|
5667
5180
|
}
|
|
5668
5181
|
function type_check_skip_reason(directory) {
|
|
5669
5182
|
if (!is_basic(directory)) return void 0;
|
|
@@ -5727,40 +5240,40 @@ var BASIC_REQUIRED_SUFFIXES = [
|
|
|
5727
5240
|
".toml"
|
|
5728
5241
|
];
|
|
5729
5242
|
function normalize(paths) {
|
|
5730
|
-
return paths.map((
|
|
5243
|
+
return paths.map((path13) => path13.trim()).filter((path13) => path13 !== "");
|
|
5731
5244
|
}
|
|
5732
|
-
function is_test_file(
|
|
5733
|
-
return TEST_SUFFIXES.some((suffix) =>
|
|
5245
|
+
function is_test_file(path13) {
|
|
5246
|
+
return TEST_SUFFIXES.some((suffix) => path13.endsWith(suffix));
|
|
5734
5247
|
}
|
|
5735
|
-
function is_basic_manual(
|
|
5736
|
-
const lower =
|
|
5248
|
+
function is_basic_manual(path13, is_basic2) {
|
|
5249
|
+
const lower = path13.toLowerCase();
|
|
5737
5250
|
return is_basic2 && BASIC_REQUIRED_SUFFIXES.every((suffix) => !lower.endsWith(suffix));
|
|
5738
5251
|
}
|
|
5739
|
-
function is_basic_visual(
|
|
5740
|
-
const lower =
|
|
5252
|
+
function is_basic_visual(path13) {
|
|
5253
|
+
const lower = path13.toLowerCase();
|
|
5741
5254
|
return BASIC_VISUAL_SUFFIXES.some((suffix) => lower.endsWith(suffix));
|
|
5742
5255
|
}
|
|
5743
|
-
function is_exempt(
|
|
5744
|
-
if (EXEMPT_PATHS.includes(
|
|
5745
|
-
return EXEMPT_SUFFIXES.some((suffix) =>
|
|
5256
|
+
function is_exempt(path13, is_basic2 = false) {
|
|
5257
|
+
if (EXEMPT_PATHS.includes(path13) || is_basic_manual(path13, is_basic2)) return true;
|
|
5258
|
+
return EXEMPT_SUFFIXES.some((suffix) => path13.endsWith(suffix)) || EXEMPT_PREFIXES.some((prefix) => path13.startsWith(prefix));
|
|
5746
5259
|
}
|
|
5747
|
-
function is_runtime(
|
|
5748
|
-
return !is_test_file(
|
|
5260
|
+
function is_runtime(path13, is_basic2 = false) {
|
|
5261
|
+
return !is_test_file(path13) && !is_exempt(path13, is_basic2);
|
|
5749
5262
|
}
|
|
5750
5263
|
function verdict_for2(paths, is_basic2 = false) {
|
|
5751
5264
|
const changed = normalize(paths);
|
|
5752
|
-
if (changed.some((
|
|
5753
|
-
if (changed.some((
|
|
5265
|
+
if (changed.some((path13) => is_test_file(path13))) return "satisfied";
|
|
5266
|
+
if (changed.some((path13) => is_runtime(path13, is_basic2))) return "required";
|
|
5754
5267
|
return "exempt";
|
|
5755
5268
|
}
|
|
5756
5269
|
function runtime_files(paths, is_basic2 = false) {
|
|
5757
|
-
return normalize(paths).filter((
|
|
5270
|
+
return normalize(paths).filter((path13) => is_runtime(path13, is_basic2));
|
|
5758
5271
|
}
|
|
5759
5272
|
function exempt_files(paths, is_basic2 = false) {
|
|
5760
|
-
return normalize(paths).filter((
|
|
5273
|
+
return normalize(paths).filter((path13) => is_exempt(path13, is_basic2));
|
|
5761
5274
|
}
|
|
5762
5275
|
function manual_check_files(paths, is_basic2) {
|
|
5763
|
-
return normalize(paths).filter((
|
|
5276
|
+
return normalize(paths).filter((path13) => is_exempt(path13, is_basic2) && !is_exempt(path13));
|
|
5764
5277
|
}
|
|
5765
5278
|
var test_declared_logic = {
|
|
5766
5279
|
EXEMPT_PATHS,
|
|
@@ -5820,8 +5333,8 @@ function is_untested_commit(call) {
|
|
|
5820
5333
|
return test_declared_changed.current_verdict() === "required";
|
|
5821
5334
|
}
|
|
5822
5335
|
var REASON = "\u26D4 test declared: this commits a runtime code change with no test beside it \u2014 `pnpm josh test:declared` reads it `required` and names the files. Tests are required for ALL code changes: add the test and reissue, or, for a change that touches no runtime path, declare the non-runtime exception in your Step 0 work summary and reissue. It fires once per run (`CLAUDE.md` \u2192 Code Change Rules).";
|
|
5823
|
-
var
|
|
5824
|
-
var test_declared_commit = { REASON, ROW:
|
|
5336
|
+
var ROW20 = { id: "test-declared", is_trigger: is_untested_commit, reason: REASON };
|
|
5337
|
+
var test_declared_commit = { REASON, ROW: ROW20 };
|
|
5825
5338
|
|
|
5826
5339
|
// scripts/rules/third-party-write.ts
|
|
5827
5340
|
function is_third_party_write_segment(segment, session_owner, resolve_placeholder_owners) {
|
|
@@ -5859,14 +5372,14 @@ function writes_third_party(command, resolve_owner = repo_party.current_owner, r
|
|
|
5859
5372
|
);
|
|
5860
5373
|
}
|
|
5861
5374
|
var THIRD_PARTY_WRITE_REASON = "\u26D4 third-party write: this `gh api` call writes to a repository whose owner is not this session, which is Tier C and needs explicit current-turn user instruction. Check with `pnpm josh repo:party <owner/repo>`, then record the finding on our own Issue and draft the artifact for a person to post. This rule fires on every occurrence (`prompts/collaboration-workflow/upstream-interrupt.md`).";
|
|
5862
|
-
var
|
|
5375
|
+
var ROW21 = {
|
|
5863
5376
|
id: "third-party-write",
|
|
5864
5377
|
is_trigger: bash_triggers.on_bash_command((command) => writes_third_party(command)),
|
|
5865
5378
|
reason: THIRD_PARTY_WRITE_REASON,
|
|
5866
5379
|
decide: () => true
|
|
5867
5380
|
};
|
|
5868
5381
|
var third_party_write = {
|
|
5869
|
-
ROW:
|
|
5382
|
+
ROW: ROW21,
|
|
5870
5383
|
THIRD_PARTY_WRITE_REASON,
|
|
5871
5384
|
writes_third_party
|
|
5872
5385
|
};
|
|
@@ -5898,7 +5411,8 @@ var DELIVERED_RULES = [
|
|
|
5898
5411
|
reason: piped_verification.PIPED_VERIFICATION_REASON,
|
|
5899
5412
|
keeps: on_bash_command(piped_verification.keeps_verdict_intact),
|
|
5900
5413
|
reaches: on_bash_command(piped_verification.runs_verification),
|
|
5901
|
-
// A
|
|
5414
|
+
// A masking whose filter reads to the end is rewritten under `pipefail`, never refused.
|
|
5415
|
+
rewrite: piped_verification.pipefail_input,
|
|
5902
5416
|
rewrite_note: piped_verification.PIPEFAIL_NOTE
|
|
5903
5417
|
},
|
|
5904
5418
|
{
|
|
@@ -5937,6 +5451,7 @@ var DELIVERED_RULES = [
|
|
|
5937
5451
|
lane_split_park.ROW,
|
|
5938
5452
|
lane_park.ROW,
|
|
5939
5453
|
lane_interactive_ask.ROW,
|
|
5454
|
+
agent_model.ROW,
|
|
5940
5455
|
lane_carry_conflict.ROW,
|
|
5941
5456
|
lane_switch_main.ROW,
|
|
5942
5457
|
// Disjoint from `run-tail` by the `-y` flag.
|
|
@@ -5976,22 +5491,22 @@ var MEASURED_RULES = [
|
|
|
5976
5491
|
];
|
|
5977
5492
|
var BATCH_STAMP = hook_decision.create_refusal_stamp(time_batch_guard.STAMP_PREFIX);
|
|
5978
5493
|
var BATCH_REFUSAL_WINDOW_MS = 1e4;
|
|
5979
|
-
function will_batch_guard_refuse(tail, call,
|
|
5494
|
+
function will_batch_guard_refuse(tail, call, run) {
|
|
5980
5495
|
if (lane_guard_policy.mode_here("batching") !== "refuse") return false;
|
|
5981
|
-
const refused_at_ms = BATCH_STAMP.last_ms(BATCH_STAMP.path(
|
|
5982
|
-
if (
|
|
5496
|
+
const refused_at_ms = BATCH_STAMP.last_ms(BATCH_STAMP.path(run.transcript));
|
|
5497
|
+
if (run.now_ms - refused_at_ms < BATCH_REFUSAL_WINDOW_MS) return true;
|
|
5983
5498
|
return time_batch_guard.should_block(tail, call, refused_at_ms);
|
|
5984
5499
|
}
|
|
5985
|
-
function is_first_delivery(tail, call, delivered_at_ms,
|
|
5986
|
-
return delivered_at_ms === hook_decision.NEVER_MS && !will_batch_guard_refuse(tail, call,
|
|
5500
|
+
function is_first_delivery(tail, call, delivered_at_ms, run) {
|
|
5501
|
+
return delivered_at_ms === hook_decision.NEVER_MS && !will_batch_guard_refuse(tail, call, run);
|
|
5987
5502
|
}
|
|
5988
5503
|
function delivery_decision(rule) {
|
|
5989
|
-
const { decide:
|
|
5990
|
-
if (
|
|
5991
|
-
return function should_block(tail, call, delivered_at_ms,
|
|
5504
|
+
const { decide: decide5, already_satisfied } = rule;
|
|
5505
|
+
if (decide5 === void 0 && already_satisfied === void 0) return is_first_delivery;
|
|
5506
|
+
return function should_block(tail, call, delivered_at_ms, run) {
|
|
5992
5507
|
if (already_satisfied?.(tail, call) === true) return false;
|
|
5993
|
-
if (
|
|
5994
|
-
return
|
|
5508
|
+
if (decide5 === void 0) return true;
|
|
5509
|
+
return decide5(call, run, !will_batch_guard_refuse(tail, call, run), delivered_at_ms);
|
|
5995
5510
|
};
|
|
5996
5511
|
}
|
|
5997
5512
|
function guard_of(rule) {
|
|
@@ -6044,6 +5559,144 @@ var delivered_rules = {
|
|
|
6044
5559
|
is_issue_filing
|
|
6045
5560
|
};
|
|
6046
5561
|
|
|
5562
|
+
// scripts/rules/guard-remedy.ts
|
|
5563
|
+
var REWRITTEN = "the hook makes the same call right itself; it refuses only a spelling it cannot rewrite";
|
|
5564
|
+
var ANOTHER_TOOL = "the right form is another tool, which `updatedInput` cannot switch to";
|
|
5565
|
+
var ANOTHER_COMMAND = "the right act is another command, whose arguments the call does not carry";
|
|
5566
|
+
var NO_RUN = "the call must not run at all, or only on a person's word \u2014 refusing is the remedy";
|
|
5567
|
+
var STOP_NOTIFY = "the hook sends the notify itself; it blocks only when the send fails";
|
|
5568
|
+
var HOLD_RELEASE = "the hook releases the hold itself; it blocks only when that release fails";
|
|
5569
|
+
var ISSUE_CITATION = "the hook prints the citation lines itself; it blocks only on a number it cannot cite";
|
|
5570
|
+
var FILING_OFFER = "the filing needs a title and a body only the model can write";
|
|
5571
|
+
function rewrite() {
|
|
5572
|
+
return { remedy: "rewrite", why: REWRITTEN };
|
|
5573
|
+
}
|
|
5574
|
+
function judgment(why) {
|
|
5575
|
+
return { remedy: "judgment", why };
|
|
5576
|
+
}
|
|
5577
|
+
var GUARD_REMEDIES = {
|
|
5578
|
+
// The rewrites: each fix is the same call made right.
|
|
5579
|
+
"piped-verification": rewrite(),
|
|
5580
|
+
// wrapped in `(set -o pipefail; …)`
|
|
5581
|
+
"issue-comments": rewrite(),
|
|
5582
|
+
// the same Issue's comments read on the same line
|
|
5583
|
+
"lane-background": rewrite(),
|
|
5584
|
+
// a lane child's `ship` run in the foreground (`pretool-guard.ts`)
|
|
5585
|
+
"file-body": judgment(ANOTHER_TOOL),
|
|
5586
|
+
// Edit or Write
|
|
5587
|
+
"shell-body": judgment(
|
|
5588
|
+
"which part of the body the shell was meant to expand is the author's, not the hook's"
|
|
5589
|
+
),
|
|
5590
|
+
"raw-field-body": judgment("the body moves to a file the call does not name"),
|
|
5591
|
+
"rule-body": judgment("a trigger-plus-pointer line is written, not derived"),
|
|
5592
|
+
"direct-filing": judgment(ANOTHER_COMMAND),
|
|
5593
|
+
"direct-pr-create": judgment(ANOTHER_COMMAND),
|
|
5594
|
+
"josh-git-bare": judgment(ANOTHER_COMMAND),
|
|
5595
|
+
"run-tail": judgment(ANOTHER_COMMAND),
|
|
5596
|
+
"pre-gate-cut": judgment(ANOTHER_COMMAND),
|
|
5597
|
+
"implementation-cut": judgment(ANOTHER_COMMAND),
|
|
5598
|
+
"early-heartbeat": judgment(ANOTHER_COMMAND),
|
|
5599
|
+
"poll-loop": judgment(ANOTHER_COMMAND),
|
|
5600
|
+
"lane-park": judgment(ANOTHER_COMMAND),
|
|
5601
|
+
"lane-split-park": judgment(ANOTHER_COMMAND),
|
|
5602
|
+
"lane-interactive-ask": judgment(ANOTHER_COMMAND),
|
|
5603
|
+
"agent-model": judgment("which model fits the unit is the author's call"),
|
|
5604
|
+
"lane-carry-conflict": judgment(ANOTHER_COMMAND),
|
|
5605
|
+
"lane-switch-main": judgment(ANOTHER_COMMAND),
|
|
5606
|
+
"oracle-consulted": judgment(ANOTHER_COMMAND),
|
|
5607
|
+
"test-declared": judgment(ANOTHER_COMMAND),
|
|
5608
|
+
batching: judgment(ANOTHER_COMMAND),
|
|
5609
|
+
investigation: judgment(ANOTHER_COMMAND),
|
|
5610
|
+
"duplicate-read": judgment(ANOTHER_COMMAND),
|
|
5611
|
+
"run-watcher": judgment(ANOTHER_COMMAND),
|
|
5612
|
+
"parent-cut": judgment(ANOTHER_COMMAND),
|
|
5613
|
+
"issue-watch": judgment(ANOTHER_COMMAND),
|
|
5614
|
+
"third-party-write": judgment(NO_RUN),
|
|
5615
|
+
"filing-cap": judgment(NO_RUN),
|
|
5616
|
+
"git-force": judgment(NO_RUN),
|
|
5617
|
+
"worktree-mutation": judgment(NO_RUN),
|
|
5618
|
+
"index-mutation": judgment(NO_RUN),
|
|
5619
|
+
"destructive-command": judgment(NO_RUN),
|
|
5620
|
+
"protected-file": judgment(NO_RUN),
|
|
5621
|
+
// The `Stop` rows: the hook judges a finished reply, so it has no call to rewrite.
|
|
5622
|
+
"stop-notify": judgment(STOP_NOTIFY),
|
|
5623
|
+
"issue-citation": judgment(ISSUE_CITATION),
|
|
5624
|
+
"filing-offer": judgment(FILING_OFFER),
|
|
5625
|
+
"hold-release": judgment(HOLD_RELEASE)
|
|
5626
|
+
};
|
|
5627
|
+
var FAMILY_SEPARATOR = ":";
|
|
5628
|
+
function entry_of(id) {
|
|
5629
|
+
return GUARD_REMEDIES[id] ?? GUARD_REMEDIES[id.split(FAMILY_SEPARATOR)[0] ?? ""];
|
|
5630
|
+
}
|
|
5631
|
+
function remedy_of(id) {
|
|
5632
|
+
return entry_of(id)?.remedy;
|
|
5633
|
+
}
|
|
5634
|
+
function why_of(id) {
|
|
5635
|
+
return entry_of(id)?.why;
|
|
5636
|
+
}
|
|
5637
|
+
function is_rewrite(id) {
|
|
5638
|
+
return remedy_of(id) === "rewrite";
|
|
5639
|
+
}
|
|
5640
|
+
var guard_remedy = {
|
|
5641
|
+
GUARD_REMEDIES,
|
|
5642
|
+
is_rewrite,
|
|
5643
|
+
remedy_of,
|
|
5644
|
+
why_of
|
|
5645
|
+
};
|
|
5646
|
+
|
|
5647
|
+
// scripts/rules/rule-rewrite.ts
|
|
5648
|
+
var REWRITING_RULES = delivered_rules.DELIVERED_RULES.filter(
|
|
5649
|
+
(rule) => guard_remedy.is_rewrite(rule.id) && rule.rewrite !== void 0
|
|
5650
|
+
);
|
|
5651
|
+
var NOTE_SEPARATOR = "\n\n";
|
|
5652
|
+
function read_payload_tail(raw_payload) {
|
|
5653
|
+
try {
|
|
5654
|
+
const payload = hook_decision.parse_hook_payload(raw_payload);
|
|
5655
|
+
return payload ? time_density_hook.read_tail(
|
|
5656
|
+
time_hook_transcript.transcript_of(payload.transcript_path, payload.agent_id)
|
|
5657
|
+
) : "";
|
|
5658
|
+
} catch {
|
|
5659
|
+
return "";
|
|
5660
|
+
}
|
|
5661
|
+
}
|
|
5662
|
+
function tail_reader(raw_payload) {
|
|
5663
|
+
const cache = {};
|
|
5664
|
+
return function tail() {
|
|
5665
|
+
cache.tail ??= read_payload_tail(raw_payload);
|
|
5666
|
+
return cache.tail;
|
|
5667
|
+
};
|
|
5668
|
+
}
|
|
5669
|
+
function fold(name, typed, tail) {
|
|
5670
|
+
const folded = { input: typed, notes: [] };
|
|
5671
|
+
for (const rule of REWRITING_RULES) {
|
|
5672
|
+
const input = rule.rewrite?.({ name, input: folded.input }, tail);
|
|
5673
|
+
if (input === void 0) {
|
|
5674
|
+
continue;
|
|
5675
|
+
}
|
|
5676
|
+
folded.input = input;
|
|
5677
|
+
folded.notes = [...folded.notes, rule.rewrite_note ?? ""];
|
|
5678
|
+
}
|
|
5679
|
+
return folded;
|
|
5680
|
+
}
|
|
5681
|
+
function typed_payload(raw_payload) {
|
|
5682
|
+
const fields = json_value.parse_or_undefined(raw_payload);
|
|
5683
|
+
if (!json_value.is_record(fields)) return void 0;
|
|
5684
|
+
const input = fields["tool_input"];
|
|
5685
|
+
return json_value.is_record(input) ? { fields, name: String(fields["tool_name"]), input } : void 0;
|
|
5686
|
+
}
|
|
5687
|
+
function rewrite2(raw_payload) {
|
|
5688
|
+
const typed = delivered_rules.is_enabled() ? typed_payload(raw_payload) : void 0;
|
|
5689
|
+
if (typed === void 0) return void 0;
|
|
5690
|
+
const { input, notes } = fold(typed.name, typed.input, tail_reader(raw_payload));
|
|
5691
|
+
if (notes.length === 0) return void 0;
|
|
5692
|
+
const note = notes.join(NOTE_SEPARATOR);
|
|
5693
|
+
return { payload: JSON.stringify({ ...typed.fields, tool_input: input }), input, note };
|
|
5694
|
+
}
|
|
5695
|
+
var rule_rewrite = {
|
|
5696
|
+
NOTE_SEPARATOR,
|
|
5697
|
+
rewrite: rewrite2
|
|
5698
|
+
};
|
|
5699
|
+
|
|
6047
5700
|
// scripts/run/progress/run-progress-read.ts
|
|
6048
5701
|
import { loadavg } from "node:os";
|
|
6049
5702
|
|
|
@@ -6059,8 +5712,8 @@ function format_holder(issue, repo, ages) {
|
|
|
6059
5712
|
function format_holders(issues, repo, ages) {
|
|
6060
5713
|
return issues.map((issue) => format_holder(issue, repo, ages)).join(", ");
|
|
6061
5714
|
}
|
|
6062
|
-
function occupied_lanes(
|
|
6063
|
-
return
|
|
5715
|
+
function occupied_lanes(read2) {
|
|
5716
|
+
return read2.kind === "busy" ? read2.issues.length : 0;
|
|
6064
5717
|
}
|
|
6065
5718
|
function occupancy_message(issues, repo, limit, ages = NO_AGES) {
|
|
6066
5719
|
return `${String(issues.length)} of ${String(limit)} lanes in use in ${repo}: ${format_holders(issues, repo, ages)}.`;
|
|
@@ -6078,18 +5731,18 @@ var BUSY_REASONS = {
|
|
|
6078
5731
|
unreadable: unreadable_message,
|
|
6079
5732
|
truncated: truncated_message
|
|
6080
5733
|
};
|
|
6081
|
-
function busy_reason(
|
|
6082
|
-
if (
|
|
6083
|
-
if (
|
|
6084
|
-
return BUSY_REASONS[
|
|
5734
|
+
function busy_reason(read2, repo, limit, ages = NO_AGES) {
|
|
5735
|
+
if (read2.kind === "busy") return lanes_full_message(read2.issues, repo, limit, ages);
|
|
5736
|
+
if (read2.kind === "idle") return "";
|
|
5737
|
+
return BUSY_REASONS[read2.kind](repo);
|
|
6085
5738
|
}
|
|
6086
5739
|
function is_parked(issue) {
|
|
6087
5740
|
return has_any_label(issue.labels, PARKED_LABELS);
|
|
6088
5741
|
}
|
|
6089
5742
|
function parse_listing(raw, is_capped) {
|
|
6090
|
-
const
|
|
6091
|
-
if (
|
|
6092
|
-
const holders =
|
|
5743
|
+
const read2 = read_json_listing(raw, open_issue_schema);
|
|
5744
|
+
if (read2.kind !== "read") return { kind: "unreadable" };
|
|
5745
|
+
const holders = read2.rows.filter((row) => !is_parked(row));
|
|
6093
5746
|
if (holders.length > 0) return { kind: "busy", issues: holders };
|
|
6094
5747
|
return { kind: is_capped ? "truncated" : "idle" };
|
|
6095
5748
|
}
|
|
@@ -6114,411 +5767,16 @@ var epic_busy = {
|
|
|
6114
5767
|
read_repository
|
|
6115
5768
|
};
|
|
6116
5769
|
|
|
6117
|
-
// scripts/run/run-liveness.ts
|
|
6118
|
-
import { readFileSync as readFileSync7, realpathSync, statSync } from "node:fs";
|
|
6119
|
-
import { homedir, tmpdir } from "node:os";
|
|
6120
|
-
import path14 from "node:path";
|
|
6121
|
-
import { setTimeout as sleep } from "node:timers/promises";
|
|
6122
|
-
|
|
6123
|
-
// scripts/agent/agent-event.ts
|
|
6124
|
-
import { z as z16 } from "zod";
|
|
6125
|
-
|
|
6126
|
-
// scripts/agent/claude-result-event.ts
|
|
6127
|
-
import { z as z15 } from "zod";
|
|
6128
|
-
var RESULT_EVENT_SCHEMA = z15.looseObject({
|
|
6129
|
-
type: z15.literal("result"),
|
|
6130
|
-
is_error: z15.unknown().optional(),
|
|
6131
|
-
subtype: z15.unknown().optional(),
|
|
6132
|
-
num_turns: z15.unknown().optional(),
|
|
6133
|
-
permission_denials: z15.unknown().optional(),
|
|
6134
|
-
result: z15.unknown().optional(),
|
|
6135
|
-
session_id: z15.unknown().optional(),
|
|
6136
|
-
usage: z15.unknown().optional()
|
|
6137
|
-
});
|
|
6138
|
-
var USAGE_SCHEMA = z15.looseObject({
|
|
6139
|
-
input_tokens: z15.unknown().optional(),
|
|
6140
|
-
cache_read_input_tokens: z15.unknown().optional(),
|
|
6141
|
-
output_tokens: z15.unknown().optional()
|
|
6142
|
-
});
|
|
6143
|
-
function usable_reason(value) {
|
|
6144
|
-
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
6145
|
-
}
|
|
6146
|
-
function numeric_value(value) {
|
|
6147
|
-
return typeof value === "number" ? value : void 0;
|
|
6148
|
-
}
|
|
6149
|
-
function denial_count(value) {
|
|
6150
|
-
return Array.isArray(value) ? value.length : 0;
|
|
6151
|
-
}
|
|
6152
|
-
function usage_of(value) {
|
|
6153
|
-
const parsed = USAGE_SCHEMA.safeParse(value);
|
|
6154
|
-
if (!parsed.success) return void 0;
|
|
6155
|
-
const usage = {
|
|
6156
|
-
input_tokens: numeric_value(parsed.data.input_tokens),
|
|
6157
|
-
cached_input_tokens: numeric_value(parsed.data.cache_read_input_tokens),
|
|
6158
|
-
output_tokens: numeric_value(parsed.data.output_tokens)
|
|
6159
|
-
};
|
|
6160
|
-
return Object.values(usage).some((count) => count !== void 0) ? usage : void 0;
|
|
6161
|
-
}
|
|
6162
|
-
function decode(value) {
|
|
6163
|
-
const parsed = RESULT_EVENT_SCHEMA.safeParse(value);
|
|
6164
|
-
if (!parsed.success) return void 0;
|
|
6165
|
-
const is_error = parsed.data.is_error === true;
|
|
6166
|
-
return {
|
|
6167
|
-
is_error,
|
|
6168
|
-
subtype: usable_reason(parsed.data.subtype),
|
|
6169
|
-
num_turns: numeric_value(parsed.data.num_turns),
|
|
6170
|
-
permission_denials: denial_count(parsed.data.permission_denials),
|
|
6171
|
-
refused_ask: interactive_ask.refused_ask_of(parsed.data.permission_denials),
|
|
6172
|
-
reason: is_error ? usable_reason(parsed.data.result) ?? usable_reason(parsed.data.subtype) : void 0,
|
|
6173
|
-
session_id: usable_reason(parsed.data.session_id),
|
|
6174
|
-
usage: usage_of(parsed.data.usage)
|
|
6175
|
-
};
|
|
6176
|
-
}
|
|
6177
|
-
var claude_result_event = { decode };
|
|
6178
|
-
|
|
6179
|
-
// scripts/agent/agent-event.ts
|
|
6180
|
-
var TEXT_BLOCK_SCHEMA = z16.looseObject({ type: z16.literal("text"), text: z16.string() });
|
|
6181
|
-
var CLAUDE_MESSAGE_SCHEMA = z16.looseObject({ content: z16.array(z16.unknown()).optional() });
|
|
6182
|
-
var CLAUDE_INIT_SCHEMA = z16.looseObject({ type: z16.literal("system"), subtype: z16.literal("init") });
|
|
6183
|
-
var CLAUDE_ASSISTANT_SCHEMA = z16.looseObject({
|
|
6184
|
-
type: z16.literal("assistant"),
|
|
6185
|
-
message: CLAUDE_MESSAGE_SCHEMA
|
|
6186
|
-
});
|
|
6187
|
-
var USAGE_SCHEMA2 = z16.looseObject({
|
|
6188
|
-
input_tokens: z16.number().optional(),
|
|
6189
|
-
cached_input_tokens: z16.number().optional(),
|
|
6190
|
-
output_tokens: z16.number().optional()
|
|
6191
|
-
});
|
|
6192
|
-
var CODEX_START_SCHEMA = z16.looseObject({ type: z16.enum(["thread.started", "turn.started"]) });
|
|
6193
|
-
var CODEX_PROGRESS_SCHEMA = z16.looseObject({
|
|
6194
|
-
type: z16.enum(["item.started", "item.updated", "item.completed"]),
|
|
6195
|
-
item: z16.looseObject({ type: z16.string(), text: z16.string().optional() }).optional()
|
|
6196
|
-
});
|
|
6197
|
-
var CODEX_COMPLETE_SCHEMA = z16.looseObject({
|
|
6198
|
-
type: z16.literal("turn.completed"),
|
|
6199
|
-
usage: USAGE_SCHEMA2.optional()
|
|
6200
|
-
});
|
|
6201
|
-
var CODEX_FAILURE_SCHEMA = z16.looseObject({
|
|
6202
|
-
type: z16.enum(["turn.failed", "error"]),
|
|
6203
|
-
error: z16.looseObject({ message: z16.string().optional() }).optional(),
|
|
6204
|
-
message: z16.string().optional()
|
|
6205
|
-
});
|
|
6206
|
-
var EMPTY_STATE = {
|
|
6207
|
-
provider: void 0,
|
|
6208
|
-
launch: "pending",
|
|
6209
|
-
progress: void 0,
|
|
6210
|
-
result: "running",
|
|
6211
|
-
reason: void 0,
|
|
6212
|
-
usage: void 0
|
|
6213
|
-
};
|
|
6214
|
-
var LAUNCH_HEADER_PREFIX = "=== ";
|
|
6215
|
-
var LAUNCH_HEADER_MARKER = " \xB7 started by process ";
|
|
6216
|
-
function usable_text(value) {
|
|
6217
|
-
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
6218
|
-
}
|
|
6219
|
-
function claude_progress(content) {
|
|
6220
|
-
return content.map((block) => TEXT_BLOCK_SCHEMA.safeParse(block)).filter((parsed) => parsed.success).map((parsed) => parsed.data.text).findLast((text) => text.trim() !== "");
|
|
6221
|
-
}
|
|
6222
|
-
function claude_result(value, state) {
|
|
6223
|
-
const result = claude_result_event.decode(value);
|
|
6224
|
-
if (result === void 0) return void 0;
|
|
6225
|
-
return {
|
|
6226
|
-
...state,
|
|
6227
|
-
provider: "anthropic",
|
|
6228
|
-
result: result.is_error ? "failed" : "completed",
|
|
6229
|
-
reason: result.is_error ? result.reason ?? state.reason : state.reason,
|
|
6230
|
-
usage: result.usage
|
|
6231
|
-
};
|
|
6232
|
-
}
|
|
6233
|
-
function claude_assistant(value, state) {
|
|
6234
|
-
const assistant = CLAUDE_ASSISTANT_SCHEMA.safeParse(value);
|
|
6235
|
-
if (!assistant.success) return void 0;
|
|
6236
|
-
const progress = claude_progress(assistant.data.message.content ?? []) ?? state.progress;
|
|
6237
|
-
return { ...state, provider: "anthropic", progress };
|
|
6238
|
-
}
|
|
6239
|
-
function claude_terminal(value, state) {
|
|
6240
|
-
return claude_result(value, state);
|
|
6241
|
-
}
|
|
6242
|
-
function claude_event(value, state) {
|
|
6243
|
-
if (CLAUDE_INIT_SCHEMA.safeParse(value).success) {
|
|
6244
|
-
return { ...state, provider: "anthropic", launch: "started" };
|
|
6245
|
-
}
|
|
6246
|
-
return claude_assistant(value, state) ?? claude_terminal(value, state);
|
|
6247
|
-
}
|
|
6248
|
-
function codex_progress(value, state) {
|
|
6249
|
-
const parsed = CODEX_PROGRESS_SCHEMA.safeParse(value);
|
|
6250
|
-
if (!parsed.success) return void 0;
|
|
6251
|
-
const progress = usable_text(parsed.data.item?.text) ?? state.progress;
|
|
6252
|
-
return { ...state, provider: "openai", progress };
|
|
6253
|
-
}
|
|
6254
|
-
function codex_completed(value, state) {
|
|
6255
|
-
const completed = CODEX_COMPLETE_SCHEMA.safeParse(value);
|
|
6256
|
-
if (!completed.success) return void 0;
|
|
6257
|
-
return { ...state, provider: "openai", result: "completed", usage: completed.data.usage };
|
|
6258
|
-
}
|
|
6259
|
-
function codex_failed(value, state) {
|
|
6260
|
-
const failed = CODEX_FAILURE_SCHEMA.safeParse(value);
|
|
6261
|
-
if (!failed.success) return void 0;
|
|
6262
|
-
const reason = usable_text(failed.data.error?.message) ?? usable_text(failed.data.message);
|
|
6263
|
-
return { ...state, provider: "openai", result: "failed", reason: reason ?? state.reason };
|
|
6264
|
-
}
|
|
6265
|
-
function codex_terminal(value, state) {
|
|
6266
|
-
return codex_completed(value, state) ?? codex_failed(value, state);
|
|
6267
|
-
}
|
|
6268
|
-
function codex_event(value, state) {
|
|
6269
|
-
if (CODEX_START_SCHEMA.safeParse(value).success) {
|
|
6270
|
-
return { ...state, provider: "openai", launch: "started" };
|
|
6271
|
-
}
|
|
6272
|
-
return codex_progress(value, state) ?? codex_terminal(value, state);
|
|
6273
|
-
}
|
|
6274
|
-
function normalized(value, state) {
|
|
6275
|
-
return claude_event(value, state) ?? codex_event(value, state) ?? state;
|
|
6276
|
-
}
|
|
6277
|
-
function next_state2(line, state) {
|
|
6278
|
-
const is_header = line.startsWith(LAUNCH_HEADER_PREFIX) && line.includes(LAUNCH_HEADER_MARKER);
|
|
6279
|
-
if (is_header) return EMPTY_STATE;
|
|
6280
|
-
return normalized(json_value.parse_or_undefined(line), state);
|
|
6281
|
-
}
|
|
6282
|
-
function read2(transcript) {
|
|
6283
|
-
let state = EMPTY_STATE;
|
|
6284
|
-
for (const line of transcript.split("\n")) state = next_state2(line, state);
|
|
6285
|
-
return state;
|
|
6286
|
-
}
|
|
6287
|
-
function describe(state) {
|
|
6288
|
-
const progress = state.progress === void 0 ? "" : ` progress=${state.progress}`;
|
|
6289
|
-
const reason = state.reason === void 0 ? "" : ` reason=${state.reason}`;
|
|
6290
|
-
return `launch=${state.launch} result=${state.result}${progress}${reason}`;
|
|
6291
|
-
}
|
|
6292
|
-
var agent_event = { describe, read: read2 };
|
|
6293
|
-
|
|
6294
|
-
// scripts/issue/issue-state.ts
|
|
6295
|
-
import { z as z17 } from "zod";
|
|
6296
|
-
var NO_LABELS = "(none)";
|
|
6297
|
-
var LABEL_SEPARATOR = ", ";
|
|
6298
|
-
var STATE_LABEL = "state: ";
|
|
6299
|
-
var LABELS_LABEL = "labels: ";
|
|
6300
|
-
var HUMAN_REVIEW_LABEL_LINE = "human_review: ";
|
|
6301
|
-
var YES = "yes";
|
|
6302
|
-
var NO = "no";
|
|
6303
|
-
var ISSUE_LABEL = "issue: ";
|
|
6304
|
-
var HUMAN_REVIEW_LABELS = /* @__PURE__ */ new Set([NEEDS_HUMAN_REVIEW_LABEL]);
|
|
6305
|
-
var label_schema = z17.looseObject({ name: z17.string() });
|
|
6306
|
-
var issue_state_schema = z17.looseObject({
|
|
6307
|
-
state: z17.string(),
|
|
6308
|
-
labels: label_schema.array().optional()
|
|
6309
|
-
});
|
|
6310
|
-
function parse_issue_state(json) {
|
|
6311
|
-
try {
|
|
6312
|
-
const parsed = parse_json_object_or_undefined(json, issue_state_schema);
|
|
6313
|
-
if (parsed === void 0) return void 0;
|
|
6314
|
-
const labels = parsed.labels ?? [];
|
|
6315
|
-
return {
|
|
6316
|
-
state: parsed.state,
|
|
6317
|
-
labels: labels.map((label) => label.name),
|
|
6318
|
-
is_human_review: has_any_label(labels, HUMAN_REVIEW_LABELS)
|
|
6319
|
-
};
|
|
6320
|
-
} catch {
|
|
6321
|
-
return void 0;
|
|
6322
|
-
}
|
|
6323
|
-
}
|
|
6324
|
-
function format_labels(labels) {
|
|
6325
|
-
return labels.length === 0 ? NO_LABELS : labels.join(LABEL_SEPARATOR);
|
|
6326
|
-
}
|
|
6327
|
-
function format_issue_state(state) {
|
|
6328
|
-
const human_review = `${HUMAN_REVIEW_LABEL_LINE}${state.is_human_review ? YES : NO}`;
|
|
6329
|
-
return `${STATE_LABEL}${state.state}
|
|
6330
|
-
${LABELS_LABEL}${format_labels(state.labels)}
|
|
6331
|
-
${human_review}`;
|
|
6332
|
-
}
|
|
6333
|
-
function format_attributed_issue_state(issue_number, state) {
|
|
6334
|
-
return `${ISSUE_LABEL}${issue_number}
|
|
6335
|
-
${format_issue_state(state)}`;
|
|
6336
|
-
}
|
|
6337
|
-
var issue_state = {
|
|
6338
|
-
NO_LABELS,
|
|
6339
|
-
parse_issue_state,
|
|
6340
|
-
format_issue_state,
|
|
6341
|
-
format_attributed_issue_state
|
|
6342
|
-
};
|
|
6343
|
-
|
|
6344
|
-
// scripts/run/run-liveness.ts
|
|
6345
|
-
var ALIVE_VERDICT = "alive";
|
|
6346
|
-
var SETTLED_VERDICT = "settled";
|
|
6347
|
-
var STOPPED_VERDICT = "stopped";
|
|
6348
|
-
var UNDETERMINED_VERDICT = "undetermined";
|
|
6349
|
-
var PROCESS_ALIVE = "alive";
|
|
6350
|
-
var PROCESS_UNKNOWN = "unknown";
|
|
6351
|
-
var DEFAULT_SILENT_MINUTES = 30;
|
|
6352
|
-
var DEFAULT_GAP_SECONDS = 5;
|
|
6353
|
-
var MS_PER_MINUTE3 = 6e4;
|
|
6354
|
-
var MS_PER_SECOND2 = 1e3;
|
|
6355
|
-
var OPEN_STATE = "OPEN";
|
|
6356
|
-
var STATE_FIELDS = "state,labels";
|
|
6357
|
-
var REASONS = {
|
|
6358
|
-
[ALIVE_VERDICT]: "The unit is still working: its output moved, or a process of the child is alive.",
|
|
6359
|
-
[SETTLED_VERDICT]: "The child is closed, parked with `needs-decision`, or marked `already-done`, so there is nothing here to recover.",
|
|
6360
|
-
[STOPPED_VERDICT]: "The output has been frozen past the silent window and no process of the child is alive in that checkout.",
|
|
6361
|
-
[UNDETERMINED_VERDICT]: "A trace could not be read, so this says nothing about the unit. A trace that could not be read answers `undetermined`, never `stopped`."
|
|
6362
|
-
};
|
|
6363
|
-
var ALIVE_ADVICE = "Keep polling; do not touch the child.";
|
|
6364
|
-
var SETTLED_ADVICE = "Read the child with `pnpm josh issue:state <N>` and take the branch its state says.";
|
|
6365
|
-
var STOPPED_CLEAN_ADVICE = 'The unit ended \u2014 classify how before booking it. Run `pnpm josh run:merge <N> --output <path>` (add `--epic <E> --repo <owner/repo> --owner "$PPID"` for a named epic): it reads the child\'s exit record without waiting for the unit to return, re-dispatches a child that could not reach the API (counting the outage; a run of them trips the environment guard and stops the run), and parks an abandoned child with `needs-decision` against the consecutive-failure guard. The checkout is clean, so there is nothing to stash.';
|
|
6366
|
-
var STOPPED_DIRTY_ADVICE = 'Stash the half-finished work with `git stash push -u -m "backlogrun: stopped unit for #<N>"` and record it on the Issue, then classify how the unit ended with `pnpm josh run:merge <N> --output <path>` (add `--epic <E> --repo <owner/repo> --owner "$PPID"` for a named epic): it re-dispatches an API-outage child (counting the outage; a run of them trips the environment guard) and parks an abandoned child with `needs-decision` against the consecutive-failure guard, without waiting for the unit to return.';
|
|
6367
|
-
var UNDETERMINED_ADVICE = "Read the trace that failed and ask again. Where the process trace was given as `unknown`, leave `--process` out so the command reads it. Two of these in a row is a fault in the check itself rather than a slow unit: stop polling and report it.";
|
|
6368
|
-
function is_output_moving(traces) {
|
|
6369
|
-
return traces.is_output_frozen === false;
|
|
6370
|
-
}
|
|
6371
|
-
function is_agent_state_finished(state) {
|
|
6372
|
-
return state?.result === "completed" || state?.result === "failed";
|
|
6373
|
-
}
|
|
6374
|
-
function is_agent_finished(traces) {
|
|
6375
|
-
return is_agent_state_finished(traces.agent_state);
|
|
6376
|
-
}
|
|
6377
|
-
function definitive_verdict(traces) {
|
|
6378
|
-
if (traces.is_child_settled === true) return SETTLED_VERDICT;
|
|
6379
|
-
if (is_agent_finished(traces)) return STOPPED_VERDICT;
|
|
6380
|
-
if (is_output_moving(traces)) return ALIVE_VERDICT;
|
|
6381
|
-
return void 0;
|
|
6382
|
-
}
|
|
6383
|
-
function is_check_running(traces) {
|
|
6384
|
-
return traces.process_trace === PROCESS_ALIVE;
|
|
6385
|
-
}
|
|
6386
|
-
function has_unreadable_trace(traces) {
|
|
6387
|
-
return traces.is_child_settled === void 0 || traces.is_output_frozen === void 0 || traces.process_trace === PROCESS_UNKNOWN;
|
|
6388
|
-
}
|
|
6389
|
-
function to_verdict(traces) {
|
|
6390
|
-
const definitive = definitive_verdict(traces);
|
|
6391
|
-
if (definitive !== void 0) return definitive;
|
|
6392
|
-
if (has_unreadable_trace(traces)) return UNDETERMINED_VERDICT;
|
|
6393
|
-
return is_check_running(traces) ? ALIVE_VERDICT : STOPPED_VERDICT;
|
|
6394
|
-
}
|
|
6395
|
-
function to_advice(verdict, has_work_to_stash) {
|
|
6396
|
-
if (verdict === ALIVE_VERDICT) return ALIVE_ADVICE;
|
|
6397
|
-
if (verdict === SETTLED_VERDICT) return SETTLED_ADVICE;
|
|
6398
|
-
if (verdict === UNDETERMINED_VERDICT) return UNDETERMINED_ADVICE;
|
|
6399
|
-
return has_work_to_stash ? STOPPED_DIRTY_ADVICE : STOPPED_CLEAN_ADVICE;
|
|
6400
|
-
}
|
|
6401
|
-
function decide5(traces) {
|
|
6402
|
-
const verdict = to_verdict(traces);
|
|
6403
|
-
const has_work_to_stash = verdict === STOPPED_VERDICT && traces.is_tree_dirty;
|
|
6404
|
-
return {
|
|
6405
|
-
advice: to_advice(verdict, has_work_to_stash),
|
|
6406
|
-
has_work_to_stash,
|
|
6407
|
-
reason: traces.agent_state?.reason ?? REASONS[verdict],
|
|
6408
|
-
verdict
|
|
6409
|
-
};
|
|
6410
|
-
}
|
|
6411
|
-
function to_resolved_root(root) {
|
|
6412
|
-
try {
|
|
6413
|
-
return realpathSync(root);
|
|
6414
|
-
} catch {
|
|
6415
|
-
return root;
|
|
6416
|
-
}
|
|
6417
|
-
}
|
|
6418
|
-
var ALLOWED_ROOTS = [
|
|
6419
|
-
...new Set(
|
|
6420
|
-
[homedir(), tmpdir(), PLATFORM_TEMP_ROOT].flatMap((root) => [root, to_resolved_root(root)])
|
|
6421
|
-
)
|
|
6422
|
-
];
|
|
6423
|
-
function is_within(candidate, root) {
|
|
6424
|
-
const relative = path14.relative(root, candidate);
|
|
6425
|
-
return relative !== "" && !relative.startsWith("..") && !path14.isAbsolute(relative);
|
|
6426
|
-
}
|
|
6427
|
-
function to_safe_path(output_path) {
|
|
6428
|
-
const normalized2 = path14.normalize(output_path);
|
|
6429
|
-
if (!path14.isAbsolute(normalized2)) return void 0;
|
|
6430
|
-
return ALLOWED_ROOTS.some((root) => is_within(normalized2, root)) ? normalized2 : void 0;
|
|
6431
|
-
}
|
|
6432
|
-
function sample_output(output_path) {
|
|
6433
|
-
const safe_path = to_safe_path(output_path);
|
|
6434
|
-
if (safe_path === void 0) return void 0;
|
|
6435
|
-
const stats = statSync(safe_path, { throwIfNoEntry: false });
|
|
6436
|
-
if (!stats?.isFile()) return void 0;
|
|
6437
|
-
return { mtime_ms: stats.mtimeMs, size: stats.size };
|
|
6438
|
-
}
|
|
6439
|
-
function read_agent_state(output_path) {
|
|
6440
|
-
const safe_path = to_safe_path(output_path);
|
|
6441
|
-
if (safe_path === void 0) return void 0;
|
|
6442
|
-
try {
|
|
6443
|
-
const state = agent_event.read(readFileSync7(safe_path, "utf8"));
|
|
6444
|
-
return state.provider === void 0 ? void 0 : state;
|
|
6445
|
-
} catch {
|
|
6446
|
-
return void 0;
|
|
6447
|
-
}
|
|
6448
|
-
}
|
|
6449
|
-
function describe_agent_state(output_path) {
|
|
6450
|
-
const state = read_agent_state(output_path);
|
|
6451
|
-
return state === void 0 ? void 0 : `agent: ${state.provider ?? "unknown"} ${agent_event.describe(state)}`;
|
|
6452
|
-
}
|
|
6453
|
-
async function read_output_frozen(request2) {
|
|
6454
|
-
const first = sample_output(request2.output_path);
|
|
6455
|
-
if (first === void 0) return void 0;
|
|
6456
|
-
if (request2.now_ms - first.mtime_ms < request2.silent_window_ms) return false;
|
|
6457
|
-
await sleep(request2.gap_ms);
|
|
6458
|
-
const second = sample_output(request2.output_path);
|
|
6459
|
-
if (second === void 0) return void 0;
|
|
6460
|
-
return second.mtime_ms === first.mtime_ms && second.size === first.size;
|
|
6461
|
-
}
|
|
6462
|
-
function carries_label(labels, wanted) {
|
|
6463
|
-
return labels.some((label) => label.toLowerCase() === wanted);
|
|
6464
|
-
}
|
|
6465
|
-
var SETTLED_LABELS = [NEEDS_DECISION_LABEL, ALREADY_DONE_LABEL];
|
|
6466
|
-
function carries_settled_label(labels) {
|
|
6467
|
-
return SETTLED_LABELS.some((label) => carries_label(labels, label));
|
|
6468
|
-
}
|
|
6469
|
-
async function read_child_settled(issue, repo) {
|
|
6470
|
-
const json = await git_gh_issue_read.issue_view_json(issue, STATE_FIELDS, repo);
|
|
6471
|
-
if (json === void 0) return void 0;
|
|
6472
|
-
const state = issue_state.parse_issue_state(json);
|
|
6473
|
-
if (state === void 0) return void 0;
|
|
6474
|
-
return state.state !== OPEN_STATE || carries_settled_label(state.labels);
|
|
6475
|
-
}
|
|
6476
|
-
async function read_traces(request2) {
|
|
6477
|
-
const [is_initial_child_settled, is_output_frozen, is_tree_dirty] = await Promise.all([
|
|
6478
|
-
read_child_settled(request2.issue, request2.repo),
|
|
6479
|
-
read_output_frozen({
|
|
6480
|
-
gap_ms: request2.gap_ms ?? DEFAULT_GAP_SECONDS * MS_PER_SECOND2,
|
|
6481
|
-
now_ms: Date.now(),
|
|
6482
|
-
output_path: request2.output_path,
|
|
6483
|
-
silent_window_ms: request2.silent_window_ms ?? DEFAULT_SILENT_MINUTES * MS_PER_MINUTE3
|
|
6484
|
-
}),
|
|
6485
|
-
run_hold.is_tree_dirty()
|
|
6486
|
-
]);
|
|
6487
|
-
const agent_state = read_agent_state(request2.output_path);
|
|
6488
|
-
const is_latest_child_settled = is_agent_state_finished(agent_state) ? await read_child_settled(request2.issue, request2.repo) : void 0;
|
|
6489
|
-
const is_child_settled = is_latest_child_settled ?? is_initial_child_settled;
|
|
6490
|
-
return {
|
|
6491
|
-
agent_state,
|
|
6492
|
-
is_child_settled,
|
|
6493
|
-
is_output_frozen,
|
|
6494
|
-
is_tree_dirty,
|
|
6495
|
-
process_trace: request2.process_trace
|
|
6496
|
-
};
|
|
6497
|
-
}
|
|
6498
|
-
async function check2(request2) {
|
|
6499
|
-
issue_number_shape.require_issue_number(request2.issue);
|
|
6500
|
-
return decide5(await read_traces(request2));
|
|
6501
|
-
}
|
|
6502
|
-
var run_liveness = {
|
|
6503
|
-
check: check2,
|
|
6504
|
-
decide: decide5,
|
|
6505
|
-
describe_agent_state,
|
|
6506
|
-
read_child_settled,
|
|
6507
|
-
read_output_frozen,
|
|
6508
|
-
sample_output,
|
|
6509
|
-
to_safe_path
|
|
6510
|
-
};
|
|
6511
|
-
|
|
6512
5770
|
// scripts/lane/lane-report.ts
|
|
6513
5771
|
var NO_LANES2 = "No lanes are open.";
|
|
6514
|
-
var
|
|
5772
|
+
var OPEN_STATE = "open";
|
|
6515
5773
|
var STRANDED_STATE = "stranded";
|
|
6516
5774
|
var UNREADABLE_STATE = "unreadable";
|
|
6517
5775
|
var UNKNOWN_VALUE = "-";
|
|
6518
5776
|
var COLUMN_SEPARATOR = " ";
|
|
6519
5777
|
function lane_state(lane) {
|
|
6520
5778
|
if (lane.is_stranded) return STRANDED_STATE;
|
|
6521
|
-
return lane.seat === void 0 ? UNREADABLE_STATE :
|
|
5779
|
+
return lane.seat === void 0 ? UNREADABLE_STATE : OPEN_STATE;
|
|
6522
5780
|
}
|
|
6523
5781
|
function value_or_unknown(value) {
|
|
6524
5782
|
return value === void 0 ? UNKNOWN_VALUE : String(value);
|
|
@@ -6562,7 +5820,7 @@ function describe_opened(lane) {
|
|
|
6562
5820
|
}
|
|
6563
5821
|
var lane_report = {
|
|
6564
5822
|
NO_LANES: NO_LANES2,
|
|
6565
|
-
OPEN_STATE
|
|
5823
|
+
OPEN_STATE,
|
|
6566
5824
|
STRANDED_STATE,
|
|
6567
5825
|
UNREADABLE_STATE,
|
|
6568
5826
|
describe_lane,
|
|
@@ -6571,197 +5829,6 @@ var lane_report = {
|
|
|
6571
5829
|
lane_state
|
|
6572
5830
|
};
|
|
6573
5831
|
|
|
6574
|
-
// scripts/run/run-preflight.ts
|
|
6575
|
-
import { z as z18 } from "zod";
|
|
6576
|
-
var CLEAN_VERDICT = "clean";
|
|
6577
|
-
var RECLAIM_VERDICT = "reclaim";
|
|
6578
|
-
var RESUME_VERDICT = "resume";
|
|
6579
|
-
var PARK_VERDICT = "park";
|
|
6580
|
-
var NO_PR = "none";
|
|
6581
|
-
var OPEN_PR = "open";
|
|
6582
|
-
var MERGED_PR = "merged";
|
|
6583
|
-
var CLOSED_PR = "closed";
|
|
6584
|
-
var NO_CHILD_WORK = { branch_name: void 0, pr_state: NO_PR };
|
|
6585
|
-
var pr_info_schema = z18.object({ state: z18.string().optional() });
|
|
6586
|
-
var GH_PR_STATES = /* @__PURE__ */ new Map([
|
|
6587
|
-
["CLOSED", CLOSED_PR],
|
|
6588
|
-
["MERGED", MERGED_PR],
|
|
6589
|
-
["OPEN", OPEN_PR]
|
|
6590
|
-
]);
|
|
6591
|
-
var CLEAN_REASON = "Nothing was left behind: the tree is clean, HEAD is on the default branch, and this issue has no pull request and no branch holding work.";
|
|
6592
|
-
var CLEAN_ADVICE = "Start the child.";
|
|
6593
|
-
var RESUME_ADVICE = "Reuse the branch and run the whole verification gate from the start \u2014 refactor, `pnpm josh gate`, `/code-review` \u2014 never only the part the interrupted run had not reached. Nobody verified what it already committed.";
|
|
6594
|
-
var PARK_ADVICE = "Park the child: add `needs-decision` and comment what was found. Do not delete the branch, do not reopen the pull request, and do not commit on top of it.";
|
|
6595
|
-
var STASH_LABEL_PREFIX = "run:hold reclaimed before #";
|
|
6596
|
-
var { require_issue_number } = issue_number_shape;
|
|
6597
|
-
var UNREADABLE_PR_MESSAGE = "The pull request could not be read for branch ";
|
|
6598
|
-
function needs_reclaim(tree) {
|
|
6599
|
-
return tree.is_dirty || tree.branch !== tree.default_branch;
|
|
6600
|
-
}
|
|
6601
|
-
function is_pr_decided(state) {
|
|
6602
|
-
return state === MERGED_PR || state === CLOSED_PR;
|
|
6603
|
-
}
|
|
6604
|
-
function has_leftover_work(child) {
|
|
6605
|
-
return child.branch_name !== void 0 || child.pr_state === OPEN_PR;
|
|
6606
|
-
}
|
|
6607
|
-
function to_verdict2(tree, child) {
|
|
6608
|
-
if (needs_reclaim(tree)) return RECLAIM_VERDICT;
|
|
6609
|
-
if (is_pr_decided(child.pr_state)) return PARK_VERDICT;
|
|
6610
|
-
if (has_leftover_work(child)) return RESUME_VERDICT;
|
|
6611
|
-
return CLEAN_VERDICT;
|
|
6612
|
-
}
|
|
6613
|
-
function reclaim_reason(tree) {
|
|
6614
|
-
const findings = [
|
|
6615
|
-
tree.is_dirty ? "uncommitted changes" : void 0,
|
|
6616
|
-
tree.branch === tree.default_branch ? void 0 : `HEAD on ${tree.branch}`
|
|
6617
|
-
].filter((entry) => entry !== void 0);
|
|
6618
|
-
return `An earlier run left ${findings.join(" and ")} in this working tree.`;
|
|
6619
|
-
}
|
|
6620
|
-
function park_reason(state) {
|
|
6621
|
-
return `The pull request for this issue is ${state}, so whether any work is still owed is a person's call.`;
|
|
6622
|
-
}
|
|
6623
|
-
function resume_reason(child) {
|
|
6624
|
-
const branch_part = child.branch_name === void 0 ? "" : ` on branch ${child.branch_name}`;
|
|
6625
|
-
const pr_part = child.pr_state === OPEN_PR ? ", and its pull request is still open" : "";
|
|
6626
|
-
return `An earlier run left a partial implementation${branch_part}${pr_part}.`;
|
|
6627
|
-
}
|
|
6628
|
-
function to_reason(verdict, tree, child) {
|
|
6629
|
-
if (verdict === RECLAIM_VERDICT) return reclaim_reason(tree);
|
|
6630
|
-
if (verdict === PARK_VERDICT) return park_reason(child.pr_state);
|
|
6631
|
-
if (verdict === RESUME_VERDICT) return resume_reason(child);
|
|
6632
|
-
return CLEAN_REASON;
|
|
6633
|
-
}
|
|
6634
|
-
function reclaim_steps(tree, issue) {
|
|
6635
|
-
if (!tree.is_dirty) return [];
|
|
6636
|
-
return [
|
|
6637
|
-
`git stash push -u -m "${STASH_LABEL_PREFIX}${issue}"`,
|
|
6638
|
-
`Record the stash on ${session_cite.issue(issue)} \u2014 the comment is what gets it popped; nothing pops it for you.`
|
|
6639
|
-
];
|
|
6640
|
-
}
|
|
6641
|
-
function reclaim_advice(tree, issue) {
|
|
6642
|
-
return [
|
|
6643
|
-
...reclaim_steps(tree, issue),
|
|
6644
|
-
"pnpm josh ms",
|
|
6645
|
-
"Then ask this command again: it is re-askable, and the clean tree gets its own answer."
|
|
6646
|
-
].join("\n");
|
|
6647
|
-
}
|
|
6648
|
-
function to_advice2(verdict, issue, tree) {
|
|
6649
|
-
if (verdict === RECLAIM_VERDICT) return reclaim_advice(tree, issue);
|
|
6650
|
-
if (verdict === RESUME_VERDICT) return RESUME_ADVICE;
|
|
6651
|
-
if (verdict === PARK_VERDICT) return PARK_ADVICE;
|
|
6652
|
-
return CLEAN_ADVICE;
|
|
6653
|
-
}
|
|
6654
|
-
function decide6(tree, child, issue) {
|
|
6655
|
-
const verdict = to_verdict2(tree, child);
|
|
6656
|
-
return {
|
|
6657
|
-
advice: to_advice2(verdict, issue, tree),
|
|
6658
|
-
reason: to_reason(verdict, tree, child),
|
|
6659
|
-
verdict
|
|
6660
|
-
};
|
|
6661
|
-
}
|
|
6662
|
-
function read_pr_field(raw) {
|
|
6663
|
-
return json_value.parse_with(raw, pr_info_schema)?.state;
|
|
6664
|
-
}
|
|
6665
|
-
function to_pr_state(raw) {
|
|
6666
|
-
const state = read_pr_field(raw);
|
|
6667
|
-
return (state === void 0 ? void 0 : GH_PR_STATES.get(state)) ?? NO_PR;
|
|
6668
|
-
}
|
|
6669
|
-
async function read_tree_state() {
|
|
6670
|
-
const [is_dirty, current, default_branch] = await Promise.all([
|
|
6671
|
-
run_hold.is_tree_dirty(),
|
|
6672
|
-
git_command.branch(),
|
|
6673
|
-
git_command.get_default_branch()
|
|
6674
|
-
]);
|
|
6675
|
-
return { branch: current, default_branch, is_dirty };
|
|
6676
|
-
}
|
|
6677
|
-
async function read_pr_state(branch_name) {
|
|
6678
|
-
if (!await git_gh_pr_read.pr_exists(branch_name)) return NO_PR;
|
|
6679
|
-
const raw = await git_gh_pr_read.pr_view(branch_name);
|
|
6680
|
-
if (raw === "") throw new Error(`${UNREADABLE_PR_MESSAGE}${branch_name}`);
|
|
6681
|
-
return to_pr_state(raw);
|
|
6682
|
-
}
|
|
6683
|
-
function is_pr_open(state) {
|
|
6684
|
-
return state === OPEN_PR;
|
|
6685
|
-
}
|
|
6686
|
-
async function read_pr_of_branch(branch_name) {
|
|
6687
|
-
return { branch_name, pr_state: await read_pr_state(branch_name) };
|
|
6688
|
-
}
|
|
6689
|
-
function pick_child_state(reads) {
|
|
6690
|
-
const decided = reads.find((read3) => is_pr_decided(read3.pr_state));
|
|
6691
|
-
const open = reads.find((read3) => is_pr_open(read3.pr_state));
|
|
6692
|
-
return decided ?? open ?? { branch_name: reads[0]?.branch_name, pr_state: NO_PR };
|
|
6693
|
-
}
|
|
6694
|
-
var ISSUE_BRANCH_SUFFIX = "-*";
|
|
6695
|
-
var ANY_REMOTE_PREFIX = "*/";
|
|
6696
|
-
var REMOTE_SEPARATOR = "/";
|
|
6697
|
-
var NOT_FOUND_INDEX = -1;
|
|
6698
|
-
function to_head_branch(name) {
|
|
6699
|
-
const separator_index = name.indexOf(REMOTE_SEPARATOR);
|
|
6700
|
-
return separator_index === NOT_FOUND_INDEX ? name : name.slice(separator_index + 1);
|
|
6701
|
-
}
|
|
6702
|
-
function group_by_head(pairs) {
|
|
6703
|
-
const groups = /* @__PURE__ */ new Map();
|
|
6704
|
-
for (const [name, reference] of pairs) groups.set(name, [...groups.get(name) ?? [], reference]);
|
|
6705
|
-
return groups;
|
|
6706
|
-
}
|
|
6707
|
-
async function read_branch_candidates(issue) {
|
|
6708
|
-
const pattern = `${issue}${ISSUE_BRANCH_SUFFIX}`;
|
|
6709
|
-
const [local, remote] = await Promise.all([
|
|
6710
|
-
git_command.branch_names(pattern),
|
|
6711
|
-
git_command.branch_names_remote(`${ANY_REMOTE_PREFIX}${pattern}`)
|
|
6712
|
-
]);
|
|
6713
|
-
return group_by_head([
|
|
6714
|
-
...local.map((name) => [name, name]),
|
|
6715
|
-
...remote.map((reference) => [to_head_branch(reference), reference])
|
|
6716
|
-
]);
|
|
6717
|
-
}
|
|
6718
|
-
async function has_commits_beyond(base, references) {
|
|
6719
|
-
const counts = await Promise.all(
|
|
6720
|
-
references.map(async (reference) => await git_command.commit_count_beyond(base, reference))
|
|
6721
|
-
);
|
|
6722
|
-
return counts.some((count) => count > 0);
|
|
6723
|
-
}
|
|
6724
|
-
async function is_held_dirty(name, lane) {
|
|
6725
|
-
if (lane?.branch !== name || lane.is_stranded) return false;
|
|
6726
|
-
return await run_hold.is_tree_dirty(lane.directory);
|
|
6727
|
-
}
|
|
6728
|
-
async function read_candidate(name, references, context) {
|
|
6729
|
-
const state = await read_pr_of_branch(name);
|
|
6730
|
-
if (state.pr_state !== NO_PR || await has_commits_beyond(context.base, references)) return state;
|
|
6731
|
-
return await is_held_dirty(name, context.lane) ? state : void 0;
|
|
6732
|
-
}
|
|
6733
|
-
async function read_child_state(issue) {
|
|
6734
|
-
const candidates = await read_branch_candidates(issue);
|
|
6735
|
-
if (candidates.size === 0) return NO_CHILD_WORK;
|
|
6736
|
-
const [base, lane] = await Promise.all([
|
|
6737
|
-
git_command.default_branch_reference(),
|
|
6738
|
-
lane_registry.find_open_lane(issue)
|
|
6739
|
-
]);
|
|
6740
|
-
const reads = await Promise.all(
|
|
6741
|
-
[...candidates].map(
|
|
6742
|
-
async ([name, references]) => await read_candidate(name, references, { base, lane })
|
|
6743
|
-
)
|
|
6744
|
-
);
|
|
6745
|
-
return pick_child_state(reads.filter((read3) => read3 !== void 0));
|
|
6746
|
-
}
|
|
6747
|
-
async function check3(issue) {
|
|
6748
|
-
require_issue_number(issue);
|
|
6749
|
-
const tree = await read_tree_state();
|
|
6750
|
-
if (needs_reclaim(tree)) return decide6(tree, NO_CHILD_WORK, issue);
|
|
6751
|
-
return decide6(tree, await read_child_state(issue), issue);
|
|
6752
|
-
}
|
|
6753
|
-
var run_preflight = {
|
|
6754
|
-
CLEAN_VERDICT,
|
|
6755
|
-
RESUME_ADVICE,
|
|
6756
|
-
MERGED_PR,
|
|
6757
|
-
STASH_LABEL_PREFIX,
|
|
6758
|
-
check: check3,
|
|
6759
|
-
decide: decide6,
|
|
6760
|
-
read_child_state,
|
|
6761
|
-
read_pr_state,
|
|
6762
|
-
to_pr_state
|
|
6763
|
-
};
|
|
6764
|
-
|
|
6765
5832
|
// scripts/run/progress/run-progress-read.ts
|
|
6766
5833
|
var { mark: mark2, parse_stamp: parse_stamp2, read_last_report: read_last_report2 } = run_progress_clock;
|
|
6767
5834
|
var FIRST_LOAD_AVERAGE = 0;
|
|
@@ -6789,10 +5856,10 @@ async function to_child(issue) {
|
|
|
6789
5856
|
return { issue: number, title: issue.title, labels: to_labels(issue), pr_state: child.pr_state };
|
|
6790
5857
|
}
|
|
6791
5858
|
async function read_children(repo) {
|
|
6792
|
-
const
|
|
6793
|
-
if (
|
|
6794
|
-
if (
|
|
6795
|
-
return await Promise.all(
|
|
5859
|
+
const read2 = await epic_busy.read_repository(repo);
|
|
5860
|
+
if (read2.kind === "idle") return [];
|
|
5861
|
+
if (read2.kind !== "busy") return void 0;
|
|
5862
|
+
return await Promise.all(read2.issues.map(async (issue) => await to_child(issue)));
|
|
6796
5863
|
}
|
|
6797
5864
|
async function read_lanes() {
|
|
6798
5865
|
const lanes = await lane_registry.list_lanes();
|
|
@@ -6806,11 +5873,11 @@ function read_record_age(paths, now_ms) {
|
|
|
6806
5873
|
if (times.length === 0) return void 0;
|
|
6807
5874
|
return now_ms - Math.max(...times);
|
|
6808
5875
|
}
|
|
6809
|
-
function is_hold_present(
|
|
6810
|
-
return
|
|
5876
|
+
function is_hold_present(read2) {
|
|
5877
|
+
return read2.kind === "held" || read2.kind === "stale";
|
|
6811
5878
|
}
|
|
6812
|
-
function is_carry_present(
|
|
6813
|
-
return
|
|
5879
|
+
function is_carry_present(read2) {
|
|
5880
|
+
return read2.kind === "carried";
|
|
6814
5881
|
}
|
|
6815
5882
|
function hold_present(worktree) {
|
|
6816
5883
|
return worktree !== void 0 && is_hold_present(run_hold.read_hold(run_hold.hold_path(worktree)));
|
|
@@ -6854,21 +5921,21 @@ var run_progress_read = {
|
|
|
6854
5921
|
};
|
|
6855
5922
|
|
|
6856
5923
|
// scripts/run/run-watcher-hook.ts
|
|
6857
|
-
import { z as
|
|
5924
|
+
import { z as z13 } from "zod";
|
|
6858
5925
|
|
|
6859
5926
|
// scripts/run/run-watcher-guard.ts
|
|
6860
5927
|
var WATCHER_TICK_MS = 3e4;
|
|
6861
5928
|
var TICK_MULTIPLIER = 3;
|
|
6862
|
-
var
|
|
5929
|
+
var MS_PER_SECOND2 = 1e3;
|
|
6863
5930
|
var STALE_THRESHOLD_MS = WATCHER_TICK_MS * TICK_MULTIPLIER;
|
|
6864
|
-
var STALE_THRESHOLD_S = STALE_THRESHOLD_MS /
|
|
5931
|
+
var STALE_THRESHOLD_S = STALE_THRESHOLD_MS / MS_PER_SECOND2;
|
|
6865
5932
|
var STALE_NOTE = `Lane children are in-flight but the progress watcher has not pinged in the last ${String(STALE_THRESHOLD_S)}s \u2014 run \`pnpm josh run:progress --wait\` in the background before proceeding. It reports to the run event stream on its own and exits only when newly runnable work arrives, so start it once and relay nothing`;
|
|
6866
5933
|
var OK_RESULT = { kind: "ok" };
|
|
6867
5934
|
async function owes_watcher() {
|
|
6868
5935
|
if (run_headless.is_headless() || !await run_headless.is_backlog_parent()) return false;
|
|
6869
5936
|
return await lane_registry.has_lanes_in_flight();
|
|
6870
5937
|
}
|
|
6871
|
-
async function
|
|
5938
|
+
async function check2(life_target) {
|
|
6872
5939
|
if (!await owes_watcher() || run_progress_clock.is_life_fresh(life_target, STALE_THRESHOLD_MS)) {
|
|
6873
5940
|
return OK_RESULT;
|
|
6874
5941
|
}
|
|
@@ -6877,13 +5944,13 @@ async function check4(life_target) {
|
|
|
6877
5944
|
var run_watcher_guard = {
|
|
6878
5945
|
STALE_NOTE,
|
|
6879
5946
|
STALE_THRESHOLD_MS,
|
|
6880
|
-
check:
|
|
5947
|
+
check: check2
|
|
6881
5948
|
};
|
|
6882
5949
|
|
|
6883
5950
|
// scripts/run/run-watcher-hook.ts
|
|
6884
5951
|
var SWITCH_ENV_KEY2 = "JOSH_WATCHER_GUARD";
|
|
6885
5952
|
var STAMP_PREFIX2 = "josh-watcher-guard-";
|
|
6886
|
-
var payload_schema =
|
|
5953
|
+
var payload_schema = z13.object({ transcript_path: z13.string().min(1) });
|
|
6887
5954
|
function transcript_of(raw_payload) {
|
|
6888
5955
|
return json_value.parse_with(raw_payload, payload_schema)?.transcript_path;
|
|
6889
5956
|
}
|
|
@@ -6913,7 +5980,7 @@ var run_watcher_hook = { transcript_of, watcher_hook_reason };
|
|
|
6913
5980
|
var SWITCH_ENV_KEY3 = "JOSH_PARENT_CUT_GUARD";
|
|
6914
5981
|
var STAMP_PREFIX3 = "josh-parent-cut-guard-";
|
|
6915
5982
|
var QUIET_WINDOW_MS = 6e5;
|
|
6916
|
-
function
|
|
5983
|
+
function current_state2() {
|
|
6917
5984
|
return {
|
|
6918
5985
|
carry: async () => await run_headless.driving_carry(),
|
|
6919
5986
|
verdict: () => implementation_cut_verdict.reused_verdict(() => cost_cli.session_verdict())
|
|
@@ -6947,7 +6014,7 @@ function is_unit_call(raw_payload) {
|
|
|
6947
6014
|
function is_exempt2(raw_payload) {
|
|
6948
6015
|
return !hook_decision.is_switch_enabled(SWITCH_ENV_KEY3) || is_unit_call(raw_payload);
|
|
6949
6016
|
}
|
|
6950
|
-
async function parent_cut_reason(raw_payload, now_ms = Date.now(), state =
|
|
6017
|
+
async function parent_cut_reason(raw_payload, now_ms = Date.now(), state = current_state2()) {
|
|
6951
6018
|
if (is_exempt2(raw_payload)) return void 0;
|
|
6952
6019
|
const transcript = run_watcher_hook.transcript_of(raw_payload);
|
|
6953
6020
|
if (transcript === void 0) return void 0;
|
|
@@ -6960,8 +6027,95 @@ var run_parent_cut_hook = {
|
|
|
6960
6027
|
parent_cut_reason
|
|
6961
6028
|
};
|
|
6962
6029
|
|
|
6030
|
+
// scripts/run/run-poll-hook.ts
|
|
6031
|
+
var SWITCH_ENV_KEY4 = "JOSH_POLL_GUARD";
|
|
6032
|
+
var BASH_TOOL = "Bash";
|
|
6033
|
+
var STATE_READS = /* @__PURE__ */ new Set([
|
|
6034
|
+
"josh lane:list",
|
|
6035
|
+
"josh lane:output",
|
|
6036
|
+
"josh run:board",
|
|
6037
|
+
"josh run:carry",
|
|
6038
|
+
"josh run:liveness",
|
|
6039
|
+
"josh run:progress",
|
|
6040
|
+
"josh run:wake"
|
|
6041
|
+
]);
|
|
6042
|
+
var POLL_REASON = '\u26D4 poll: this `backlogrun` session repeats a state read with nothing decided in between, on every occurrence. Wait on `pnpm josh backlog:drive`, or `pnpm josh lane:await <N...> --owner "$PPID"` in the background, and end the turn; its exit is the wake.';
|
|
6043
|
+
var WRITING_FLAGS = /* @__PURE__ */ new Set([
|
|
6044
|
+
"--begin",
|
|
6045
|
+
"--cut",
|
|
6046
|
+
"--done",
|
|
6047
|
+
"--end",
|
|
6048
|
+
"--every",
|
|
6049
|
+
"--filed",
|
|
6050
|
+
"--loop",
|
|
6051
|
+
"--mark",
|
|
6052
|
+
"--merged",
|
|
6053
|
+
"--resume",
|
|
6054
|
+
"--retrospective",
|
|
6055
|
+
"--start",
|
|
6056
|
+
"--stop",
|
|
6057
|
+
"--wait"
|
|
6058
|
+
]);
|
|
6059
|
+
var FLAG_PREFIX4 = "-";
|
|
6060
|
+
var NAME_WORDS = 2;
|
|
6061
|
+
var SIGNATURE_SEPARATOR = " ";
|
|
6062
|
+
function read_key(signature) {
|
|
6063
|
+
const words = signature.split(SIGNATURE_SEPARATOR);
|
|
6064
|
+
const name = words.slice(0, NAME_WORDS).join(SIGNATURE_SEPARATOR);
|
|
6065
|
+
if (!STATE_READS.has(name) || words.some((word) => WRITING_FLAGS.has(word))) return void 0;
|
|
6066
|
+
return words.filter((word) => !word.startsWith(FLAG_PREFIX4)).join(SIGNATURE_SEPARATOR);
|
|
6067
|
+
}
|
|
6068
|
+
function read_keys(signatures) {
|
|
6069
|
+
return signatures.map((signature) => read_key(signature)).filter((key) => key !== void 0);
|
|
6070
|
+
}
|
|
6071
|
+
function state_reads_of(command) {
|
|
6072
|
+
return read_keys(time_shell.josh_signatures_of(command));
|
|
6073
|
+
}
|
|
6074
|
+
function command_of(input) {
|
|
6075
|
+
if (typeof input !== "object" || input === null || !("command" in input)) return "";
|
|
6076
|
+
return typeof input.command === "string" ? input.command : "";
|
|
6077
|
+
}
|
|
6078
|
+
function candidate_reads(raw_payload) {
|
|
6079
|
+
const payload = hook_decision.parse_hook_payload(raw_payload);
|
|
6080
|
+
if (payload?.tool_name !== BASH_TOOL || (payload.agent_id ?? "") !== "") return [];
|
|
6081
|
+
return state_reads_of(command_of(payload.tool_input));
|
|
6082
|
+
}
|
|
6083
|
+
function last_step(tail) {
|
|
6084
|
+
return time_spans.parse_timeline(tail).spans.findLast((span) => span.category !== time_spans.MODEL_CATEGORY);
|
|
6085
|
+
}
|
|
6086
|
+
function repeats_last_call(tail, reads) {
|
|
6087
|
+
const last = last_step(tail);
|
|
6088
|
+
if (last?.category !== time_spans.TOOL_CATEGORY) return false;
|
|
6089
|
+
const last_reads = read_keys(last.josh_signatures);
|
|
6090
|
+
return reads.some((key) => last_reads.includes(key));
|
|
6091
|
+
}
|
|
6092
|
+
function is_repeat(raw_payload) {
|
|
6093
|
+
const reads = hook_decision.is_switch_enabled(SWITCH_ENV_KEY4) ? candidate_reads(raw_payload) : [];
|
|
6094
|
+
const transcript = reads.length === 0 ? void 0 : run_watcher_hook.transcript_of(raw_payload);
|
|
6095
|
+
if (transcript === void 0) return false;
|
|
6096
|
+
return repeats_last_call(time_density_hook.read_tail(transcript), reads);
|
|
6097
|
+
}
|
|
6098
|
+
async function poll_reason(raw_payload, is_parent = run_headless.is_backlog_parent) {
|
|
6099
|
+
if (!is_repeat(raw_payload)) return void 0;
|
|
6100
|
+
return await is_parent() ? POLL_REASON : void 0;
|
|
6101
|
+
}
|
|
6102
|
+
async function safe_poll_reason(raw_payload) {
|
|
6103
|
+
try {
|
|
6104
|
+
return await poll_reason(raw_payload);
|
|
6105
|
+
} catch (error) {
|
|
6106
|
+
error_text.trace_swallowed("run_poll_hook.poll_reason", error);
|
|
6107
|
+
return void 0;
|
|
6108
|
+
}
|
|
6109
|
+
}
|
|
6110
|
+
var run_poll_hook = {
|
|
6111
|
+
POLL_REASON,
|
|
6112
|
+
SWITCH_ENV_KEY: SWITCH_ENV_KEY4,
|
|
6113
|
+
poll_reason,
|
|
6114
|
+
safe_poll_reason
|
|
6115
|
+
};
|
|
6116
|
+
|
|
6963
6117
|
// scripts/hooks/step-zero-notice.ts
|
|
6964
|
-
import
|
|
6118
|
+
import path12 from "node:path";
|
|
6965
6119
|
var STAMP_PREFIX4 = "josh-step-zero-notice-";
|
|
6966
6120
|
var EDIT_TOOLS3 = /* @__PURE__ */ new Set(["Edit", "Write"]);
|
|
6967
6121
|
var PARENT_PREFIX = "..";
|
|
@@ -6976,9 +6130,9 @@ function edited_paths(tool_input) {
|
|
|
6976
6130
|
);
|
|
6977
6131
|
}
|
|
6978
6132
|
function is_runtime_file(file_path, root) {
|
|
6979
|
-
const relative =
|
|
6980
|
-
if (relative.startsWith(PARENT_PREFIX) ||
|
|
6981
|
-
return !test_declared_logic.is_exempt(relative.split(
|
|
6133
|
+
const relative = path12.relative(root, path12.resolve(root, file_path));
|
|
6134
|
+
if (relative.startsWith(PARENT_PREFIX) || path12.isAbsolute(relative)) return false;
|
|
6135
|
+
return !test_declared_logic.is_exempt(relative.split(path12.sep).join("/"));
|
|
6982
6136
|
}
|
|
6983
6137
|
function is_candidate2(raw_payload, root) {
|
|
6984
6138
|
const payload = hook_decision.parse_hook_payload(raw_payload);
|
|
@@ -7031,7 +6185,8 @@ async function mark_phase(outcome) {
|
|
|
7031
6185
|
async function async_reason(raw_payload) {
|
|
7032
6186
|
const watcher = await run_watcher_hook.watcher_hook_reason(raw_payload);
|
|
7033
6187
|
const cut = watcher ?? await run_parent_cut_hook.parent_cut_reason(raw_payload);
|
|
7034
|
-
|
|
6188
|
+
const poll2 = cut ?? await run_poll_hook.safe_poll_reason(raw_payload);
|
|
6189
|
+
return poll2 ?? await issue_watch_hook.watch_reason();
|
|
7035
6190
|
}
|
|
7036
6191
|
async function pretool_outcome_async(raw_payload) {
|
|
7037
6192
|
const base = guard_outcome(raw_payload);
|
|
@@ -7063,38 +6218,26 @@ function foreground_rewrite(outcome, raw_payload, is_lane_child) {
|
|
|
7063
6218
|
rewrite_context(lane_background.FOREGROUND_NOTE, outcome)
|
|
7064
6219
|
);
|
|
7065
6220
|
}
|
|
7066
|
-
function
|
|
7067
|
-
if (
|
|
7068
|
-
|
|
7069
|
-
const input = call === void 0 ? void 0 : piped_verification.pipefail_input(call);
|
|
7070
|
-
const payload = json_value.parse_or_undefined(raw_payload);
|
|
7071
|
-
if (input === void 0 || !json_value.is_record(payload)) return void 0;
|
|
7072
|
-
return { payload: JSON.stringify({ ...payload, tool_input: input }), input };
|
|
7073
|
-
}
|
|
7074
|
-
function pipefail_envelope(outcome, input) {
|
|
7075
|
-
if (input === void 0 || outcome.reason !== void 0) return void 0;
|
|
7076
|
-
return hook_decision.flow_rewrite_envelope(
|
|
7077
|
-
input,
|
|
7078
|
-
rewrite_context(piped_verification.PIPEFAIL_NOTE, outcome)
|
|
7079
|
-
);
|
|
6221
|
+
function rule_envelope(outcome, rewrite3) {
|
|
6222
|
+
if (rewrite3 === void 0 || outcome.reason !== void 0) return void 0;
|
|
6223
|
+
return hook_decision.flow_rewrite_envelope(rewrite3.input, rewrite_context(rewrite3.note, outcome));
|
|
7080
6224
|
}
|
|
7081
|
-
function emit(raw_payload, outcome,
|
|
7082
|
-
const
|
|
7083
|
-
if (
|
|
7084
|
-
else process.stdout.write(`${
|
|
6225
|
+
function emit(raw_payload, outcome, rewrite3) {
|
|
6226
|
+
const envelope = rule_envelope(outcome, rewrite3) ?? foreground_rewrite(outcome, raw_payload);
|
|
6227
|
+
if (envelope === void 0) hook_decision.emit_outcome(outcome);
|
|
6228
|
+
else process.stdout.write(`${envelope}
|
|
7085
6229
|
`);
|
|
7086
6230
|
}
|
|
7087
6231
|
async function respond(raw_payload) {
|
|
7088
|
-
const
|
|
7089
|
-
const judged =
|
|
7090
|
-
emit(judged, await pretool_outcome_async(judged),
|
|
6232
|
+
const rewrite3 = rule_rewrite.rewrite(raw_payload);
|
|
6233
|
+
const judged = rewrite3?.payload ?? raw_payload;
|
|
6234
|
+
emit(judged, await pretool_outcome_async(judged), rewrite3);
|
|
7091
6235
|
}
|
|
7092
6236
|
var pretool_guard = {
|
|
7093
6237
|
combine_outcomes,
|
|
7094
6238
|
emit,
|
|
7095
6239
|
foreground_rewrite,
|
|
7096
6240
|
mark_phase,
|
|
7097
|
-
pipefail_rewrite,
|
|
7098
6241
|
pretool_outcome,
|
|
7099
6242
|
respond
|
|
7100
6243
|
};
|