@moretea-labs/forge 1.7.0 → 1.7.1
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/AGENTS.md +2 -0
- package/CHANGELOG.md +13 -0
- package/CLAUDE.md +2 -0
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/agents/openai.yaml +1 -1
- package/assets/partials-agents/02-operating-mode.partial.md +2 -0
- package/assets/plugin-registry.v1.json +3 -3
- package/assets/skill-version.json +2 -2
- package/assets/templates/helpers/check-architecture-sync.sh +17 -0
- package/assets/templates/helpers/inspect-project-state.ts +8 -6
- package/assets/templates/helpers/migrate-workflow-docs.ts +9 -7
- package/assets/templates/helpers/workflow-contract.ts +5 -1
- package/docs/architecture/CURRENT.md +12 -4
- package/docs/forge-plugin-management.md +1 -1
- package/docs/operations/controller-performance-and-502.md +19 -0
- package/docs/operations/homebrew.md +2 -2
- package/package.json +5 -2
- package/scripts/architecture-event.ts +2 -820
- package/scripts/architecture-queue.sh +2 -645
- package/scripts/archive-architecture-request.sh +2 -242
- package/scripts/archive-workflow.sh +1 -291
- package/scripts/benchmark-work-efficiency.ts +0 -0
- package/scripts/capability-config.ts +2 -392
- package/scripts/capability-resolver.ts +2 -503
- package/scripts/capture-plan.sh +1 -332
- package/scripts/check-agent-tooling.sh +2 -1531
- package/scripts/check-architecture-sync.sh +2 -302
- package/scripts/check-brain-manifest.sh +2 -253
- package/scripts/check-context-files.sh +2 -47
- package/scripts/check-deploy-sql-order.sh +2 -115
- package/scripts/check-runtime-architecture.mjs +243 -16
- package/scripts/check-skill-version.ts +3 -191
- package/scripts/check-source-duplication.mjs +61 -0
- package/scripts/check-stable-baseline.ts +0 -0
- package/scripts/check-task-sync.sh +2 -63
- package/scripts/check-task-workflow.sh +2 -1000
- package/scripts/codex-handoff-resume.sh +2 -267
- package/scripts/context-contract-sync.sh +2 -514
- package/scripts/contract-run.ts +2 -463
- package/scripts/contract-worktree.sh +1 -702
- package/scripts/ensure-task-workflow.sh +1 -1192
- package/scripts/inspect-project-state.ts +4 -279
- package/scripts/lib/project-init-lib.sh +7 -2
- package/scripts/lib/run-forge-helper.sh +19 -0
- package/scripts/lib/run-forge-helper.ts +26 -0
- package/scripts/migrate-project-template.sh +1 -33
- package/scripts/migrate-workflow-docs.ts +4 -412
- package/scripts/new-plan.sh +1 -180
- package/scripts/new-spec.sh +1 -47
- package/scripts/new-sprint.sh +1 -46
- package/scripts/plan-to-todo.sh +1 -771
- package/scripts/prepare-codex-handoff.sh +2 -201
- package/scripts/prepare-handoff.sh +1 -78
- package/scripts/refresh-current-status.sh +2 -467
- package/scripts/run-governed-gate.ts +3 -0
- package/scripts/select-agent-context-blocks.sh +2 -64
- package/scripts/ship-worktrees.sh +1 -531
- package/scripts/sprint-backlog.sh +1 -834
- package/scripts/stage-runtime-release.ts +2 -1
- package/scripts/summarize-failures.sh +2 -123
- package/scripts/switch-plan.sh +1 -150
- package/scripts/sync-brain-docs.sh +2 -379
- package/scripts/sync-generated-authority.mjs +175 -0
- package/scripts/verify-contract.sh +2 -593
- package/scripts/verify-sprint.sh +1 -500
- package/scripts/workflow-contract.ts +4 -201
- package/scripts/workstream-sync.sh +2 -261
- package/src/cli/agent-jobs/executor-health.ts +1 -1
- package/src/cli/commands/plugin.ts +12 -3
- package/src/cli/controller/check-runner.ts +7 -2
- package/src/cli/controller/context-pack.ts +46 -21
- package/src/cli/github/contracts.ts +16 -0
- package/src/cli/github/github.ts +2 -16
- package/src/cli/github/session.ts +2 -1
- package/src/cli/local-bridge/facade-api.ts +37 -47
- package/src/cli/local-bridge/server.ts +2 -2
- package/src/cli/mcp/legacy-tool-service.ts +10 -33
- package/src/cli/mcp/post-finalize-work-attribution.ts +150 -0
- package/src/cli/mcp/repository-tools.ts +85 -89
- package/src/cli/mcp/server.ts +57 -13
- package/src/cli/mcp/tool-contract.ts +14 -0
- package/src/cli/mcp/toolset.ts +2 -2
- package/src/cli/mcp/transports/http.ts +23 -0
- package/src/cli/repositories/command-classifier.ts +2 -2
- package/src/cli/repositories/command-executor.ts +24 -6
- package/src/cli/repositories/repository-snapshot.ts +5 -2
- package/src/cli/repositories/structured-git.ts +57 -3
- package/src/cli/repository/inspector.ts +11 -3
- package/src/runtime/context/generic-lsp-provider.ts +1 -1
- package/src/runtime/context/semantic-navigation-contract.ts +61 -0
- package/src/runtime/context/semantic-navigation.ts +9 -61
- package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +18 -25
- package/src/runtime/control-plane/execution/repository-work-attribution.ts +106 -0
- package/src/runtime/control-plane/execution/retained-work-resume.ts +203 -0
- package/src/runtime/control-plane/execution/work-completion-authority.ts +58 -0
- package/src/runtime/control-plane/execution/work-evidence-policy.ts +200 -0
- package/src/runtime/control-plane/execution/work-execution-support.ts +386 -0
- package/src/runtime/control-plane/execution/work-finalization-service.ts +1913 -0
- package/src/runtime/control-plane/execution/work-handle-authority.ts +96 -0
- package/src/runtime/control-plane/execution/work-handle-store.ts +1 -1
- package/src/runtime/control-plane/execution/work-operation-service.ts +468 -0
- package/src/runtime/control-plane/execution/work-path-scope.ts +37 -0
- package/src/runtime/control-plane/execution/work-preparation-service.ts +479 -0
- package/src/runtime/control-plane/execution/work-process-evidence.ts +129 -0
- package/src/runtime/control-plane/execution/work-task-receipt.ts +4 -43
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +13 -3
- package/src/runtime/control-plane/execution/work-verification-context.ts +56 -0
- package/src/runtime/control-plane/execution/work-verification-service.ts +388 -0
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +5 -1
- package/src/runtime/control-plane/facade/controller-round-relay.ts +164 -37
- package/src/runtime/control-plane/facade/controller-session-store.ts +183 -24
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +15 -1
- package/src/runtime/control-plane/facade/goal-workloop.ts +329 -148
- package/src/runtime/control-plane/facade/index.ts +2 -0
- package/src/runtime/control-plane/facade/plan-contract-store.ts +90 -22
- package/src/runtime/control-plane/facade/repository-work-admission.ts +147 -0
- package/src/runtime/control-plane/facade/requirement-authority.ts +83 -0
- package/src/runtime/control-plane/facade/types.ts +68 -5
- package/src/runtime/control-plane/facade/work-contract-store.ts +3 -209
- package/src/runtime/control-plane/facade/work-state-machine.ts +250 -0
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +14 -7
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +5 -1
- package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +13 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +15 -6
- package/src/runtime/control-plane/launcher/launch-reservation-store.ts +54 -5
- package/src/runtime/control-plane/launcher/thin-launcher.ts +56 -7
- package/src/runtime/control-plane/persistence/requirement-store.ts +0 -12
- package/src/runtime/control-plane/repo-actor/registry.ts +4 -2
- package/src/runtime/control-plane/routing/route-policy.ts +18 -6
- package/src/runtime/control-plane/routing/workspace-admission.ts +70 -0
- package/src/runtime/evidence/process-check-execution.ts +18 -0
- package/src/runtime/execution/jobs/child-reference.ts +6 -2
- package/src/runtime/execution/process-runtime/check-result.ts +53 -18
- package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +7 -1
- package/src/runtime/execution/process-runtime/command-facade.ts +39 -17
- package/src/runtime/execution/process-runtime/lightweight-managed.ts +20 -3
- package/src/runtime/execution/process-runtime/persisted-check.ts +4 -1
- package/src/runtime/execution/process-runtime/runtime.ts +10 -0
- package/src/runtime/execution/process-runtime/types.ts +2 -12
- package/src/runtime/execution/work-activity.ts +21 -0
- package/src/runtime/execution/workers/executor.ts +18 -13
- package/src/runtime/gateway/mcp/execution-tools.ts +35 -2930
- package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +61 -0
- package/src/runtime/gateway/mcp/router.ts +2 -2
- package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +21 -2
- package/src/runtime/gateway/mcp/runtime-tools.ts +805 -1009
- package/src/runtime/plugins/app-store-connect-adapter.ts +93 -28
- package/src/runtime/plugins/browser-adapter.ts +256 -1083
- package/src/runtime/plugins/browser-handoff-host.ts +2 -25
- package/src/runtime/plugins/browser-handoff.ts +18 -3
- package/src/runtime/plugins/browser-macos-bridge.ts +121 -16
- package/src/runtime/plugins/browser-manifest-surface.ts +603 -0
- package/src/runtime/plugins/browser-native-session-service.ts +222 -0
- package/src/runtime/plugins/browser-runtime-contract.ts +2 -0
- package/src/runtime/plugins/browser-runtime.ts +10 -0
- package/src/runtime/plugins/browser-session-store.ts +121 -0
- package/src/runtime/plugins/browser-session-types.ts +98 -0
- package/src/runtime/plugins/desktop-operator-registration.ts +4 -4
- package/src/runtime/plugins/external-adapter.ts +92 -58
- package/src/runtime/plugins/macos-capability-broker.ts +0 -8
- package/src/runtime/plugins/store.ts +66 -9
- package/src/runtime/plugins/types.ts +3 -1
- package/src/runtime/recovery/maintenance-executor.ts +61 -25
- package/src/runtime/root/package-connector-service.ts +46 -4
- package/src/runtime/root/package-runtime-release.ts +1 -1
- package/src/runtime/root/package-runtime-service.ts +33 -2
- package/src/runtime/root/release-manifest.ts +137 -16
- package/src/runtime/root/release-materialize.ts +109 -35
- package/src/runtime/root/types.ts +10 -0
- package/src/runtime/standalone-recovery/core.ts +425 -194
- package/src/runtime/standalone-recovery/entry.ts +1 -1
- package/src/runtime/standalone-recovery/installer.ts +1 -1
- package/src/runtime/workflow/schedules/engine.ts +113 -87
- package/src/runtime/workflow/schedules/settlement.ts +26 -23
- package/src/runtime/workflow/schedules/store.ts +79 -10
|
@@ -1,280 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import {
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
export * from "../assets/templates/helpers/inspect-project-state";
|
|
3
|
+
import { runTrackedForgeHelper } from "./lib/run-forge-helper";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
type InspectionResult = {
|
|
8
|
-
repo: string;
|
|
9
|
-
mode: Mode;
|
|
10
|
-
legacy_contract_version: string;
|
|
11
|
-
drift_signals: string[];
|
|
12
|
-
required_decisions: string[];
|
|
13
|
-
safe_defaults: string[];
|
|
14
|
-
detected_paths: string[];
|
|
15
|
-
upgrade_plan: UpgradePlanItem[];
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
type UpgradePlanItem = {
|
|
19
|
-
id: string;
|
|
20
|
-
signal: string;
|
|
21
|
-
action: string;
|
|
22
|
-
risk: string;
|
|
23
|
-
ownership: string;
|
|
24
|
-
paths: string[];
|
|
25
|
-
target_paths?: string[];
|
|
26
|
-
summary: string;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
function parseArgs(argv: string[]) {
|
|
30
|
-
let repo = process.cwd();
|
|
31
|
-
let format: "json" | "text" = "json";
|
|
32
|
-
|
|
33
|
-
for (let i = 0; i < argv.length; i += 1) {
|
|
34
|
-
const arg = argv[i];
|
|
35
|
-
if (arg === "--repo") {
|
|
36
|
-
repo = argv[i + 1] ? resolve(argv[i + 1]) : repo;
|
|
37
|
-
i += 1;
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
if (arg === "--format") {
|
|
41
|
-
format = argv[i + 1] === "text" ? "text" : "json";
|
|
42
|
-
i += 1;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return { repo, format };
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function fileHasContent(path: string, pattern: RegExp): boolean {
|
|
50
|
-
if (!existsSync(path)) return false;
|
|
51
|
-
return pattern.test(readFileSync(path, "utf-8"));
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function jsonPathExists(path: string, keys: string[]): boolean {
|
|
55
|
-
if (!existsSync(path)) return false;
|
|
56
|
-
try {
|
|
57
|
-
let value: unknown = JSON.parse(readFileSync(path, "utf-8"));
|
|
58
|
-
for (const key of keys) {
|
|
59
|
-
if (!value || typeof value !== "object" || !(key in value)) return false;
|
|
60
|
-
value = (value as Record<string, unknown>)[key];
|
|
61
|
-
}
|
|
62
|
-
return true;
|
|
63
|
-
} catch {
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function hasAnyPath(repo: string, relPaths: string[]): boolean {
|
|
69
|
-
return relPaths.some((relPath) => existsSync(join(repo, relPath)));
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function hasCustomClaudeHooks(repo: string): boolean {
|
|
73
|
-
const hooksDir = join(repo, ".claude", "hooks");
|
|
74
|
-
if (!existsSync(hooksDir)) return false;
|
|
75
|
-
try {
|
|
76
|
-
return readdirSync(hooksDir).some((entry) => /^custom-.*\.sh$/.test(entry));
|
|
77
|
-
} catch {
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function detectMode(repo: string): Mode {
|
|
83
|
-
const hasTasks = existsSync(join(repo, "tasks"));
|
|
84
|
-
const hasPlan = existsSync(join(repo, "plans"));
|
|
85
|
-
const hasLegacyDocs =
|
|
86
|
-
existsSync(join(repo, "docs", "plan.md")) || existsSync(join(repo, "docs", "TODO.md"));
|
|
87
|
-
const hasLegacySkillFactory =
|
|
88
|
-
existsSync(join(repo, ".claude", "skill-factory")) ||
|
|
89
|
-
existsSync(join(repo, "scripts", "skill-factory-check.sh")) ||
|
|
90
|
-
existsSync(join(repo, "scripts", "skill-factory-create.sh")) ||
|
|
91
|
-
existsSync(join(repo, ".ai", "hooks", "memory-intake.sh")) ||
|
|
92
|
-
existsSync(join(repo, ".ai", "hooks", "skill-factory-session-end.sh"));
|
|
93
|
-
|
|
94
|
-
if (hasTasks && hasPlan) return "audit";
|
|
95
|
-
if (hasLegacyDocs || hasLegacySkillFactory) return "migrate";
|
|
96
|
-
if (!hasTasks && !hasPlan && !hasLegacyDocs) return "initialize";
|
|
97
|
-
return "repair";
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function inspectRepo(repo: string): InspectionResult {
|
|
101
|
-
const contract = loadWorkflowContract(resolveWorkflowContractForRepo(repo));
|
|
102
|
-
const latestContract = loadWorkflowContract();
|
|
103
|
-
const upgradeActions = latestContract.migrations.upgrade?.actions ?? contract.migrations.upgrade?.actions ?? [];
|
|
104
|
-
const detectedPathSet = new Set(
|
|
105
|
-
[...new Set([...contract.migrations.legacyPaths, ...latestContract.migrations.legacyPaths])]
|
|
106
|
-
.map((relPath) => relPath)
|
|
107
|
-
.filter((relPath) => existsSync(join(repo, relPath)))
|
|
108
|
-
);
|
|
109
|
-
const driftSignals: string[] = [];
|
|
110
|
-
const requiredDecisions: string[] = [];
|
|
111
|
-
const safeDefaults = [
|
|
112
|
-
"Preserve repo-local tasks-first workflow",
|
|
113
|
-
"Archive uncertain legacy content instead of overwriting it",
|
|
114
|
-
"Delete only manifest-owned known_generated legacy files",
|
|
115
|
-
"Distill repeated corrections into tasks/lessons.md and hidden contracts into docs/researches/",
|
|
116
|
-
];
|
|
117
|
-
|
|
118
|
-
const runtimeManifest = join(repo, contract.artifacts.runtimeManifest);
|
|
119
|
-
const todoFile = join(repo, contract.documents.deferredGoalLedger ?? contract.documents.taskChecklist ?? "tasks/todos.md");
|
|
120
|
-
const legacySingularTodoFile = join(repo, "tasks", "todo.md");
|
|
121
|
-
const legacyTaskSprintDir = join(repo, "tasks", "sprints");
|
|
122
|
-
const policyFile = join(repo, ".ai", "harness", "policy.json");
|
|
123
|
-
const generatedClaudeHookPaths = [
|
|
124
|
-
".claude/hooks/run-hook.sh",
|
|
125
|
-
".claude/hooks/finalize-handoff.sh",
|
|
126
|
-
".claude/hooks/session-start-context.sh",
|
|
127
|
-
".claude/hooks/hook-input.sh",
|
|
128
|
-
".claude/hooks/lib/workflow-state.sh",
|
|
129
|
-
".claude/hooks/lib/session-state.sh",
|
|
130
|
-
];
|
|
131
|
-
const ignoredReferenceOrSecretPaths = [
|
|
132
|
-
"_ref",
|
|
133
|
-
"_ops",
|
|
134
|
-
];
|
|
135
|
-
|
|
136
|
-
if (!existsSync(runtimeManifest)) {
|
|
137
|
-
driftSignals.push("missing-runtime-contract-manifest");
|
|
138
|
-
}
|
|
139
|
-
if (existsSync(policyFile) && !jsonPathExists(policyFile, ["upgrade", "strategy_version"])) {
|
|
140
|
-
driftSignals.push("policy-missing-upgrade-strategy");
|
|
141
|
-
}
|
|
142
|
-
if (existsSync(join(repo, "docs", "plan.md"))) {
|
|
143
|
-
driftSignals.push("legacy-docs-plan");
|
|
144
|
-
}
|
|
145
|
-
if (existsSync(join(repo, "docs", "TODO.md"))) {
|
|
146
|
-
driftSignals.push("legacy-docs-todo");
|
|
147
|
-
}
|
|
148
|
-
if (existsSync(legacySingularTodoFile) && legacySingularTodoFile !== todoFile) {
|
|
149
|
-
driftSignals.push("legacy-singular-todo-file");
|
|
150
|
-
}
|
|
151
|
-
if (existsSync(legacyTaskSprintDir)) {
|
|
152
|
-
driftSignals.push("legacy-task-sprint-prds");
|
|
153
|
-
}
|
|
154
|
-
if (
|
|
155
|
-
existsSync(join(repo, ".claude", "skill-factory")) ||
|
|
156
|
-
existsSync(join(repo, "scripts", "skill-factory-check.sh")) ||
|
|
157
|
-
existsSync(join(repo, "scripts", "skill-factory-create.sh")) ||
|
|
158
|
-
existsSync(join(repo, ".ai", "hooks", "memory-intake.sh")) ||
|
|
159
|
-
existsSync(join(repo, ".ai", "hooks", "skill-factory-session-end.sh"))
|
|
160
|
-
) {
|
|
161
|
-
driftSignals.push("legacy-skill-factory-surface");
|
|
162
|
-
}
|
|
163
|
-
if (existsSync(join(repo, "docs", "PROGRESS.md"))) {
|
|
164
|
-
driftSignals.push("legacy-docs-progress");
|
|
165
|
-
}
|
|
166
|
-
if (
|
|
167
|
-
existsSync(todoFile) &&
|
|
168
|
-
(
|
|
169
|
-
!fileHasContent(todoFile, /^# Deferred Goal Ledger\s*$/m) ||
|
|
170
|
-
!fileHasContent(todoFile, /^\> \*\*Status\*\*:\s*Backlog\s*$/m)
|
|
171
|
-
)
|
|
172
|
-
) {
|
|
173
|
-
driftSignals.push("legacy-task-checklist-format");
|
|
174
|
-
}
|
|
175
|
-
if (hasAnyPath(repo, generatedClaudeHookPaths)) {
|
|
176
|
-
driftSignals.push("stale-generated-claude-hook-shims");
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (driftSignals.includes("missing-runtime-contract-manifest")) {
|
|
180
|
-
requiredDecisions.push("Install runtime workflow contract manifest");
|
|
181
|
-
}
|
|
182
|
-
if (driftSignals.includes("policy-missing-upgrade-strategy")) {
|
|
183
|
-
requiredDecisions.push("Merge versioned upgrade strategy into harness policy");
|
|
184
|
-
}
|
|
185
|
-
if (driftSignals.includes("legacy-docs-plan") || driftSignals.includes("legacy-docs-todo")) {
|
|
186
|
-
requiredDecisions.push("Run legacy document migration before template refresh");
|
|
187
|
-
}
|
|
188
|
-
if (driftSignals.includes("legacy-singular-todo-file")) {
|
|
189
|
-
requiredDecisions.push("Migrate legacy tasks/todo.md into tasks/todos.md");
|
|
190
|
-
}
|
|
191
|
-
if (driftSignals.includes("legacy-task-sprint-prds")) {
|
|
192
|
-
requiredDecisions.push("Move legacy tasks/sprints/*.sprint.md into plans/sprints/*.sprint.md");
|
|
193
|
-
}
|
|
194
|
-
if (driftSignals.includes("legacy-docs-progress")) {
|
|
195
|
-
requiredDecisions.push("Archive legacy docs/PROGRESS.md into research report or changelog surfaces");
|
|
196
|
-
}
|
|
197
|
-
if (driftSignals.includes("legacy-skill-factory-surface")) {
|
|
198
|
-
requiredDecisions.push("Remove repo-local Skill Factory and auto-memory surfaces");
|
|
199
|
-
}
|
|
200
|
-
if (driftSignals.includes("stale-generated-claude-hook-shims")) {
|
|
201
|
-
requiredDecisions.push("Remove manifest-owned generated .claude/hooks shims and keep .ai/hooks as source of truth");
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const upgradeSignals = new Set(driftSignals);
|
|
205
|
-
if (hasCustomClaudeHooks(repo)) {
|
|
206
|
-
upgradeSignals.add("custom-claude-hooks");
|
|
207
|
-
}
|
|
208
|
-
if (hasAnyPath(repo, ignoredReferenceOrSecretPaths)) {
|
|
209
|
-
upgradeSignals.add("ignored-reference-or-secret-surfaces");
|
|
210
|
-
}
|
|
211
|
-
const upgradePlan = upgradeActions
|
|
212
|
-
.filter((action) => upgradeSignals.has(action.signal))
|
|
213
|
-
.map((action) => {
|
|
214
|
-
for (const relPath of action.paths) {
|
|
215
|
-
if (!relPath.includes("*") && existsSync(join(repo, relPath))) {
|
|
216
|
-
detectedPathSet.add(relPath);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
return {
|
|
220
|
-
id: action.id,
|
|
221
|
-
signal: action.signal,
|
|
222
|
-
action: action.action,
|
|
223
|
-
risk: action.risk,
|
|
224
|
-
ownership: action.ownership,
|
|
225
|
-
paths: action.paths,
|
|
226
|
-
target_paths: action.targetPaths,
|
|
227
|
-
summary: action.summary,
|
|
228
|
-
};
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
let legacyContractVersion = "current-v1";
|
|
232
|
-
if (driftSignals.includes("legacy-docs-plan") || driftSignals.includes("legacy-docs-todo")) {
|
|
233
|
-
legacyContractVersion = "pre-tasks-first";
|
|
234
|
-
} else if (driftSignals.includes("missing-runtime-contract-manifest")) {
|
|
235
|
-
legacyContractVersion = "tasks-first-without-contract-manifest";
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
return {
|
|
239
|
-
repo,
|
|
240
|
-
mode: detectMode(repo),
|
|
241
|
-
legacy_contract_version: legacyContractVersion,
|
|
242
|
-
drift_signals: driftSignals,
|
|
243
|
-
required_decisions: requiredDecisions,
|
|
244
|
-
safe_defaults: safeDefaults,
|
|
245
|
-
detected_paths: [...detectedPathSet].sort(),
|
|
246
|
-
upgrade_plan: upgradePlan,
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
function renderText(result: InspectionResult): string {
|
|
251
|
-
const lines = [
|
|
252
|
-
`repo: ${result.repo}`,
|
|
253
|
-
`mode: ${result.mode}`,
|
|
254
|
-
`legacy_contract_version: ${result.legacy_contract_version}`,
|
|
255
|
-
`drift_signals: ${result.drift_signals.join(", ") || "(none)"}`,
|
|
256
|
-
`required_decisions: ${result.required_decisions.join(" | ") || "(none)"}`,
|
|
257
|
-
`safe_defaults: ${result.safe_defaults.join(" | ")}`,
|
|
258
|
-
`upgrade_plan:`,
|
|
259
|
-
];
|
|
260
|
-
if (result.upgrade_plan.length === 0) {
|
|
261
|
-
lines.push("- (none)");
|
|
262
|
-
} else {
|
|
263
|
-
for (const item of result.upgrade_plan) {
|
|
264
|
-
const target = item.target_paths?.length ? ` -> ${item.target_paths.join(", ")}` : "";
|
|
265
|
-
lines.push(
|
|
266
|
-
`- ${item.action} ${item.id} [${item.risk}, ${item.ownership}]: ${item.paths.join(", ")}${target}`
|
|
267
|
-
);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
return lines.join("\n");
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
const { repo, format } = parseArgs(process.argv.slice(2));
|
|
274
|
-
const result = inspectRepo(repo);
|
|
275
|
-
|
|
276
|
-
if (format === "text") {
|
|
277
|
-
console.log(renderText(result));
|
|
278
|
-
} else {
|
|
279
|
-
console.log(JSON.stringify(result, null, 2));
|
|
280
|
-
}
|
|
5
|
+
if (import.meta.main) runTrackedForgeHelper("inspect-project-state.ts");
|
|
@@ -1055,7 +1055,9 @@ pi_install_helpers() {
|
|
|
1055
1055
|
fi
|
|
1056
1056
|
|
|
1057
1057
|
if [[ "$mode" != "apply" ]]; then
|
|
1058
|
-
if [[ "$source_repo_target" -eq 1
|
|
1058
|
+
if [[ "$source_repo_target" -eq 1 ]]; then
|
|
1059
|
+
echo "[dry-run] preserve tracked source helper compatibility surfaces in $scripts_dir"
|
|
1060
|
+
elif [[ "$(pi_repo_pins_helper_source "$target_dir" && printf yes || true)" == "yes" ]]; then
|
|
1059
1061
|
echo "[dry-run] install source helpers into $scripts_dir"
|
|
1060
1062
|
else
|
|
1061
1063
|
echo "[dry-run] install helper compatibility wrappers in $scripts_dir; package runtime dispatches through forge run"
|
|
@@ -1083,7 +1085,10 @@ pi_install_helpers() {
|
|
|
1083
1085
|
fi
|
|
1084
1086
|
fi
|
|
1085
1087
|
if [[ "$source_repo_target" -eq 1 ]]; then
|
|
1086
|
-
|
|
1088
|
+
# Self-host source helpers are tracked compatibility surfaces. Their
|
|
1089
|
+
# implementation authority lives in assets/templates/helpers; never
|
|
1090
|
+
# copy the full runtime implementation back into scripts/.
|
|
1091
|
+
continue
|
|
1087
1092
|
elif pi_repo_pins_helper_source "$target_dir"; then
|
|
1088
1093
|
cp "$helpers_dir/$helper_name" "$runtime_dir/$helper_name"
|
|
1089
1094
|
pi_normalize_installed_helper "$runtime_dir/$helper_name"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
|
+
SOURCE_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
6
|
+
HELPER_NAME="${1:?helper filename is required}"
|
|
7
|
+
shift
|
|
8
|
+
HELPER_ID="${HELPER_NAME%.*}"
|
|
9
|
+
|
|
10
|
+
if command -v bun >/dev/null 2>&1 && [[ -f "$SOURCE_ROOT/src/cli/index.ts" && -f "$SOURCE_ROOT/assets/templates/helpers/$HELPER_NAME" ]]; then
|
|
11
|
+
exec bun "$SOURCE_ROOT/src/cli/index.ts" run "$HELPER_ID" "$@"
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
if command -v forge >/dev/null 2>&1; then
|
|
15
|
+
exec forge run "$HELPER_ID" "$@"
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
echo "Missing Forge runtime for helper $HELPER_ID" >&2
|
|
19
|
+
exit 1
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { dirname, join, resolve } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
export function runTrackedForgeHelper(helperName: string, args = process.argv.slice(2)): never {
|
|
8
|
+
const helperId = helperName.replace(/\.[^.]+$/, "");
|
|
9
|
+
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const sourceRoot = resolve(scriptDir, "..", "..");
|
|
11
|
+
const sourceCli = join(sourceRoot, "src", "cli", "index.ts");
|
|
12
|
+
const canonicalHelper = join(sourceRoot, "assets", "templates", "helpers", helperName);
|
|
13
|
+
const command = existsSync(sourceCli) && existsSync(canonicalHelper)
|
|
14
|
+
? ["bun", sourceCli, "run", helperId]
|
|
15
|
+
: ["forge", "run", helperId];
|
|
16
|
+
const result = spawnSync(command[0], [...command.slice(1), ...args], {
|
|
17
|
+
cwd: process.cwd(),
|
|
18
|
+
env: process.env,
|
|
19
|
+
stdio: "inherit",
|
|
20
|
+
});
|
|
21
|
+
if (result.error) {
|
|
22
|
+
console.error(`Missing Forge runtime for helper ${helperId}: ${result.error.message}`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
process.exit(result.status ?? 1);
|
|
26
|
+
}
|
|
@@ -1,36 +1,4 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# Run the canonical Forge adoption path without guessing a developer checkout.
|
|
3
|
-
#
|
|
4
|
-
# The self-host repository invokes this script directly, so delegating to a
|
|
5
|
-
# discovered copy of this same filename used to recurse. Installed helper
|
|
6
|
-
# copies use an explicit source root when one is supplied, otherwise the
|
|
7
|
-
# installed `forge` CLI.
|
|
8
|
-
|
|
9
2
|
set -euo pipefail
|
|
10
|
-
|
|
11
3
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
12
|
-
|
|
13
|
-
SOURCE_ROOT="${FORGE_SOURCE_ROOT:-${AGENTIC_DEV_ROOT:-${AGENTIC_DEV_SKILL_ROOT:-}}}"
|
|
14
|
-
|
|
15
|
-
run_source_root() {
|
|
16
|
-
local root="$1"
|
|
17
|
-
shift
|
|
18
|
-
[[ -f "$root/src/cli/index.ts" ]] || return 1
|
|
19
|
-
command -v bun >/dev/null 2>&1 || {
|
|
20
|
-
echo "[migrate] bun is required to run Forge from source: $root" >&2
|
|
21
|
-
exit 1
|
|
22
|
-
}
|
|
23
|
-
exec bun "$root/src/cli/index.ts" adopt "$@" --no-codegraph --no-verify
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
run_source_root "$SELF_SOURCE_ROOT" "$@"
|
|
27
|
-
if [[ -n "$SOURCE_ROOT" ]]; then
|
|
28
|
-
run_source_root "$SOURCE_ROOT" "$@"
|
|
29
|
-
fi
|
|
30
|
-
|
|
31
|
-
if command -v forge >/dev/null 2>&1; then
|
|
32
|
-
exec forge adopt "$@" --no-codegraph --no-verify
|
|
33
|
-
fi
|
|
34
|
-
|
|
35
|
-
echo "[migrate] Missing Forge CLI; set FORGE_SOURCE_ROOT to a Forge source checkout." >&2
|
|
36
|
-
exit 1
|
|
4
|
+
exec "$SCRIPT_DIR/lib/run-forge-helper.sh" "migrate-project-template.sh" "$@"
|