agent-control-plane 0.4.9 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +72 -9
  2. package/npm/bin/agent-control-plane.js +1 -1
  3. package/package.json +39 -33
  4. package/tools/bin/debug-session.sh +106 -0
  5. package/tools/bin/flow-runtime-doctor-linux.sh +136 -0
  6. package/tools/bin/flow-runtime-doctor.sh +5 -1
  7. package/tools/bin/install-project-systemd.sh +255 -0
  8. package/tools/bin/project-runtimectl.sh +45 -0
  9. package/tools/bin/project-systemd-bootstrap.sh +74 -0
  10. package/tools/bin/uninstall-project-systemd.sh +87 -0
  11. package/tools/dashboard/app.js +198 -5
  12. package/tools/dashboard/issue_queue_state.py +101 -0
  13. package/tools/dashboard/server.py +123 -1
  14. package/tools/dashboard/styles.css +526 -455
  15. package/tools/bin/agent-cleanup-worktree +0 -247
  16. package/tools/bin/agent-github-update-labels +0 -105
  17. package/tools/bin/agent-init-worktree +0 -216
  18. package/tools/bin/agent-project-archive-run +0 -52
  19. package/tools/bin/agent-project-capture-worker +0 -46
  20. package/tools/bin/agent-project-catch-up-issue-pr-links +0 -118
  21. package/tools/bin/agent-project-catch-up-merged-prs +0 -195
  22. package/tools/bin/agent-project-catch-up-scheduled-issue-retries +0 -123
  23. package/tools/bin/agent-project-cleanup-session +0 -513
  24. package/tools/bin/agent-project-detached-launch +0 -127
  25. package/tools/bin/agent-project-heartbeat-loop +0 -1029
  26. package/tools/bin/agent-project-open-issue-worktree +0 -89
  27. package/tools/bin/agent-project-open-pr-worktree +0 -80
  28. package/tools/bin/agent-project-publish-issue-pr +0 -468
  29. package/tools/bin/agent-project-reconcile-issue-session +0 -1409
  30. package/tools/bin/agent-project-reconcile-pr-session +0 -1288
  31. package/tools/bin/agent-project-retry-state +0 -158
  32. package/tools/bin/agent-project-run-claude-session +0 -805
  33. package/tools/bin/agent-project-run-codex-resilient +0 -963
  34. package/tools/bin/agent-project-run-codex-session +0 -435
  35. package/tools/bin/agent-project-run-kilo-session +0 -369
  36. package/tools/bin/agent-project-run-ollama-session +0 -658
  37. package/tools/bin/agent-project-run-openclaw-session +0 -1309
  38. package/tools/bin/agent-project-run-opencode-session +0 -377
  39. package/tools/bin/agent-project-run-pi-session +0 -479
  40. package/tools/bin/agent-project-sync-anchor-repo +0 -139
  41. package/tools/bin/agent-project-sync-source-repo-main +0 -163
  42. package/tools/bin/agent-project-worker-status +0 -188
  43. package/tools/bin/branch-verification-guard.sh +0 -364
  44. package/tools/bin/capture-worker.sh +0 -18
  45. package/tools/bin/cleanup-worktree.sh +0 -52
  46. package/tools/bin/codex-quota +0 -31
  47. package/tools/bin/create-follow-up-issue.sh +0 -114
  48. package/tools/bin/dashboard-launchd-bootstrap.sh +0 -50
  49. package/tools/bin/issue-publish-localization-guard.sh +0 -142
  50. package/tools/bin/issue-publish-scope-guard.sh +0 -242
  51. package/tools/bin/issue-requires-local-workspace-install.sh +0 -31
  52. package/tools/bin/issue-resource-class.sh +0 -12
  53. package/tools/bin/kick-scheduler.sh +0 -75
  54. package/tools/bin/label-follow-up-issues.sh +0 -14
  55. package/tools/bin/new-pr-worktree.sh +0 -50
  56. package/tools/bin/new-worktree.sh +0 -49
  57. package/tools/bin/pr-risk.sh +0 -12
  58. package/tools/bin/prepare-worktree.sh +0 -142
  59. package/tools/bin/provider-cooldown-state.sh +0 -204
  60. package/tools/bin/publish-issue-worker.sh +0 -31
  61. package/tools/bin/reconcile-bootstrap-lib.sh +0 -113
  62. package/tools/bin/reconcile-issue-worker.sh +0 -34
  63. package/tools/bin/reconcile-pr-worker.sh +0 -34
  64. package/tools/bin/record-verification.sh +0 -71
  65. package/tools/bin/render-flow-config.sh +0 -98
  66. package/tools/bin/resident-issue-controller-lib.sh +0 -448
  67. package/tools/bin/retry-state.sh +0 -31
  68. package/tools/bin/reuse-issue-worktree.sh +0 -121
  69. package/tools/bin/run-codex-bypass.sh +0 -3
  70. package/tools/bin/run-codex-safe.sh +0 -3
  71. package/tools/bin/run-codex-task.sh +0 -280
  72. package/tools/bin/serve-dashboard.sh +0 -5
  73. package/tools/bin/start-issue-worker.sh +0 -943
  74. package/tools/bin/start-pr-fix-worker.sh +0 -528
  75. package/tools/bin/start-pr-merge-repair-worker.sh +0 -8
  76. package/tools/bin/start-pr-review-worker.sh +0 -261
  77. package/tools/bin/start-resident-issue-loop.sh +0 -499
  78. package/tools/bin/update-github-labels.sh +0 -14
  79. package/tools/bin/worker-status.sh +0 -19
  80. package/tools/bin/workflow-catalog.sh +0 -77
