specrails-desktop 2.29.4 → 2.30.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/client/dist/assets/{ActivityFeedPage-CDMzpGXd.js → ActivityFeedPage-AQgpr9qG.js} +1 -1
- package/client/dist/assets/{AgentBrowserCapture-BVTacapZ.js → AgentBrowserCapture-I7a0usG7.js} +1 -1
- package/client/dist/assets/AgentModeCodePane-BqOVg15n.js +2 -0
- package/client/dist/assets/{AgentModeJobsPane-DAjN8Au5.js → AgentModeJobsPane-4SG6FF27.js} +1 -1
- package/client/dist/assets/{AgentsPage-CebykajE.js → AgentsPage-C3FgYlEi.js} +1 -1
- package/client/dist/assets/{AnalyticsPage-BiPrVvgv.js → AnalyticsPage-BcMNByW5.js} +1 -1
- package/client/dist/assets/{CodePage-Dw9eQFRS.js → CodePage-CgdDkXp-.js} +1 -1
- package/client/dist/assets/{DesktopAnalyticsPage-cCG_JAEi.js → DesktopAnalyticsPage-DPMcS88n.js} +1 -1
- package/client/dist/assets/{DocsDialog-C1kZ_mRP.js → DocsDialog-BC7574Zi.js} +1 -1
- package/client/dist/assets/{DocsPage-3GivxWJm.js → DocsPage-Dd9yilUg.js} +1 -1
- package/client/dist/assets/{InteractiveJobComposer-KuZXGdr8.js → InteractiveJobComposer-CqC_0VQL.js} +1 -1
- package/client/dist/assets/{JobDetailModal-DWpRALkB.js → JobDetailModal-BFNXOhk1.js} +1 -1
- package/client/dist/assets/{JobDetailPage-mrXDKafj.js → JobDetailPage-DM-6zYpA.js} +1 -1
- package/client/dist/assets/{JobsPage-CUYXjcoc.js → JobsPage-1dkjPk1k.js} +1 -1
- package/client/dist/assets/{LoopBuilderPage-CwjBD5Gm.js → LoopBuilderPage-BPeqz6cG.js} +1 -1
- package/client/dist/assets/{LoopPreviewModal-CO9ton0-.js → LoopPreviewModal-EdkyYaGN.js} +1 -1
- package/client/dist/assets/{LoopsPage-CLL5UuvN.js → LoopsPage-nZfgiaK8.js} +1 -1
- package/client/dist/assets/{MinimizedChatsContext-DJAkRYps.js → MinimizedChatsContext-Cs34FPTz.js} +1 -1
- package/client/dist/assets/{PluginsPage-DZvCC5Ri.js → PluginsPage-CwFfFBzW.js} +1 -1
- package/client/dist/assets/{ProjectSettingsDialog-C7Hesadg.js → ProjectSettingsDialog-DHsxLFMT.js} +1 -1
- package/client/dist/assets/{TemplatePreviewModal-DczCzUzP.js → TemplatePreviewModal-wcI3nGNr.js} +1 -1
- package/client/dist/assets/TicketDetailModal-7EloKP1C.js +14 -0
- package/client/dist/assets/{Trans-Cm9rhdnG.js → Trans-CPISVji8.js} +1 -1
- package/client/dist/assets/agent-BABjRt0P.js +1 -0
- package/client/dist/assets/agent-BuUpgqVx.js +1 -0
- package/client/dist/assets/agent-CCDZesgU.js +1 -0
- package/client/dist/assets/agent-CVn64zWH.js +1 -0
- package/client/dist/assets/agent-CWeOny0E.js +1 -0
- package/client/dist/assets/agent-DOysmad_.js +1 -0
- package/client/dist/assets/agent-DSsjTBhn.js +1 -0
- package/client/dist/assets/agent-DlZMxfM9.js +1 -0
- package/client/dist/assets/builder-BH8Fua-g.js +1 -0
- package/client/dist/assets/builder-BoV7DgKd.js +1 -0
- package/client/dist/assets/builder-Cc_Lf79C.js +1 -0
- package/client/dist/assets/builder-CwA4T7gP.js +1 -0
- package/client/dist/assets/builder-CwZ7Bme2.js +1 -0
- package/client/dist/assets/builder-CxW-JFsR.js +1 -0
- package/client/dist/assets/builder-D94lrV7x.js +1 -0
- package/client/dist/assets/builder-cqHpCyGa.js +1 -0
- package/client/dist/assets/{dist-js-BERxOT0X.js → dist-js-Bt2zW2YG.js} +1 -1
- package/client/dist/assets/{dist-js-Di8lflPo.js → dist-js-zvt5ap3o.js} +1 -1
- package/client/dist/assets/{formatDistanceToNow-BAXZRbEO.js → formatDistanceToNow-ByKli7Q_.js} +1 -1
- package/client/dist/assets/{getTimezoneOffsetInMilliseconds-DwzZXHtg.js → getTimezoneOffsetInMilliseconds-qrcBaLW1.js} +1 -1
- package/client/dist/assets/i18n-Bf9Ckd10.js +2 -0
- package/client/dist/assets/index-Dh9i4CnN.css +2 -0
- package/client/dist/assets/index-xkzK3E5i.js +76 -0
- package/client/dist/assets/setup-3832BJCo.js +1 -0
- package/client/dist/assets/setup-B8J-gECe.js +1 -0
- package/client/dist/assets/setup-BCIOxVsc.js +1 -0
- package/client/dist/assets/setup-BciLj_tU.js +1 -0
- package/client/dist/assets/setup-CITtPjed.js +1 -0
- package/client/dist/assets/setup-CTkE3cfh.js +1 -0
- package/client/dist/assets/setup-ajB4rYm-.js +1 -0
- package/client/dist/assets/setup-xFO1wNl0.js +1 -0
- package/client/dist/assets/{spending-BLb5pj6G.js → spending-DMnCXy84.js} +1 -1
- package/client/dist/assets/{useBrowserCaptureSession-DR1_jL56.js → useBrowserCaptureSession-CkBJShUw.js} +1 -1
- package/client/dist/assets/{useDesktop-D4DxBGPU.js → useDesktop-B4pSBIDd.js} +1 -1
- package/client/dist/index.html +14 -13
- package/docs/codex.md +2 -1
- package/docs/customizing.md +1 -1
- package/docs/internals/gemini-mcp-registration.md +1 -1
- package/docs/internals/global-artifacts-alignment-contract.md +4 -4
- package/docs/internals/project-builder.md +306 -0
- package/docs/internals/safe-pr-review-flow.md +29 -19
- package/package.json +1 -1
- package/server/dist/agent-operator-prompt.js +7 -1
- package/server/dist/blueprint-chat-manager.js +335 -0
- package/server/dist/blueprint-commit.js +335 -0
- package/server/dist/blueprint-draft-parser.js +168 -0
- package/server/dist/blueprint-operator-prompt.js +149 -0
- package/server/dist/blueprint-render.js +105 -0
- package/server/dist/blueprint-router.js +173 -0
- package/server/dist/blueprint-spec-quality.js +167 -0
- package/server/dist/blueprint-store.js +49 -0
- package/server/dist/blueprint-types.js +29 -0
- package/server/dist/builder-cwd-manager.js +57 -0
- package/server/dist/chat-manager.js +435 -23
- package/server/dist/context-scope.js +6 -3
- package/server/dist/contract-refine-runner.js +143 -72
- package/server/dist/desktop-db.js +27 -0
- package/server/dist/index.js +15 -0
- package/server/dist/offline-assemble.js +203 -0
- package/server/dist/pricing.js +5 -0
- package/server/dist/project-router-chat.js +14 -2
- package/server/dist/project-router.js +130 -7
- package/server/dist/providers/claude-adapter.js +8 -2
- package/server/dist/providers/codex-adapter.js +23 -10
- package/server/dist/providers/gemini-adapter.js +16 -7
- package/server/dist/rail-isolated-launch.js +11 -1
- package/server/dist/setup-manager.js +6 -54
- package/server/dist/spec-models.js +3 -0
- package/server/dist/workspace-manager.js +3 -1
- package/server/dist/worktree-overlay.js +233 -51
- package/client/dist/assets/AgentModeCodePane-D9bhFyuy.js +0 -2
- package/client/dist/assets/TicketDetailModal-CFh7GOv5.js +0 -14
- package/client/dist/assets/agent-BXc59ARK2.js +0 -1
- package/client/dist/assets/agent-BbIFXdDq.js +0 -1
- package/client/dist/assets/agent-BqEfA5u5.js +0 -1
- package/client/dist/assets/agent-BtGzgTC4.js +0 -1
- package/client/dist/assets/agent-CIhys_5d.js +0 -1
- package/client/dist/assets/agent-CJPaqsVR.js +0 -1
- package/client/dist/assets/agent-n-hY4GuL.js +0 -1
- package/client/dist/assets/agent-tJ-efa3_2.js +0 -1
- package/client/dist/assets/i18n-cK5pPbj8.js +0 -2
- package/client/dist/assets/index-BT6xDQjB.css +0 -2
- package/client/dist/assets/index-CCq_kIrF.js +0 -76
- package/client/dist/assets/setup-CGZjy2IF2.js +0 -1
- package/client/dist/assets/setup-CXa0Sx16.js +0 -1
- package/client/dist/assets/setup-CmK87LuS.js +0 -1
- package/client/dist/assets/setup-D2ktKKMF2.js +0 -1
- package/client/dist/assets/setup-DG2H7ha5.js +0 -1
- package/client/dist/assets/setup-DK5bHDUq2.js +0 -1
- package/client/dist/assets/setup-DrWlIQTZ.js +0 -1
- package/client/dist/assets/setup-rzHUVgAu.js +0 -1
- /package/client/dist/assets/{activity-C6kJpm9q2.js → activity-C6kJpm9q.js} +0 -0
- /package/client/dist/assets/{activity-DAyekdlt2.js → activity-DAyekdlt.js} +0 -0
- /package/client/dist/assets/{addspec-DbNBbrha2.js → addspec-DbNBbrha.js} +0 -0
- /package/client/dist/assets/{addspec-htHGZHOe2.js → addspec-htHGZHOe.js} +0 -0
- /package/client/dist/assets/{agents-6ZOJXWVk2.js → agents-6ZOJXWVk.js} +0 -0
- /package/client/dist/assets/{agents-Bz-thHkB2.js → agents-Bz-thHkB.js} +0 -0
- /package/client/dist/assets/{agentstudio-BLGvxWBx2.js → agentstudio-BLGvxWBx.js} +0 -0
- /package/client/dist/assets/{agentstudio-D9UKiWTj2.js → agentstudio-D9UKiWTj.js} +0 -0
- /package/client/dist/assets/{aiedit-BoG24nlg2.js → aiedit-BoG24nlg.js} +0 -0
- /package/client/dist/assets/{aiedit-olnv3QSt2.js → aiedit-olnv3QSt.js} +0 -0
- /package/client/dist/assets/{analytics-CdsAPAwZ2.js → analytics-CdsAPAwZ.js} +0 -0
- /package/client/dist/assets/{analytics-IEsKZvpW2.js → analytics-IEsKZvpW.js} +0 -0
- /package/client/dist/assets/{attachments-D0wXXt9T2.js → attachments-D0wXXt9T.js} +0 -0
- /package/client/dist/assets/{attachments-V_WZAYXx2.js → attachments-V_WZAYXx.js} +0 -0
- /package/client/dist/assets/{browser-CyR1Kp3m2.js → browser-CyR1Kp3m.js} +0 -0
- /package/client/dist/assets/{browser-DwZljcRh2.js → browser-DwZljcRh.js} +0 -0
- /package/client/dist/assets/{chat-BR8oe53x2.js → chat-BR8oe53x.js} +0 -0
- /package/client/dist/assets/{chat-DZyu3ImY2.js → chat-DZyu3ImY.js} +0 -0
- /package/client/dist/assets/{code-D20ef9Cf2.js → code-D20ef9Cf.js} +0 -0
- /package/client/dist/assets/{code-geHmknB92.js → code-geHmknB9.js} +0 -0
- /package/client/dist/assets/{commands-BEwbAjtD2.js → commands-BEwbAjtD.js} +0 -0
- /package/client/dist/assets/{commands-DTQBF_q52.js → commands-DTQBF_q5.js} +0 -0
- /package/client/dist/assets/{common-BNbnv8cE2.js → common-BNbnv8cE.js} +0 -0
- /package/client/dist/assets/{common-DBtTzeYm2.js → common-DBtTzeYm.js} +0 -0
- /package/client/dist/assets/{dashboard-Cqmmbh3l2.js → dashboard-Cqmmbh3l.js} +0 -0
- /package/client/dist/assets/{dashboard-Dy2Um-US2.js → dashboard-Dy2Um-US.js} +0 -0
- /package/client/dist/assets/{explore-C0TjprJW2.js → explore-C0TjprJW.js} +0 -0
- /package/client/dist/assets/{explore-DsXAgnmJ2.js → explore-DsXAgnmJ.js} +0 -0
- /package/client/dist/assets/{integrations-CH0zy1Mw2.js → integrations-CH0zy1Mw.js} +0 -0
- /package/client/dist/assets/{integrations-b8pH-vfl2.js → integrations-b8pH-vfl.js} +0 -0
- /package/client/dist/assets/{jira-CNeYi06w2.js → jira-CNeYi06w.js} +0 -0
- /package/client/dist/assets/{jira-pRaL7JQo2.js → jira-pRaL7JQo.js} +0 -0
- /package/client/dist/assets/{jobs-B-sDHEay2.js → jobs-B-sDHEay.js} +0 -0
- /package/client/dist/assets/{jobs-DzSIR8V62.js → jobs-DzSIR8V6.js} +0 -0
- /package/client/dist/assets/{loops-Crc9It8o2.js → loops-Crc9It8o.js} +0 -0
- /package/client/dist/assets/{loops-DH2hZcbK2.js → loops-DH2hZcbK.js} +0 -0
- /package/client/dist/assets/{loops-DS5TmvIU2.js → loops-DS5TmvIU.js} +0 -0
- /package/client/dist/assets/{mcp-Czd_iyp02.js → mcp-Czd_iyp0.js} +0 -0
- /package/client/dist/assets/{mcp-D4ZjtIx32.js → mcp-D4ZjtIx3.js} +0 -0
- /package/client/dist/assets/{mcp-DIfBUv2D2.js → mcp-DIfBUv2D.js} +0 -0
- /package/client/dist/assets/{nav-BRJBxaGt2.js → nav-BRJBxaGt.js} +0 -0
- /package/client/dist/assets/{nav-CNskRJKQ2.js → nav-CNskRJKQ.js} +0 -0
- /package/client/dist/assets/{nav-TvumAFD22.js → nav-TvumAFD2.js} +0 -0
- /package/client/dist/assets/{settings-DAZqjX2a2.js → settings-DAZqjX2a.js} +0 -0
- /package/client/dist/assets/{settings-DRh39v1S2.js → settings-DRh39v1S.js} +0 -0
- /package/client/dist/assets/{settings-Mj1OJbfd2.js → settings-Mj1OJbfd.js} +0 -0
- /package/client/dist/assets/{specs-BcyxaCwf2.js → specs-BcyxaCwf.js} +0 -0
- /package/client/dist/assets/{specs-CLZKysq-2.js → specs-CLZKysq-.js} +0 -0
- /package/client/dist/assets/{specs-dV3Mq5Mu2.js → specs-dV3Mq5Mu.js} +0 -0
- /package/client/dist/assets/{terminal-C2NAd7BW2.js → terminal-C2NAd7BW.js} +0 -0
- /package/client/dist/assets/{terminal-IahE4LW92.js → terminal-IahE4LW9.js} +0 -0
- /package/client/dist/assets/{terminal-QpXZU2Bn2.js → terminal-QpXZU2Bn.js} +0 -0
- /package/client/dist/assets/{tickets-Bs37scwY2.js → tickets-Bs37scwY.js} +0 -0
- /package/client/dist/assets/{tickets-DQp7JS2R2.js → tickets-DQp7JS2R.js} +0 -0
- /package/client/dist/assets/{tickets-DpmdE8tv2.js → tickets-DpmdE8tv.js} +0 -0
|
@@ -11,6 +11,10 @@ const code_explorer_router_1 = require("./code-explorer-router");
|
|
|
11
11
|
const jira_router_1 = require("./jira-router");
|
|
12
12
|
const ticket_store_1 = require("./ticket-store");
|
|
13
13
|
const workspace_resolution_1 = require("./workspace-resolution");
|
|
14
|
+
const workspace_manager_1 = require("./workspace-manager");
|
|
15
|
+
const blueprint_render_1 = require("./blueprint-render");
|
|
16
|
+
const blueprint_draft_parser_1 = require("./blueprint-draft-parser");
|
|
17
|
+
const blueprint_spec_quality_1 = require("./blueprint-spec-quality");
|
|
14
18
|
const file_story_manager_1 = require("./file-story-manager");
|
|
15
19
|
const file_summary_generator_1 = require("./file-summary-generator");
|
|
16
20
|
const providers_1 = require("./providers");
|
|
@@ -24,15 +28,16 @@ const project_router_terminals_1 = require("./project-router-terminals");
|
|
|
24
28
|
const project_router_settings_1 = require("./project-router-settings");
|
|
25
29
|
const project_router_loop_runs_1 = require("./project-router-loop-runs");
|
|
26
30
|
const project_router_git_1 = require("./project-router-git");
|
|
31
|
+
const project_router_helpers_1 = require("./project-router-helpers");
|
|
27
32
|
// Re-export the spec helpers from their new home so existing importers
|
|
28
33
|
// (`import { ... } from './project-router'`) keep working unchanged.
|
|
29
|
-
var
|
|
30
|
-
Object.defineProperty(exports, "stripSpecMetadataSections", { enumerable: true, get: function () { return
|
|
31
|
-
Object.defineProperty(exports, "extractShortSummary", { enumerable: true, get: function () { return
|
|
32
|
-
Object.defineProperty(exports, "deriveFallbackShortSummary", { enumerable: true, get: function () { return
|
|
33
|
-
Object.defineProperty(exports, "lightlyStructurePrompt", { enumerable: true, get: function () { return
|
|
34
|
-
Object.defineProperty(exports, "formatDescriptionWithCriteria", { enumerable: true, get: function () { return
|
|
35
|
-
Object.defineProperty(exports, "resolveDefaultSpecModel", { enumerable: true, get: function () { return
|
|
34
|
+
var project_router_helpers_2 = require("./project-router-helpers");
|
|
35
|
+
Object.defineProperty(exports, "stripSpecMetadataSections", { enumerable: true, get: function () { return project_router_helpers_2.stripSpecMetadataSections; } });
|
|
36
|
+
Object.defineProperty(exports, "extractShortSummary", { enumerable: true, get: function () { return project_router_helpers_2.extractShortSummary; } });
|
|
37
|
+
Object.defineProperty(exports, "deriveFallbackShortSummary", { enumerable: true, get: function () { return project_router_helpers_2.deriveFallbackShortSummary; } });
|
|
38
|
+
Object.defineProperty(exports, "lightlyStructurePrompt", { enumerable: true, get: function () { return project_router_helpers_2.lightlyStructurePrompt; } });
|
|
39
|
+
Object.defineProperty(exports, "formatDescriptionWithCriteria", { enumerable: true, get: function () { return project_router_helpers_2.formatDescriptionWithCriteria; } });
|
|
40
|
+
Object.defineProperty(exports, "resolveDefaultSpecModel", { enumerable: true, get: function () { return project_router_helpers_2.resolveDefaultSpecModel; } });
|
|
36
41
|
function createProjectRouter(registry) {
|
|
37
42
|
const router = (0, express_1.Router)({ mergeParams: true });
|
|
38
43
|
// Middleware: resolve project from :projectId param
|
|
@@ -139,6 +144,22 @@ function createProjectRouter(registry) {
|
|
|
139
144
|
});
|
|
140
145
|
codeRouter(req, res, next);
|
|
141
146
|
});
|
|
147
|
+
// Project Builder sidebar re-entry (add-project-builder D5): read the
|
|
148
|
+
// workspace-resident blueprint pair's source of truth. 404 when the project
|
|
149
|
+
// has no blueprint (every non-Builder project) — the sidebar entry hides.
|
|
150
|
+
router.get('/:projectId/blueprint', (req, res) => {
|
|
151
|
+
const project = ctx(req).project;
|
|
152
|
+
const exec = (0, workspace_resolution_1.resolveProjectExecution)({ slug: project.slug, path: project.path });
|
|
153
|
+
const workspace = exec.relocated && exec.workspaceDir
|
|
154
|
+
? exec.workspaceDir
|
|
155
|
+
: (project.slug ? (0, workspace_manager_1.workspacePathFor)(project.slug) : null);
|
|
156
|
+
const blueprint = workspace ? (0, blueprint_render_1.readBlueprint)(workspace) : null;
|
|
157
|
+
if (!blueprint) {
|
|
158
|
+
res.status(404).json({ error: 'no blueprint for this project' });
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
res.json({ blueprint });
|
|
162
|
+
});
|
|
142
163
|
// Relocate-artifacts gate (single chokepoint for ALL project-router ticket
|
|
143
164
|
// I/O): relocated ⇒ the registry entry's ticketsPath (workspace); legacy ⇒
|
|
144
165
|
// resolveTicketStoragePath (preserves integration-contract.json custom
|
|
@@ -148,6 +169,108 @@ function createProjectRouter(registry) {
|
|
|
148
169
|
const exec = (0, workspace_resolution_1.resolveProjectExecution)({ slug: project.slug, path: project.path });
|
|
149
170
|
return exec.relocated ? exec.ticketsPath : (0, ticket_store_1.resolveTicketStoragePath)(project.path);
|
|
150
171
|
};
|
|
172
|
+
// Milestone batch commit (add-project-builder D7): insert one blueprint
|
|
173
|
+
// milestone's generated specs as `M<n>`-labeled todo tickets, flip that
|
|
174
|
+
// milestone to `committed`, and re-render the blueprint pair. Jira-connected
|
|
175
|
+
// projects ride the existing materializer on the store mutation unchanged.
|
|
176
|
+
router.post('/:projectId/blueprint/commit-milestone', (req, res) => {
|
|
177
|
+
const projectCtx = ctx(req);
|
|
178
|
+
const project = projectCtx.project;
|
|
179
|
+
const body = (req.body ?? {});
|
|
180
|
+
const milestoneId = typeof body.milestoneId === 'string' && /^m[0-9]{1,3}$/i.test(body.milestoneId)
|
|
181
|
+
? body.milestoneId.toLowerCase()
|
|
182
|
+
: null;
|
|
183
|
+
if (!milestoneId) {
|
|
184
|
+
res.status(400).json({ error: 'milestoneId (e.g. "m2") is required' });
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const rawSpecs = Array.isArray(body.specs) ? body.specs : [];
|
|
188
|
+
if (rawSpecs.length === 0) {
|
|
189
|
+
res.status(400).json({ error: 'specs must contain at least one titled spec' });
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const exec = (0, workspace_resolution_1.resolveProjectExecution)({ slug: project.slug, path: project.path });
|
|
193
|
+
const workspace = exec.relocated && exec.workspaceDir
|
|
194
|
+
? exec.workspaceDir
|
|
195
|
+
: (project.slug ? (0, workspace_manager_1.workspacePathFor)(project.slug) : null);
|
|
196
|
+
const blueprint = workspace ? (0, blueprint_render_1.readBlueprint)(workspace) : null;
|
|
197
|
+
if (!workspace || !blueprint) {
|
|
198
|
+
res.status(404).json({ error: 'no blueprint for this project' });
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const milestone = blueprint.milestones.find((m) => m.id === milestoneId);
|
|
202
|
+
if (!milestone) {
|
|
203
|
+
res.status(404).json({ error: `milestone ${milestoneId} not found in the blueprint` });
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (milestone.status !== 'planned') {
|
|
207
|
+
res.status(409).json({ error: `milestone ${milestoneId} is already ${milestone.status}` });
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const label = milestoneId.toUpperCase();
|
|
211
|
+
const quality = (0, blueprint_spec_quality_1.analyzeBuilderSpecBatch)({ specsComplete: body.specsComplete, specs: rawSpecs }, { milestoneLabel: label, minSpecs: 1, maxSpecs: 10, requireScaffold: false });
|
|
212
|
+
if (!quality.valid) {
|
|
213
|
+
res.status(400).json({ error: 'milestone_spec_quality_invalid', detail: (0, blueprint_spec_quality_1.firstBuilderSpecQualityDetail)(quality) });
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
const coerced = (0, blueprint_draft_parser_1.coerceBlueprint)({ blueprintVersion: 1, specsComplete: true, m1Specs: rawSpecs });
|
|
217
|
+
const specs = coerced?.m1Specs ?? [];
|
|
218
|
+
try {
|
|
219
|
+
const created = [];
|
|
220
|
+
(0, ticket_store_1.mutateStore)(ticketPath(req), (store) => {
|
|
221
|
+
const indexToId = new Map();
|
|
222
|
+
specs.forEach((spec, index) => {
|
|
223
|
+
const id = store.next_id;
|
|
224
|
+
store.next_id += 1;
|
|
225
|
+
const now = new Date().toISOString();
|
|
226
|
+
const labels = spec.labels.includes(label) ? spec.labels : [...spec.labels, label];
|
|
227
|
+
const prerequisite = spec.dependsOnIndex;
|
|
228
|
+
const prerequisites = prerequisite !== undefined && indexToId.has(prerequisite)
|
|
229
|
+
? [indexToId.get(prerequisite)]
|
|
230
|
+
: [];
|
|
231
|
+
const ticket = {
|
|
232
|
+
id,
|
|
233
|
+
title: spec.title,
|
|
234
|
+
description: (0, project_router_helpers_1.formatDescriptionWithCriteria)(spec.description, spec.acceptanceCriteria),
|
|
235
|
+
status: 'todo',
|
|
236
|
+
priority: spec.priority,
|
|
237
|
+
labels,
|
|
238
|
+
assignee: null,
|
|
239
|
+
prerequisites,
|
|
240
|
+
metadata: {},
|
|
241
|
+
origin_conversation_id: null,
|
|
242
|
+
is_epic: false,
|
|
243
|
+
parent_epic_id: null,
|
|
244
|
+
execution_order: null,
|
|
245
|
+
short_summary: spec.shortSummary,
|
|
246
|
+
created_at: now,
|
|
247
|
+
updated_at: now,
|
|
248
|
+
created_by: 'project-builder',
|
|
249
|
+
source: 'project-builder',
|
|
250
|
+
};
|
|
251
|
+
store.tickets[String(id)] = ticket;
|
|
252
|
+
created.push(ticket);
|
|
253
|
+
indexToId.set(index, id);
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
milestone.status = 'committed';
|
|
257
|
+
milestone.ticketIds = created.map((t) => t.id);
|
|
258
|
+
(0, blueprint_render_1.writeBlueprintPair)(workspace, blueprint);
|
|
259
|
+
for (const ticket of created) {
|
|
260
|
+
projectCtx.broadcast({
|
|
261
|
+
type: 'ticket_created',
|
|
262
|
+
ticket: ticket,
|
|
263
|
+
projectId: project.id,
|
|
264
|
+
timestamp: new Date().toISOString(),
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
res.status(201).json({ insertedIds: created.map((t) => t.id), milestone: milestone.id });
|
|
268
|
+
}
|
|
269
|
+
catch (err) {
|
|
270
|
+
console.error('[project-router] commit-milestone error:', err);
|
|
271
|
+
res.status(500).json({ error: 'Failed to commit the milestone' });
|
|
272
|
+
}
|
|
273
|
+
});
|
|
151
274
|
const deps = { router, registry, ctx, ticketPath };
|
|
152
275
|
(0, project_router_jobs_1.registerJobsRoutes)(deps);
|
|
153
276
|
(0, project_router_spending_1.registerSpendingRoutes)(deps);
|
|
@@ -71,8 +71,14 @@ function commonFlagsFor(opts) {
|
|
|
71
71
|
return [
|
|
72
72
|
// No approval bypass is necessary when no tool can be invoked. Keeping it
|
|
73
73
|
// off also makes the pure-output boundary fail closed if Claude ever
|
|
74
|
-
// changes how it interprets the sentinel.
|
|
75
|
-
|
|
74
|
+
// changes how it interprets the sentinel. Read-only work uses Claude's
|
|
75
|
+
// native plan mode: Read/Grep/Glob stay usable without granting the
|
|
76
|
+
// blanket permission bypass carried by normal autonomous turns.
|
|
77
|
+
...(toolPolicy === 'default'
|
|
78
|
+
? ['--dangerously-skip-permissions']
|
|
79
|
+
: toolPolicy === 'read-only'
|
|
80
|
+
? ['--permission-mode', 'plan', '--safe-mode']
|
|
81
|
+
: []),
|
|
76
82
|
...toolArgs,
|
|
77
83
|
'--output-format', 'stream-json',
|
|
78
84
|
'--verbose',
|
|
@@ -33,6 +33,9 @@ const WHICH_CMD = process.platform === 'win32' ? 'where' : 'which';
|
|
|
33
33
|
const CODEX_MIN_VERSION = '0.128.0';
|
|
34
34
|
exports._CODEX_MIN_VERSION = CODEX_MIN_VERSION;
|
|
35
35
|
const CODEX_MODELS = [
|
|
36
|
+
{ value: 'gpt-5.6-sol', label: 'GPT-5.6 Sol' },
|
|
37
|
+
{ value: 'gpt-5.6-terra', label: 'GPT-5.6 Terra' },
|
|
38
|
+
{ value: 'gpt-5.6-luna', label: 'GPT-5.6 Luna' },
|
|
36
39
|
{ value: 'gpt-5.5', label: 'GPT-5.5', default: true },
|
|
37
40
|
{ value: 'gpt-5.4', label: 'GPT-5.4' },
|
|
38
41
|
{ value: 'gpt-5.4-mini', label: 'GPT-5.4 Mini' },
|
|
@@ -41,11 +44,19 @@ const CODEX_MODELS = [
|
|
|
41
44
|
const SANDBOX_FLAGS = ['--sandbox', 'workspace-write'];
|
|
42
45
|
const RAIL_SANDBOX_FLAGS = ['--sandbox', 'danger-full-access'];
|
|
43
46
|
// `codex exec resume` does NOT accept `--sandbox` (the flag only exists on
|
|
44
|
-
// `codex exec`);
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
const SANDBOX_RESUME_FLAGS = ['-c', 'sandbox_mode="workspace-write"'];
|
|
47
|
+
// `codex exec`); `resumeSandboxFlags` passes the selected policy as a `-c`
|
|
48
|
+
// config override instead, even when the per-project `.codex/config.toml`
|
|
49
|
+
// isn't on the spawn cwd (e.g. explore-cwd).
|
|
48
50
|
const SKIP_GIT_CHECK = '--skip-git-repo-check';
|
|
51
|
+
function sandboxFlags(opts, rail = false) {
|
|
52
|
+
if (opts.toolPolicy === 'read-only')
|
|
53
|
+
return ['--sandbox', 'read-only'];
|
|
54
|
+
return rail ? [...RAIL_SANDBOX_FLAGS] : [...SANDBOX_FLAGS];
|
|
55
|
+
}
|
|
56
|
+
function resumeSandboxFlags(opts) {
|
|
57
|
+
const mode = opts.toolPolicy === 'read-only' ? 'read-only' : 'workspace-write';
|
|
58
|
+
return ['-c', `sandbox_mode="${mode}"`];
|
|
59
|
+
}
|
|
49
60
|
/** Fold system prompt into the user prompt for providers without --system-prompt. */
|
|
50
61
|
function fold(systemPrompt, prompt) {
|
|
51
62
|
if (!systemPrompt)
|
|
@@ -76,7 +87,7 @@ function buildCodexArgs(action, opts) {
|
|
|
76
87
|
// ("quiero hacer un tetris"), the long system text dominates the prompt
|
|
77
88
|
// and codex responds to the system instructions instead of the user.
|
|
78
89
|
// Trust AGENTS.md and pass only the user prompt.
|
|
79
|
-
args.push('exec', '--json', ...
|
|
90
|
+
args.push('exec', '--json', ...sandboxFlags(opts), SKIP_GIT_CHECK);
|
|
80
91
|
args.push(opts.prompt);
|
|
81
92
|
args.push('--model', opts.model);
|
|
82
93
|
// Native reasoning effort (codex 0.139+). String value is quoted to match
|
|
@@ -95,7 +106,7 @@ function buildCodexArgs(action, opts) {
|
|
|
95
106
|
case 'agent-refine':
|
|
96
107
|
case 'auto-title':
|
|
97
108
|
case 'setup-enrich': {
|
|
98
|
-
args.push('exec', '--json', ...
|
|
109
|
+
args.push('exec', '--json', ...sandboxFlags(opts), SKIP_GIT_CHECK);
|
|
99
110
|
args.push(fold(opts.systemPrompt, opts.prompt));
|
|
100
111
|
args.push('--model', opts.model);
|
|
101
112
|
// Native reasoning effort (codex 0.139+). String value is quoted to match
|
|
@@ -113,7 +124,7 @@ function buildCodexArgs(action, opts) {
|
|
|
113
124
|
// See chat-turn note: AGENTS.md in explore-cwd carries the Explore
|
|
114
125
|
// framing; the per-turn argv must stay user-text-only so codex doesn't
|
|
115
126
|
// mistake the system prompt for the user request.
|
|
116
|
-
args.push('exec', 'resume', '--json', ...
|
|
127
|
+
args.push('exec', 'resume', '--json', ...resumeSandboxFlags(opts), SKIP_GIT_CHECK);
|
|
117
128
|
args.push(opts.sessionId);
|
|
118
129
|
args.push(opts.prompt);
|
|
119
130
|
args.push('--model', opts.model);
|
|
@@ -133,7 +144,7 @@ function buildCodexArgs(action, opts) {
|
|
|
133
144
|
if (!opts.sessionId) {
|
|
134
145
|
throw new Error(`${action} requires sessionId`);
|
|
135
146
|
}
|
|
136
|
-
args.push('exec', 'resume', '--json', ...
|
|
147
|
+
args.push('exec', 'resume', '--json', ...resumeSandboxFlags(opts), SKIP_GIT_CHECK);
|
|
137
148
|
args.push(opts.sessionId);
|
|
138
149
|
args.push(fold(opts.systemPrompt, opts.prompt));
|
|
139
150
|
args.push('--model', opts.model);
|
|
@@ -157,7 +168,7 @@ function buildCodexArgs(action, opts) {
|
|
|
157
168
|
// On Windows, Codex's workspace-write sandbox can fail before the first
|
|
158
169
|
// shell command with `windows sandbox: spawn setup refresh`; full access
|
|
159
170
|
// matches the existing fully-autonomous rail contract.
|
|
160
|
-
args.push('exec', '--json', ...
|
|
171
|
+
args.push('exec', '--json', ...sandboxFlags(opts, true), SKIP_GIT_CHECK);
|
|
161
172
|
args.push(fold(opts.systemPrompt, opts.prompt));
|
|
162
173
|
args.push('--model', opts.model);
|
|
163
174
|
// Native reasoning effort (codex 0.139+). String value is quoted to match
|
|
@@ -333,7 +344,9 @@ exports.codexAdapter = {
|
|
|
333
344
|
profileEnvSupport: true,
|
|
334
345
|
systemPromptArg: false,
|
|
335
346
|
supportsReasoningEffort: true,
|
|
336
|
-
|
|
347
|
+
// codex model_reasoning_effort values. xhigh/max ship with GPT-5.6 (all
|
|
348
|
+
// tiers); ultra is Sol-only upstream — codex validates the combo itself.
|
|
349
|
+
reasoningEfforts: ['minimal', 'low', 'medium', 'high', 'xhigh', 'max', 'ultra'],
|
|
337
350
|
supportsImageInput: true, // codex-cli `-i/--image <FILE>...` (verified 0.141)
|
|
338
351
|
},
|
|
339
352
|
modelCatalog: () => CODEX_MODELS,
|
|
@@ -44,10 +44,19 @@ const GEMINI_MODELS = [
|
|
|
44
44
|
{ value: 'gemini-2.5-flash-lite', label: 'Gemini 2.5 Flash Lite' },
|
|
45
45
|
];
|
|
46
46
|
const STREAM_JSON_FLAGS = ['--output-format', 'stream-json'];
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
//
|
|
47
|
+
// Default autonomous turns auto-approve tool calls so they never block on a
|
|
48
|
+
// headless approval prompt. `approvalFlags` replaces this with native plan mode
|
|
49
|
+
// for explicitly read-only work; the two modes are never combined.
|
|
50
50
|
const YOLO_FLAG = '--yolo';
|
|
51
|
+
function approvalFlags(opts) {
|
|
52
|
+
// Gemini CLI has no Codex-style selectable filesystem sandbox mode. Its
|
|
53
|
+
// verified native read-only boundary is approval-mode=plan (documented by
|
|
54
|
+
// the CLI itself as "plan (read-only mode)"). Crucially, never combine it
|
|
55
|
+
// with --yolo, which would auto-approve every action.
|
|
56
|
+
return opts.toolPolicy === 'read-only'
|
|
57
|
+
? ['--approval-mode', 'plan']
|
|
58
|
+
: [YOLO_FLAG];
|
|
59
|
+
}
|
|
51
60
|
/** Fold system prompt into the user prompt for providers without --system-prompt. */
|
|
52
61
|
function fold(systemPrompt, prompt) {
|
|
53
62
|
if (!systemPrompt)
|
|
@@ -63,12 +72,12 @@ function buildGeminiArgs(action, opts) {
|
|
|
63
72
|
// short user message ("quiero hacer un tetris") makes the model answer the
|
|
64
73
|
// system instructions instead of the user — so pass user text only and
|
|
65
74
|
// trust GEMINI.md, exactly like the codex adapter trusts AGENTS.md.
|
|
66
|
-
return ['-p', opts.prompt, ...model, ...STREAM_JSON_FLAGS,
|
|
75
|
+
return ['-p', opts.prompt, ...model, ...STREAM_JSON_FLAGS, ...approvalFlags(opts), ...(opts.extraArgs ?? [])];
|
|
67
76
|
}
|
|
68
77
|
case 'chat-resume': {
|
|
69
78
|
if (!opts.sessionId)
|
|
70
79
|
throw new Error(`${action} requires sessionId`);
|
|
71
|
-
return ['-p', opts.prompt, ...model, ...STREAM_JSON_FLAGS, '--resume', opts.sessionId,
|
|
80
|
+
return ['-p', opts.prompt, ...model, ...STREAM_JSON_FLAGS, '--resume', opts.sessionId, ...approvalFlags(opts), ...(opts.extraArgs ?? [])];
|
|
72
81
|
}
|
|
73
82
|
case 'chat-stream': {
|
|
74
83
|
// Gemini has no persistent-stdin multi-turn transport; the Explore
|
|
@@ -81,12 +90,12 @@ function buildGeminiArgs(action, opts) {
|
|
|
81
90
|
case 'auto-title':
|
|
82
91
|
case 'setup-enrich':
|
|
83
92
|
case 'rail-job': {
|
|
84
|
-
return ['-p', fold(opts.systemPrompt, opts.prompt), ...model, ...STREAM_JSON_FLAGS,
|
|
93
|
+
return ['-p', fold(opts.systemPrompt, opts.prompt), ...model, ...STREAM_JSON_FLAGS, ...approvalFlags(opts), ...(opts.extraArgs ?? [])];
|
|
85
94
|
}
|
|
86
95
|
case 'setup-enrich-resume': {
|
|
87
96
|
if (!opts.sessionId)
|
|
88
97
|
throw new Error(`${action} requires sessionId`);
|
|
89
|
-
return ['-p', fold(opts.systemPrompt, opts.prompt), ...model, ...STREAM_JSON_FLAGS, '--resume', opts.sessionId,
|
|
98
|
+
return ['-p', fold(opts.systemPrompt, opts.prompt), ...model, ...STREAM_JSON_FLAGS, '--resume', opts.sessionId, ...approvalFlags(opts), ...(opts.extraArgs ?? [])];
|
|
90
99
|
}
|
|
91
100
|
}
|
|
92
101
|
}
|
|
@@ -408,10 +408,18 @@ async function launchIsolatedRail(input, io = {}) {
|
|
|
408
408
|
// overlay their repo's own untracked on-disk entries instead. Resolved ONCE
|
|
409
409
|
// per launch; a resolution failure degrades to the legacy (repo) source.
|
|
410
410
|
let overlaySourceRoot = baseRepo;
|
|
411
|
+
let overlayFallbackRoots;
|
|
411
412
|
try {
|
|
412
413
|
const exec = resolveExecution({ slug, path: baseRepo });
|
|
413
|
-
if (exec.relocated && exec.workspaceDir)
|
|
414
|
+
if (exec.relocated && exec.workspaceDir) {
|
|
414
415
|
overlaySourceRoot = exec.workspaceDir;
|
|
416
|
+
// The repo as FALLBACK root: repo-resident untracked carve-outs
|
|
417
|
+
// (OpenSpec's `/opsx:*` commands, `openspec-*` skills, user extras)
|
|
418
|
+
// are absent from both the checkout (untracked) and the workspace
|
|
419
|
+
// (the framework ships only `specrails/`), so without this the claude
|
|
420
|
+
// CLI reports `Unknown command: /opsx:ff` inside isolated rails.
|
|
421
|
+
overlayFallbackRoots = [baseRepo];
|
|
422
|
+
}
|
|
415
423
|
}
|
|
416
424
|
catch { /* legacy fallback */ }
|
|
417
425
|
let overlayProviderDir = '.claude';
|
|
@@ -668,6 +676,7 @@ async function launchIsolatedRail(input, io = {}) {
|
|
|
668
676
|
const res = overlay({
|
|
669
677
|
worktreePath: handle.worktreePath,
|
|
670
678
|
sourceRoot: overlaySourceRoot,
|
|
679
|
+
fallbackSourceRoots: overlayFallbackRoots,
|
|
671
680
|
providerDir: overlayProviderDir,
|
|
672
681
|
instructionsFilename: overlayInstructions,
|
|
673
682
|
});
|
|
@@ -847,6 +856,7 @@ async function launchIsolatedRail(input, io = {}) {
|
|
|
847
856
|
a.overlayCleanupEvidence = (0, worktree_overlay_1.revalidateOverlayCleanupEvidence)({
|
|
848
857
|
worktreePath: a.handle.worktreePath,
|
|
849
858
|
sourceRoot: overlaySourceRoot,
|
|
859
|
+
fallbackSourceRoots: overlayFallbackRoots,
|
|
850
860
|
providerDir: overlayProviderDir,
|
|
851
861
|
instructionsFilename: overlayInstructions,
|
|
852
862
|
}, a.overlayCleanupEvidence);
|
|
@@ -26,8 +26,8 @@ const crypto_1 = require("crypto");
|
|
|
26
26
|
const artifact_registry_1 = require("./artifact-registry");
|
|
27
27
|
const install_config_path_1 = require("./install-config-path");
|
|
28
28
|
const bundled_core_1 = require("./bundled-core");
|
|
29
|
-
const bundled_openspec_1 = require("./bundled-openspec");
|
|
30
29
|
const path_resolver_1 = require("./path-resolver");
|
|
30
|
+
const offline_assemble_1 = require("./offline-assemble");
|
|
31
31
|
const framework_manager_1 = require("./framework-manager");
|
|
32
32
|
const workspace_resolution_1 = require("./workspace-resolution");
|
|
33
33
|
/**
|
|
@@ -90,58 +90,10 @@ function spawnCoreInit(args, cwd) {
|
|
|
90
90
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
91
91
|
});
|
|
92
92
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
* sources resolve from the app bundle, NOT a global install or npm registry. The
|
|
98
|
-
* framework was already materialized by FrameworkManager.materialize() (idempotent
|
|
99
|
-
* — core's ensureFramework skips re-materialization), so this call only assembles
|
|
100
|
-
* the workspace by symlink + runs openspec init.
|
|
101
|
-
*
|
|
102
|
-
* Returns null when no bundled core is present (caller falls back to spawnCoreInit).
|
|
103
|
-
*/
|
|
104
|
-
function spawnBundledCoreInit(args, cwd) {
|
|
105
|
-
const cli = (0, bundled_core_1.getBundledCoreCli)();
|
|
106
|
-
const coreRoot = (0, bundled_core_1.getBundledCoreRoot)();
|
|
107
|
-
if (!cli || !coreRoot)
|
|
108
|
-
return null;
|
|
109
|
-
const fullArgs = [cli, 'init', ...args];
|
|
110
|
-
// Force RELOCATION (core installs in-repo by default; the desktop keeps the
|
|
111
|
-
// user's repo pristine + manages the spawn cwd). See spawnCoreInit.
|
|
112
|
-
const env = { ...(0, win_spawn_1.windowsSpawnEnv)(), SPECRAILS_CORE_SCRIPT_DIR: coreRoot, SPECRAILS_RELOCATE: '1' };
|
|
113
|
-
// Bundled openspec (offline) — the LAST network step of project-add. When the
|
|
114
|
-
// app ships @fission-ai/openspec, point specrails-core's `installOpenSpecProject`
|
|
115
|
-
// at the bundled CLI and the SAME node we run the bundled core with. Tauri
|
|
116
|
-
// strips exec bits from bundled resources and the openspec CLI is a node script,
|
|
117
|
-
// so it MUST be invoked as `node <cli> init …` — hence we set BOTH the BIN and
|
|
118
|
-
// the NODE env (specrails-core's buildOpenSpecInvocation form 1). When absent we
|
|
119
|
-
// leave them unset → core falls back to `npx @fission-ai/openspec` (still works
|
|
120
|
-
// online). Bundled core + bundled openspec ⇒ project-add is FULLY OFFLINE.
|
|
121
|
-
const openspecCli = (0, bundled_openspec_1.getBundledOpenspecCli)();
|
|
122
|
-
if (openspecCli) {
|
|
123
|
-
env.SPECRAILS_OPENSPEC_BIN = openspecCli;
|
|
124
|
-
// Core runs openspec as `<node> <cli> init …`. SPECRAILS_OPENSPEC_NODE MUST be
|
|
125
|
-
// a REAL node executable — NOT process.execPath (the packaged `specrails-server`
|
|
126
|
-
// pkg binary), which cannot run openspec's ESM CLI and made `openspec init`
|
|
127
|
-
// exit with code -1 (→ core throws InstallerError code 50, setup fails). Prefer
|
|
128
|
-
// the bundled Node; fall back to `node` on PATH (resolveStartupPath prepends the
|
|
129
|
-
// bundled node bin in desktop mode, so PATH `node` is the bundled node too).
|
|
130
|
-
env.SPECRAILS_OPENSPEC_NODE = (0, path_resolver_1.resolveBundledNodeExe)() ?? 'node';
|
|
131
|
-
}
|
|
132
|
-
// Run the core CLI with the REAL bundled node — NOT process.execPath, which in
|
|
133
|
-
// the packaged app is the `specrails-server` pkg binary and would re-launch the
|
|
134
|
-
// server instead of running cli.js (same trap as SPECRAILS_OPENSPEC_NODE above).
|
|
135
|
-
// Fall back to process.execPath only in dev/tests where it IS node.
|
|
136
|
-
const nodeBin = (0, path_resolver_1.resolveBundledNodeExe)() ?? process.execPath;
|
|
137
|
-
console.log(`[SetupManager] spawning BUNDLED core: ${nodeBin} ${fullArgs.join(' ')} (cwd=${cwd})` +
|
|
138
|
-
(openspecCli ? ' [bundled openspec: offline]' : ' [openspec: npx fallback]'));
|
|
139
|
-
return (0, win_spawn_1.spawnCli)(nodeBin, fullArgs, {
|
|
140
|
-
cwd,
|
|
141
|
-
env,
|
|
142
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
143
|
-
});
|
|
144
|
-
}
|
|
93
|
+
// The bundled-core `init` spawn primitive is shared with the Project Builder's
|
|
94
|
+
// orchestrated commit (extract-don't-fork, add-project-builder D4) — the wizard
|
|
95
|
+
// keeps its streaming/phase shell and npx fallback around it.
|
|
96
|
+
// (Imported: spawnBundledCoreInit from ./offline-assemble.)
|
|
145
97
|
// H19: hard cap on the runtime probe. `npx --yes --prefer-online
|
|
146
98
|
// <CORE_PACKAGE_SPEC> version` does a network round-trip to the npm
|
|
147
99
|
// registry, and spawnSync blocks the single event loop — without a timeout a
|
|
@@ -867,7 +819,7 @@ class SetupManager {
|
|
|
867
819
|
}
|
|
868
820
|
// Bundled core (offline, node <cli> init) when available, else legacy npx.
|
|
869
821
|
const child = useBundledCore
|
|
870
|
-
? spawnBundledCoreInit(initArgs, projectPath)
|
|
822
|
+
? (0, offline_assemble_1.spawnBundledCoreInit)(initArgs, projectPath)
|
|
871
823
|
: spawnCoreInit(initArgs, projectPath);
|
|
872
824
|
this._installProcesses.set(projectId, child);
|
|
873
825
|
this._installLogBuffer.set(projectId, diagHeader);
|
|
@@ -11,6 +11,9 @@ exports.CLAUDE_MODELS = [
|
|
|
11
11
|
{ value: 'haiku', label: 'Claude Haiku' },
|
|
12
12
|
];
|
|
13
13
|
exports.CODEX_MODELS = [
|
|
14
|
+
{ value: 'gpt-5.6-sol', label: 'GPT-5.6 Sol' },
|
|
15
|
+
{ value: 'gpt-5.6-terra', label: 'GPT-5.6 Terra' },
|
|
16
|
+
{ value: 'gpt-5.6-luna', label: 'GPT-5.6 Luna' },
|
|
14
17
|
{ value: 'gpt-5.5', label: 'GPT-5.5' },
|
|
15
18
|
{ value: 'gpt-5.4', label: 'GPT-5.4' },
|
|
16
19
|
{ value: 'gpt-5.4-mini', label: 'GPT-5.4 Mini' },
|
|
@@ -99,7 +99,9 @@ function ensureFrameworkAgents(workspaceDir, providerDir, home) {
|
|
|
99
99
|
}
|
|
100
100
|
/** The framework subtrees `assemble` installs as a single DIR-symlink into
|
|
101
101
|
* `current/<provider>/` (unlike agents, which are per-file). `/specrails:*`
|
|
102
|
-
*
|
|
102
|
+
* slash commands live under `commands/`. (`/opsx:*` is NOT framework — the
|
|
103
|
+
* external OpenSpec binary installs it into the REPO's provider dir; isolated
|
|
104
|
+
* rails receive it via the worktree overlay's repo fallback root.) */
|
|
103
105
|
const DIR_LINKED_SUBTREES = ['commands', 'skills', 'rules'];
|
|
104
106
|
/**
|
|
105
107
|
* Windows repair for the DIR-symlinked framework subtrees (`commands`, `skills`,
|