agent-control-plane 0.4.9 → 0.7.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 (87) hide show
  1. package/README.md +109 -13
  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-config-lib.sh +13 -3508
  6. package/tools/bin/flow-execution-lib.sh +243 -0
  7. package/tools/bin/flow-forge-lib.sh +1770 -0
  8. package/tools/bin/flow-profile-lib.sh +335 -0
  9. package/tools/bin/flow-provider-lib.sh +981 -0
  10. package/tools/bin/flow-runtime-doctor-linux.sh +136 -0
  11. package/tools/bin/flow-runtime-doctor.sh +5 -1
  12. package/tools/bin/flow-session-lib.sh +317 -0
  13. package/tools/bin/install-project-systemd.sh +255 -0
  14. package/tools/bin/project-runtimectl.sh +45 -0
  15. package/tools/bin/project-systemd-bootstrap.sh +74 -0
  16. package/tools/bin/uninstall-project-systemd.sh +87 -0
  17. package/tools/dashboard/app.js +238 -8
  18. package/tools/dashboard/issue_queue_state.py +101 -0
  19. package/tools/dashboard/requirements.txt +3 -0
  20. package/tools/dashboard/server.py +250 -30
  21. package/tools/dashboard/styles.css +526 -455
  22. package/tools/bin/agent-cleanup-worktree +0 -247
  23. package/tools/bin/agent-github-update-labels +0 -105
  24. package/tools/bin/agent-init-worktree +0 -216
  25. package/tools/bin/agent-project-archive-run +0 -52
  26. package/tools/bin/agent-project-capture-worker +0 -46
  27. package/tools/bin/agent-project-catch-up-issue-pr-links +0 -118
  28. package/tools/bin/agent-project-catch-up-merged-prs +0 -195
  29. package/tools/bin/agent-project-catch-up-scheduled-issue-retries +0 -123
  30. package/tools/bin/agent-project-cleanup-session +0 -513
  31. package/tools/bin/agent-project-detached-launch +0 -127
  32. package/tools/bin/agent-project-heartbeat-loop +0 -1029
  33. package/tools/bin/agent-project-open-issue-worktree +0 -89
  34. package/tools/bin/agent-project-open-pr-worktree +0 -80
  35. package/tools/bin/agent-project-publish-issue-pr +0 -468
  36. package/tools/bin/agent-project-reconcile-issue-session +0 -1409
  37. package/tools/bin/agent-project-reconcile-pr-session +0 -1288
  38. package/tools/bin/agent-project-retry-state +0 -158
  39. package/tools/bin/agent-project-run-claude-session +0 -805
  40. package/tools/bin/agent-project-run-codex-resilient +0 -963
  41. package/tools/bin/agent-project-run-codex-session +0 -435
  42. package/tools/bin/agent-project-run-kilo-session +0 -369
  43. package/tools/bin/agent-project-run-ollama-session +0 -658
  44. package/tools/bin/agent-project-run-openclaw-session +0 -1309
  45. package/tools/bin/agent-project-run-opencode-session +0 -377
  46. package/tools/bin/agent-project-run-pi-session +0 -479
  47. package/tools/bin/agent-project-sync-anchor-repo +0 -139
  48. package/tools/bin/agent-project-sync-source-repo-main +0 -163
  49. package/tools/bin/agent-project-worker-status +0 -188
  50. package/tools/bin/branch-verification-guard.sh +0 -364
  51. package/tools/bin/capture-worker.sh +0 -18
  52. package/tools/bin/cleanup-worktree.sh +0 -52
  53. package/tools/bin/codex-quota +0 -31
  54. package/tools/bin/create-follow-up-issue.sh +0 -114
  55. package/tools/bin/dashboard-launchd-bootstrap.sh +0 -50
  56. package/tools/bin/issue-publish-localization-guard.sh +0 -142
  57. package/tools/bin/issue-publish-scope-guard.sh +0 -242
  58. package/tools/bin/issue-requires-local-workspace-install.sh +0 -31
  59. package/tools/bin/issue-resource-class.sh +0 -12
  60. package/tools/bin/kick-scheduler.sh +0 -75
  61. package/tools/bin/label-follow-up-issues.sh +0 -14
  62. package/tools/bin/new-pr-worktree.sh +0 -50
  63. package/tools/bin/new-worktree.sh +0 -49
  64. package/tools/bin/pr-risk.sh +0 -12
  65. package/tools/bin/prepare-worktree.sh +0 -142
  66. package/tools/bin/provider-cooldown-state.sh +0 -204
  67. package/tools/bin/publish-issue-worker.sh +0 -31
  68. package/tools/bin/reconcile-bootstrap-lib.sh +0 -113
  69. package/tools/bin/reconcile-issue-worker.sh +0 -34
  70. package/tools/bin/reconcile-pr-worker.sh +0 -34
  71. package/tools/bin/record-verification.sh +0 -71
  72. package/tools/bin/render-flow-config.sh +0 -98
  73. package/tools/bin/resident-issue-controller-lib.sh +0 -448
  74. package/tools/bin/retry-state.sh +0 -31
  75. package/tools/bin/reuse-issue-worktree.sh +0 -121
  76. package/tools/bin/run-codex-bypass.sh +0 -3
  77. package/tools/bin/run-codex-safe.sh +0 -3
  78. package/tools/bin/run-codex-task.sh +0 -280
  79. package/tools/bin/serve-dashboard.sh +0 -5
  80. package/tools/bin/start-issue-worker.sh +0 -943
  81. package/tools/bin/start-pr-fix-worker.sh +0 -528
  82. package/tools/bin/start-pr-merge-repair-worker.sh +0 -8
  83. package/tools/bin/start-pr-review-worker.sh +0 -261
  84. package/tools/bin/start-resident-issue-loop.sh +0 -499
  85. package/tools/bin/update-github-labels.sh +0 -14
  86. package/tools/bin/worker-status.sh +0 -19
  87. 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"