@@ -1,142 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- usage() {
5
- cat <<'EOF'
6
- Usage:
7
- issue-publish-localization-guard.sh --worktree <path> --base-ref <git-ref>
8
-
9
- Fail fast when an issue branch updates locale resources but still leaves obvious
10
- hardcoded user-facing strings in the touched UI files.
11
- EOF
12
- }
13
-
14
- worktree=""
15
- base_ref=""
16
-
17
- while [[ $# -gt 0 ]]; do
18
- case "$1" in
19
- --worktree) worktree="${2:-}"; shift 2 ;;
20
- --base-ref) base_ref="${2:-}"; shift 2 ;;
21
- --help|-h) usage; exit 0 ;;
22
- *) echo "Unknown argument: $1" >&2; usage >&2; exit 1 ;;
23
- esac
24
- done
25
-
26
- if [[ -z "$worktree" || -z "$base_ref" ]]; then
27
- usage >&2
28
- exit 1
29
- fi
30
-
31
- if [[ ! -d "$worktree" ]]; then
32
- echo "missing worktree: $worktree" >&2
33
- exit 1
34
- fi
35
-
36
- changed_files="$(
37
- git -C "$worktree" diff --name-only --diff-filter=ACMR "${base_ref}...HEAD"
38
- )"
39
-
40
- CHANGED_FILES="${changed_files}" WORKTREE="${worktree}" node <<'EOF'
41
- const fs = require('fs');
42
- const path = require('path');
43
-
44
- const changedFiles = String(process.env.CHANGED_FILES || '')
45
- .split('\n')
46
- .map((file) => file.trim())
47
- .filter(Boolean);
48
- const worktree = String(process.env.WORKTREE || '');
49
-
50
- const localeFiles = changedFiles.filter((file) =>
51
- /^packages\/i18n\/src\/resources\/[^/]+\.json$/.test(file),
52
- );
53
- if (localeFiles.length === 0) {
54
- process.stdout.write('LOCALIZATION_GUARD_STATUS=skipped-no-locale-files\n');
55
- process.exit(0);
56
- }
57
-
58
- const uiFiles = changedFiles.filter((file) =>
59
- /^(?:apps\/web\/|apps\/mobile\/|packages\/ui\/).+\.[cm]?[jt]sx?$/.test(file),
60
- );
61
- if (uiFiles.length === 0) {
62
- process.stdout.write('LOCALIZATION_GUARD_STATUS=skipped-no-ui-files\n');
63
- process.exit(0);
64
- }
65
-
66
- const suspiciousPatterns = [
67
- {
68
- reason: 'validation_literal',
69
- test: (line) =>
70
- /\.(?:min|max|length|email|regex|nonempty)\([^)]*,\s*['"`][^'"`]*[A-Za-z][^'"`]*['"`]/.test(line),
71
- },
72
- {
73
- reason: 'string_prop',
74
- test: (line) =>
75
- /\b(?:title|description|actionLabel|aria-label|placeholder)\s*=\s*['"][^'{"][^'"]*[A-Za-z][^'"]*['"]/.test(
76
- line,
77
- ),
78
- },
79
- {
80
- reason: 'object_label_literal',
81
- test: (line) =>
82
- /\blabel\s*:\s*['"][A-Za-z][^'"]*['"]/.test(line),
83
- },
84
- ];
85
-
86
- const ignoreLine = (line) => {
87
- const trimmed = line.trim();
88
- if (!trimmed) return true;
89
- if (/^\s*\/\//.test(trimmed)) return true;
90
- if (/\bt\(/.test(trimmed)) return true;
91
- if (/\buseSafeTranslation\b|\buseTranslation\b|\bi18nKey=/.test(trimmed)) return true;
92
- if (/^import\s/.test(trimmed)) return true;
93
- return false;
94
- };
95
-
96
- const findings = [];
97
- for (const relativeFile of uiFiles) {
98
- const absoluteFile = path.join(worktree, relativeFile);
99
- if (!fs.existsSync(absoluteFile)) continue;
100
- const lines = fs.readFileSync(absoluteFile, 'utf8').split(/\r?\n/);
101
- lines.forEach((line, index) => {
102
- if (ignoreLine(line)) return;
103
- for (const pattern of suspiciousPatterns) {
104
- if (pattern.test(line)) {
105
- findings.push({
106
- file: relativeFile,
107
- line: index + 1,
108
- reason: pattern.reason,
109
- text: line.trim(),
110
- });
111
- return;
112
- }
113
- }
114
- });
115
- }
116
-
117
- if (findings.length === 0) {
118
- process.stdout.write('LOCALIZATION_GUARD_STATUS=ok\n');
119
- process.stdout.write(`LOCALE_RESOURCE_COUNT=${localeFiles.length}\n`);
120
- process.stdout.write(`UI_FILE_COUNT=${uiFiles.length}\n`);
121
- process.exit(0);
122
- }
123
-
124
- const lines = [
125
- 'Localization guard blocked branch publication.',
126
- '',
127
- 'The branch updates locale resources but still leaves obvious hardcoded user-facing strings in touched UI files.',
128
- '',
129
- 'Why it was blocked:',
130
- ];
131
- for (const finding of findings.slice(0, 20)) {
132
- lines.push(`- ${finding.reason}: ${finding.file}:${finding.line} -> ${finding.text}`);
133
- }
134
- lines.push(
135
- '',
136
- 'Required next step:',
137
- '- move the remaining user-facing literals behind translation keys before publishing this issue branch',
138
- );
139
-
140
- process.stderr.write(`${lines.join('\n')}\n`);
141
- process.exit(44);
142
- EOF
@@ -1,242 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
- # shellcheck source=/dev/null
6
- source "${SCRIPT_DIR}/flow-config-lib.sh"
7
-
8
- usage() {
9
- cat <<'EOF'
10
- Usage:
11
- issue-publish-scope-guard.sh --worktree <path> --base-ref <git-ref> [--issue-id <number>]
12
-
13
- Fail fast when an issue worker branch is too broad to publish safely as a single
14
- PR slice.
15
- EOF
16
- }
17
-
18
- worktree=""
19
- base_ref=""
20
- issue_id=""
21
-
22
- while [[ $# -gt 0 ]]; do
23
- case "$1" in
24
- --worktree) worktree="${2:-}"; shift 2 ;;
25
- --base-ref) base_ref="${2:-}"; shift 2 ;;
26
- --issue-id) issue_id="${2:-}"; shift 2 ;;
27
- --help|-h) usage; exit 0 ;;
28
- *) echo "Unknown argument: $1" >&2; usage >&2; exit 1 ;;
29
- esac
30
- done
31
-
32
- if [[ -z "$worktree" || -z "$base_ref" ]]; then
33
- usage >&2
34
- exit 1
35
- fi
36
-
37
- if [[ ! -d "$worktree" ]]; then
38
- echo "missing worktree: $worktree" >&2
39
- exit 1
40
- fi
41
-
42
- changed_files="$(
43
- git -C "$worktree" diff --name-only --diff-filter=ACMR "${base_ref}...HEAD"
44
- )"
45
-
46
- issue_title=""
47
- issue_body=""
48
- if [[ -n "$issue_id" ]]; then
49
- CONFIG_YAML="$(resolve_flow_config_yaml "${BASH_SOURCE[0]}")"
50
- REPO_SLUG="$(flow_resolve_repo_slug "${CONFIG_YAML}")"
51
- issue_json="$(flow_github_issue_view_json "${REPO_SLUG}" "${issue_id}" 2>/dev/null || true)"
52
- if [[ -n "$issue_json" ]]; then
53
- issue_title="$(jq -r '.title // ""' <<<"$issue_json" 2>/dev/null || true)"
54
- issue_body="$(jq -r '.body // ""' <<<"$issue_json" 2>/dev/null || true)"
55
- fi
56
- fi
57
-
58
- CHANGED_FILES="$changed_files" ISSUE_ID="$issue_id" ISSUE_TITLE="$issue_title" ISSUE_BODY="$issue_body" node <<'EOF'
59
- const files = String(process.env.CHANGED_FILES || '')
60
- .split('\n')
61
- .map((file) => file.trim())
62
- .filter(Boolean);
63
-
64
- const issueId = String(process.env.ISSUE_ID || '').trim();
65
- const issueTitle = String(process.env.ISSUE_TITLE || '').trim();
66
- const issueBody = String(process.env.ISSUE_BODY || '').trim();
67
-
68
- const isDoc = (file) =>
69
- /^openspec\//.test(file) ||
70
- /^docs\//.test(file) ||
71
- /^scripts\/README\.md$/.test(file) ||
72
- /\.md$/i.test(file);
73
-
74
- const isTest = (file) =>
75
- /(?:^|\/)__tests__\//.test(file) ||
76
- /(?:^|\/)e2e\//.test(file) ||
77
- /\.(?:spec|test)\.[cm]?[jt]sx?$/.test(file);
78
-
79
- const isLocaleResource = (file) =>
80
- /^packages\/i18n\/src\/resources\/[^/]+\.json$/.test(file);
81
-
82
- const isProductNonTest = (file) =>
83
- !isDoc(file) &&
84
- !isTest(file) &&
85
- !isLocaleResource(file) &&
86
- (/^apps\//.test(file) || /^packages\//.test(file));
87
-
88
- const isMobileRouteFile = (file) =>
89
- /^apps\/mobile\/app\/.+\.[cm]?[jt]sx?$/.test(file) &&
90
- !isTest(file);
91
-
92
- const mobileSurfaceKey = (file) => {
93
- const relative = file
94
- .replace(/^apps\/mobile\/app\//, '')
95
- .replace(/\.[cm]?[jt]sx?$/, '');
96
- const segments = relative
97
- .split('/')
98
- .filter(Boolean)
99
- .filter((segment) => !/^\(.+\)$/.test(segment));
100
- if (segments.length === 0) return relative;
101
- return segments[0];
102
- };
103
-
104
- const isAuthCriticalProductFile = (file) =>
105
- /^apps\/api\/src\/modules\/auth\//.test(file) ||
106
- file === 'apps/api/src/entities/user.entity.ts' ||
107
- /^apps\/api\/src\/migrations\/.*(?:Email|Phone|Auth|User).*\.[cm]?[jt]s$/.test(file) ||
108
- /^apps\/api\/src\/common\/utils\/(?:phone|tenant|email|auth)[^/]*\.[cm]?[jt]s$/.test(file);
109
-
110
- const isAuthAdjacentProductFile = (file) =>
111
- isAuthCriticalProductFile(file) ||
112
- /^apps\/web\/src\/app\/\(auth\)\//.test(file) ||
113
- /^apps\/api\/src\/modules\/organization\//.test(file);
114
-
115
- const productNonTestFiles = files.filter(isProductNonTest);
116
- const mobileProductFiles = productNonTestFiles.filter((file) => /^apps\/mobile\//.test(file));
117
- const localeResourceFiles = files.filter(isLocaleResource);
118
- const mobileRouteFiles = productNonTestFiles.filter(isMobileRouteFile);
119
- const mobileSurfaceKeys = [...new Set(mobileRouteFiles.map(mobileSurfaceKey))];
120
- const authCriticalTouched = productNonTestFiles.some(isAuthCriticalProductFile);
121
- const authMixedScopeFiles = authCriticalTouched
122
- ? productNonTestFiles.filter((file) => !isAuthAdjacentProductFile(file))
123
- : [];
124
- const openspecChangeFiles = files.filter((file) => /^openspec\/changes\//.test(file));
125
- const workflowRuleFiles = files.filter((file) =>
126
- /^(?:AGENTS\.md|openspec\/AGENT_RULES\.md)$/.test(file),
127
- );
128
- const docsDeclaredScope =
129
- /^(?:docs?|documentation)\b/i.test(issueTitle) ||
130
- /^docs?\(/i.test(issueTitle) ||
131
- /\b(?:docs?|documentation|openspec)[ -]?only\b/i.test(issueTitle) ||
132
- /(?:^|\n)\s*(?:scope|mode|type)\s*:\s*(?:docs?|documentation|openspec)(?:[- ]only)?\b/i.test(issueBody) ||
133
- /(?:^|\n)\s*(?:docs?|documentation|openspec)[ -]?only\b/i.test(issueBody);
134
-
135
- const reasons = [];
136
- if (productNonTestFiles.length > 14) {
137
- reasons.push(`product_non_test_count=${productNonTestFiles.length} exceeds max=14`);
138
- }
139
- if (mobileProductFiles.length >= 8) {
140
- reasons.push(`mobile_product_count=${mobileProductFiles.length} exceeds max=7`);
141
- }
142
- if (localeResourceFiles.length > 8 && productNonTestFiles.length >= 6) {
143
- reasons.push(
144
- `locale_resource_count=${localeResourceFiles.length} with product_non_test_count=${productNonTestFiles.length} exceeds mixed-scope limit`,
145
- );
146
- }
147
- if (mobileRouteFiles.length > 3) {
148
- reasons.push(`mobile_route_file_count=${mobileRouteFiles.length} exceeds max=3`);
149
- }
150
- if (mobileSurfaceKeys.length > 2) {
151
- reasons.push(`mobile_surface_count=${mobileSurfaceKeys.length} exceeds max=2`);
152
- }
153
- if (authMixedScopeFiles.length > 0) {
154
- reasons.push(
155
- `auth_mixed_scope_count=${authMixedScopeFiles.length} requires a dedicated auth slice before publish`,
156
- );
157
- }
158
- if (docsDeclaredScope && productNonTestFiles.length > 0) {
159
- reasons.push(`docs_declared_scope_contains_product_changes=${productNonTestFiles.length}`);
160
- }
161
- if (openspecChangeFiles.length > 0 && productNonTestFiles.length > 0) {
162
- reasons.push(
163
- `product_and_openspec_change_mix=product:${productNonTestFiles.length},openspec_change:${openspecChangeFiles.length}`,
164
- );
165
- }
166
- if (workflowRuleFiles.length > 0 && productNonTestFiles.length > 0) {
167
- reasons.push(
168
- `workflow_rule_files_mixed_with_product_changes=${workflowRuleFiles.length}`,
169
- );
170
- }
171
-
172
- if (reasons.length === 0) {
173
- process.stdout.write('SCOPE_GUARD_STATUS=ok\n');
174
- process.stdout.write(`PRODUCT_NON_TEST_COUNT=${productNonTestFiles.length}\n`);
175
- process.stdout.write(`MOBILE_PRODUCT_COUNT=${mobileProductFiles.length}\n`);
176
- process.stdout.write(`LOCALE_RESOURCE_COUNT=${localeResourceFiles.length}\n`);
177
- process.stdout.write(`MOBILE_ROUTE_FILE_COUNT=${mobileRouteFiles.length}\n`);
178
- process.stdout.write(`MOBILE_SURFACE_COUNT=${mobileSurfaceKeys.length}\n`);
179
- process.stdout.write(`AUTH_MIXED_SCOPE_COUNT=${authMixedScopeFiles.length}\n`);
180
- process.exit(0);
181
- }
182
-
183
- const lines = [
184
- `Scope guard blocked issue${issueId ? ` #${issueId}` : ''} from publishing as a single PR.`,
185
- '',
186
- 'The branch is too broad for the current flow and should be split into a smaller slice before publish.',
187
- '',
188
- 'Why it was blocked:',
189
- ...reasons.map((reason) => `- ${reason}`),
190
- ];
191
-
192
- if (productNonTestFiles.length > 0) {
193
- lines.push('', 'Representative product files:');
194
- for (const file of productNonTestFiles.slice(0, 12)) {
195
- lines.push(`- ${file}`);
196
- }
197
- }
198
-
199
- if (localeResourceFiles.length > 0) {
200
- lines.push('', 'Locale resource files touched:');
201
- for (const file of localeResourceFiles.slice(0, 12)) {
202
- lines.push(`- ${file}`);
203
- }
204
- }
205
-
206
- if (openspecChangeFiles.length > 0) {
207
- lines.push('', 'OpenSpec change files touched:');
208
- for (const file of openspecChangeFiles.slice(0, 12)) {
209
- lines.push(`- ${file}`);
210
- }
211
- }
212
-
213
- if (workflowRuleFiles.length > 0) {
214
- lines.push('', 'Workflow or repo-rule files touched:');
215
- for (const file of workflowRuleFiles.slice(0, 12)) {
216
- lines.push(`- ${file}`);
217
- }
218
- }
219
-
220
- if (mobileRouteFiles.length > 0) {
221
- lines.push('', 'Mobile route files touched:');
222
- for (const file of mobileRouteFiles.slice(0, 12)) {
223
- lines.push(`- ${file}`);
224
- }
225
- }
226
-
227
- if (authMixedScopeFiles.length > 0) {
228
- lines.push('', 'Files that should move to a separate follow-up PR from the auth slice:');
229
- for (const file of authMixedScopeFiles.slice(0, 12)) {
230
- lines.push(`- ${file}`);
231
- }
232
- }
233
-
234
- lines.push(
235
- '',
236
- 'Required next step:',
237
- '- re-run the issue as a narrower slice that stays within one primary product surface, at most two mobile route surfaces, one dedicated auth/security contract change, or one docs/OpenSpec-only branch with no product code',
238
- );
239
-
240
- process.stderr.write(`${lines.join('\n')}\n`);
241
- process.exit(42);
242
- EOF
@@ -1,31 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- ISSUE_BODY="${ISSUE_BODY:-${1:-}}"
5
-
6
- ISSUE_BODY="$ISSUE_BODY" node <<'EOF'
7
- const body = process.env.ISSUE_BODY || '';
8
- const scheduled = /^\s*(?:Agent schedule|Schedule|Cadence)\s*:\s*(?:every\s+)?(\d+)\s*([mhd])\s*$/im.test(body);
9
-
10
- if (!scheduled) {
11
- process.stdout.write('no\n');
12
- process.exit(0);
13
- }
14
-
15
- if (/^\s*(?:Local workspace install|Worktree local install)\s*:\s*yes\s*$/im.test(body)) {
16
- process.stdout.write('yes\n');
17
- process.exit(0);
18
- }
19
-
20
- const installLikePatterns = [
21
- /(^|\n)\s*\d+\.\s*`(?:pnpm|npm|yarn)\s+(?:install|i|ci|add|remove|rm|up|update|rebuild|dlx)\b/im,
22
- /(^|\n)\s*\d+\.\s*`pnpm\s+exec\s+pod\s+install\b/im,
23
- /(^|\n)\s*\d+\.\s*`(?:npx\s+pod-install|expo\s+prebuild|pod\s+install|bundle\s+install)\b/im,
24
- /`(?:pnpm|npm|yarn)\s+(?:install|i|ci|add|remove|rm|up|update|rebuild|dlx)\b/im,
25
- /`pnpm\s+exec\s+pod\s+install\b/im,
26
- /`(?:npx\s+pod-install|expo\s+prebuild|pod\s+install|bundle\s+install)\b/im,
27
- ];
28
-
29
- const needsLocalInstall = installLikePatterns.some((pattern) => pattern.test(body));
30
- process.stdout.write(needsLocalInstall ? 'yes\n' : 'no\n');
31
- EOF
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
- # shellcheck source=/dev/null
6
- source "${SCRIPT_DIR}/flow-shell-lib.sh"
7
-
8
- ISSUE_ID="${1:?usage: issue-resource-class.sh ISSUE_ID}"
9
- FLOW_SKILL_DIR="$(resolve_flow_skill_dir "${BASH_SOURCE[0]}")"
10
- ADAPTER_BIN_DIR="${FLOW_SKILL_DIR}/bin"
11
-
12
- "${ADAPTER_BIN_DIR}/issue-resource-class.sh" "$ISSUE_ID"
@@ -1,75 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
- # shellcheck source=/dev/null
6
- source "${SCRIPT_DIR}/flow-config-lib.sh"
7
-
8
- DELAY_SECONDS="${1:-5}"
9
- WORKSPACE_DIR="$(cd "$(dirname "$0")/.." && pwd)"
10
- FLOW_SKILL_DIR="$(resolve_flow_skill_dir "${BASH_SOURCE[0]}")"
11
- if ! flow_require_explicit_profile_selection "${FLOW_SKILL_DIR}" "kick-scheduler.sh"; then
12
- exit 64
13
- fi
14
- CONFIG_YAML="$(resolve_flow_config_yaml "${BASH_SOURCE[0]}")"
15
- REPO_SLUG="$(flow_resolve_repo_slug "${CONFIG_YAML}")"
16
- STATE_ROOT="$(flow_resolve_state_root "${CONFIG_YAML}")"
17
- BOOTSTRAP_SCRIPT="${ACP_BOOTSTRAP_SCRIPT:-${F_LOSNING_BOOTSTRAP_SCRIPT:-${AGENT_SCHEDULER_BOOTSTRAP_SCRIPT:-$HOME/.agent-runtime/control-plane/workspace/bin/agent-scheduler-launchd.sh}}}"
18
- FLOW_SKILL_DIR="$(resolve_flow_skill_dir "${BASH_SOURCE[0]}")"
19
- FLOW_SAFE_AUTO_SCRIPT="${ACP_FLOW_HEARTBEAT_SCRIPT:-${F_LOSNING_FLOW_HEARTBEAT_SCRIPT:-${FLOW_SKILL_DIR}/tools/bin/heartbeat-safe-auto.sh}}"
20
- STATE_DIR="${ACP_SCHEDULER_KICK_STATE_DIR:-${STATE_ROOT}/kick-scheduler}"
21
- PID_FILE="${STATE_DIR}/pid"
22
-
23
- mkdir -p "${STATE_DIR}"
24
-
25
- active_heartbeat_pid() {
26
- ps -ax -o pid=,command= \
27
- | while read -r pid command; do
28
- [[ -n "${pid:-}" ]] || continue
29
- case "$command" in
30
- *"${BOOTSTRAP_SCRIPT}"*|*"${WORKSPACE_DIR}/bin/heartbeat-safe-auto.sh"*|*"${FLOW_SAFE_AUTO_SCRIPT}"*|*"agent-project-heartbeat-loop --repo-slug ${REPO_SLUG}"*)
31
- printf '%s\n' "$pid"
32
- return 0
33
- ;;
34
- esac
35
- done
36
- }
37
-
38
- if active_pid="$(active_heartbeat_pid)"; [[ -n "$active_pid" ]]; then
39
- printf 'KICK_STATUS=active-heartbeat\n'
40
- printf 'PID=%s\n' "$active_pid"
41
- exit 0
42
- fi
43
-
44
- if [[ -f "${PID_FILE}" ]]; then
45
- existing_pid="$(cat "${PID_FILE}" 2>/dev/null || true)"
46
- if [[ -n "${existing_pid}" ]] && kill -0 "${existing_pid}" 2>/dev/null; then
47
- printf 'KICK_STATUS=already-pending\n'
48
- printf 'PID=%s\n' "${existing_pid}"
49
- exit 0
50
- fi
51
- fi
52
-
53
- export DELAY_SECONDS BOOTSTRAP_SCRIPT FLOW_SAFE_AUTO_SCRIPT PID_FILE REPO_SLUG
54
- nohup bash -lc '
55
- trap '\''rm -f "$PID_FILE"'\'' EXIT
56
- sleep "$DELAY_SECONDS"
57
- active_pid="$(ps -ax -o pid=,command= | while read -r pid command; do
58
- [[ -n "${pid:-}" ]] || continue
59
- case "$command" in
60
- *"$BOOTSTRAP_SCRIPT"*|*"$FLOW_SAFE_AUTO_SCRIPT"*|*"agent-project-heartbeat-loop --repo-slug $REPO_SLUG"*)
61
- printf "%s\n" "$pid"
62
- break
63
- ;;
64
- esac
65
- done)"
66
- if [[ -n "$active_pid" ]]; then
67
- exit 0
68
- fi
69
- "$BOOTSTRAP_SCRIPT" >/dev/null 2>&1 || true
70
- ' >/dev/null 2>&1 &
71
-
72
- bg_pid="$!"
73
- printf '%s\n' "${bg_pid}" >"${PID_FILE}"
74
- printf 'KICK_STATUS=scheduled\n'
75
- printf 'PID=%s\n' "${bg_pid}"
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
- # shellcheck source=/dev/null
6
- source "${SCRIPT_DIR}/flow-config-lib.sh"
7
-
8
- SESSION="${1:?usage: label-follow-up-issues.sh SESSION}"
9
- CONFIG_YAML="$(resolve_flow_config_yaml "${BASH_SOURCE[0]}")"
10
- RUNS_ROOT="$(flow_resolve_runs_root "${CONFIG_YAML}")"
11
- FLOW_SKILL_DIR="$(resolve_flow_skill_dir "${BASH_SOURCE[0]}")"
12
- ADAPTER_BIN_DIR="${FLOW_SKILL_DIR}/bin"
13
-
14
- ACP_RUNS_ROOT="$RUNS_ROOT" F_LOSNING_RUNS_ROOT="$RUNS_ROOT" "${ADAPTER_BIN_DIR}/label-follow-up-issues.sh" "$SESSION"
@@ -1,50 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
- # shellcheck source=/dev/null
6
- source "${SCRIPT_DIR}/flow-config-lib.sh"
7
-
8
- FLOW_SKILL_DIR="$(resolve_flow_skill_dir "${BASH_SOURCE[0]}")"
9
- if ! flow_require_explicit_profile_selection "${FLOW_SKILL_DIR}" "new-pr-worktree.sh"; then
10
- exit 64
11
- fi
12
- FLOW_TOOLS_DIR="${FLOW_SKILL_DIR}/tools/bin"
13
- flow_export_project_env_aliases
14
- CONFIG_YAML="$(resolve_flow_config_yaml "${BASH_SOURCE[0]}")"
15
- AGENT_REPO_ROOT="$(flow_resolve_agent_repo_root "${CONFIG_YAML}")"
16
- AUTOMATION_REPO_ROOT="$(flow_resolve_repo_root "${CONFIG_YAML}")"
17
- WORKTREE_ROOT="$(flow_resolve_worktree_root "${CONFIG_YAML}")"
18
- RETAINED_REPO_ROOT="$(flow_resolve_retained_repo_root "${CONFIG_YAML}")"
19
- VSCODE_WORKSPACE_FILE="$(flow_resolve_vscode_workspace_file "${CONFIG_YAML}")"
20
- PR_WORKTREE_BRANCH_PREFIX="$(flow_resolve_pr_worktree_branch_prefix "${CONFIG_YAML}")"
21
-
22
- PR_NUMBER="${1:?usage: new-pr-worktree.sh PR_NUMBER HEAD_REF}"
23
- HEAD_REF="${2:?usage: new-pr-worktree.sh PR_NUMBER HEAD_REF}"
24
-
25
- ACP_AGENT_REPO_ROOT="$AGENT_REPO_ROOT" \
26
- F_LOSNING_AGENT_REPO_ROOT="$AGENT_REPO_ROOT" \
27
- "${SCRIPT_DIR}/sync-agent-repo.sh" >/dev/null
28
-
29
- export ACP_REPO_ROOT="$AUTOMATION_REPO_ROOT"
30
- export F_LOSNING_REPO_ROOT="$AUTOMATION_REPO_ROOT"
31
-
32
- WORKTREE_OUT="$(
33
- bash "${FLOW_TOOLS_DIR}/agent-project-open-pr-worktree" \
34
- --repo-root "$AGENT_REPO_ROOT" \
35
- --worktree-root "$WORKTREE_ROOT" \
36
- --pr-number "$PR_NUMBER" \
37
- --head-ref "$HEAD_REF" \
38
- --local-branch-prefix "$PR_WORKTREE_BRANCH_PREFIX" \
39
- --prepare-script "${SCRIPT_DIR}/prepare-worktree.sh"
40
- )"
41
-
42
- ACP_AGENT_REPO_ROOT="$AGENT_REPO_ROOT" \
43
- ACP_RETAINED_REPO_ROOT="$RETAINED_REPO_ROOT" \
44
- ACP_VSCODE_WORKSPACE_FILE="$VSCODE_WORKSPACE_FILE" \
45
- F_LOSNING_AGENT_REPO_ROOT="$AGENT_REPO_ROOT" \
46
- F_LOSNING_RETAINED_REPO_ROOT="$RETAINED_REPO_ROOT" \
47
- F_LOSNING_VSCODE_WORKSPACE_FILE="$VSCODE_WORKSPACE_FILE" \
48
- "${SCRIPT_DIR}/sync-vscode-workspace.sh" >/dev/null 2>&1 || true
49
-
50
- printf '%s\n' "$WORKTREE_OUT"
@@ -1,49 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
- # shellcheck source=/dev/null
6
- source "${SCRIPT_DIR}/flow-config-lib.sh"
7
-
8
- FLOW_SKILL_DIR="$(resolve_flow_skill_dir "${BASH_SOURCE[0]}")"
9
- if ! flow_require_explicit_profile_selection "${FLOW_SKILL_DIR}" "new-worktree.sh"; then
10
- exit 64
11
- fi
12
- CONFIG_YAML="$(resolve_flow_config_yaml "${BASH_SOURCE[0]}")"
13
- AGENT_REPO_ROOT="$(flow_resolve_agent_repo_root "${CONFIG_YAML}")"
14
- AUTOMATION_REPO_ROOT="$(flow_resolve_repo_root "${CONFIG_YAML}")"
15
- WORKTREE_ROOT="$(flow_resolve_worktree_root "${CONFIG_YAML}")"
16
- RETAINED_REPO_ROOT="$(flow_resolve_retained_repo_root "${CONFIG_YAML}")"
17
- VSCODE_WORKSPACE_FILE="$(flow_resolve_vscode_workspace_file "${CONFIG_YAML}")"
18
- FLOW_TOOLS_DIR="${FLOW_SKILL_DIR}/tools/bin"
19
- ISSUE_BRANCH_PREFIX="$(flow_resolve_issue_branch_prefix "${CONFIG_YAML}")"
20
-
21
- ISSUE_ID="${1:?usage: new-worktree.sh ISSUE_ID [SLUG]}"
22
- SLUG_INPUT="${2:-task}"
23
-
24
- ACP_AGENT_REPO_ROOT="$AGENT_REPO_ROOT" \
25
- F_LOSNING_AGENT_REPO_ROOT="$AGENT_REPO_ROOT" \
26
- "${SCRIPT_DIR}/sync-agent-repo.sh" >/dev/null
27
-
28
- export ACP_REPO_ROOT="$AUTOMATION_REPO_ROOT"
29
- export F_LOSNING_REPO_ROOT="$AUTOMATION_REPO_ROOT"
30
-
31
- WORKTREE_OUT="$(
32
- bash "${FLOW_TOOLS_DIR}/agent-project-open-issue-worktree" \
33
- --repo-root "$AGENT_REPO_ROOT" \
34
- --worktree-root "$WORKTREE_ROOT" \
35
- --issue-id "$ISSUE_ID" \
36
- --slug "$SLUG_INPUT" \
37
- --branch-prefix "$ISSUE_BRANCH_PREFIX" \
38
- --prepare-script "${SCRIPT_DIR}/prepare-worktree.sh"
39
- )"
40
-
41
- ACP_AGENT_REPO_ROOT="$AGENT_REPO_ROOT" \
42
- ACP_RETAINED_REPO_ROOT="$RETAINED_REPO_ROOT" \
43
- ACP_VSCODE_WORKSPACE_FILE="$VSCODE_WORKSPACE_FILE" \
44
- F_LOSNING_AGENT_REPO_ROOT="$AGENT_REPO_ROOT" \
45
- F_LOSNING_RETAINED_REPO_ROOT="$RETAINED_REPO_ROOT" \
46
- F_LOSNING_VSCODE_WORKSPACE_FILE="$VSCODE_WORKSPACE_FILE" \
47
- "${SCRIPT_DIR}/sync-vscode-workspace.sh" >/dev/null 2>&1 || true
48
-
49
- printf '%s\n' "$WORKTREE_OUT"
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
- # shellcheck source=/dev/null
6
- source "${SCRIPT_DIR}/flow-shell-lib.sh"
7
-
8
- PR_NUMBER="${1:?usage: pr-risk.sh PR_NUMBER}"
9
- FLOW_SKILL_DIR="$(resolve_flow_skill_dir "${BASH_SOURCE[0]}")"
10
- ADAPTER_BIN_DIR="${FLOW_SKILL_DIR}/bin"
11
-
12
- "${ADAPTER_BIN_DIR}/pr-risk.sh" "$PR_NUMBER"