@contentful/experience-design-system-cli 2.14.2 → 2.15.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/README.md +64 -2
- package/dist/package.json +3 -2
- package/dist/src/analyze/command.d.ts +11 -0
- package/dist/src/analyze/command.js +298 -3
- package/dist/src/analyze/composite-closure.d.ts +25 -0
- package/dist/src/analyze/composite-closure.js +0 -0
- package/dist/src/analyze/composition/agent-parser/author-prompt.d.ts +4 -0
- package/dist/src/analyze/composition/agent-parser/author-prompt.js +22 -0
- package/dist/src/analyze/composition/agent-parser/extract-parser.d.ts +8 -0
- package/dist/src/analyze/composition/agent-parser/extract-parser.js +44 -0
- package/dist/src/analyze/composition/agent-parser/load-prompt.d.ts +7 -0
- package/dist/src/analyze/composition/agent-parser/load-prompt.js +31 -0
- package/dist/src/analyze/composition/agent-parser/resolve-via-parser.d.ts +46 -0
- package/dist/src/analyze/composition/agent-parser/resolve-via-parser.js +88 -0
- package/dist/src/analyze/composition/agent-parser/sandbox.d.ts +45 -0
- package/dist/src/analyze/composition/agent-parser/sandbox.js +187 -0
- package/dist/src/analyze/composition/apply-mapping.d.ts +22 -0
- package/dist/src/analyze/composition/apply-mapping.js +67 -0
- package/dist/src/analyze/composition/candidate-critic-agent.d.ts +7 -0
- package/dist/src/analyze/composition/candidate-critic-agent.js +39 -0
- package/dist/src/analyze/composition/candidate-critic.d.ts +32 -0
- package/dist/src/analyze/composition/candidate-critic.js +63 -0
- package/dist/src/analyze/composition/candidate-files.d.ts +34 -0
- package/dist/src/analyze/composition/candidate-files.js +131 -0
- package/dist/src/analyze/composition/composition-cache-key.d.ts +19 -0
- package/dist/src/analyze/composition/composition-cache-key.js +19 -0
- package/dist/src/analyze/composition/interchange-schema.d.ts +37 -0
- package/dist/src/analyze/composition/interchange-schema.js +61 -0
- package/dist/src/analyze/composition/merge-edges.d.ts +19 -0
- package/dist/src/analyze/composition/merge-edges.js +50 -0
- package/dist/src/analyze/composition/parse-map-edges.d.ts +16 -0
- package/dist/src/analyze/composition/parse-map-edges.js +55 -0
- package/dist/src/analyze/composition/resolve-mapping-cli.d.ts +23 -0
- package/dist/src/analyze/composition/resolve-mapping-cli.js +29 -0
- package/dist/src/analyze/composition/resolve-mapping.d.ts +59 -0
- package/dist/src/analyze/composition/resolve-mapping.js +94 -0
- package/dist/src/analyze/cycle-detection.d.ts +27 -0
- package/dist/src/analyze/cycle-detection.js +234 -0
- package/dist/src/analyze/cycle-view.d.ts +7 -0
- package/dist/src/analyze/cycle-view.js +28 -0
- package/dist/src/analyze/fuzzy-search.d.ts +3 -0
- package/dist/src/analyze/fuzzy-search.js +55 -0
- package/dist/src/analyze/issue-inheritance.d.ts +12 -0
- package/dist/src/analyze/issue-inheritance.js +108 -0
- package/dist/src/analyze/lineage.d.ts +29 -0
- package/dist/src/analyze/lineage.js +0 -0
- package/dist/src/analyze/scope-gate-cascade.d.ts +11 -0
- package/dist/src/analyze/scope-gate-cascade.js +170 -0
- package/dist/src/analyze/search-neighborhood.d.ts +3 -0
- package/dist/src/analyze/search-neighborhood.js +56 -0
- package/dist/src/analyze/select/tui/App.js +5 -16
- package/dist/src/analyze/select/tui/components/ComponentRationalePanel.d.ts +0 -4
- package/dist/src/analyze/select/tui/components/ComponentRationalePanel.js +3 -15
- package/dist/src/analyze/select/tui/components/FieldEditor.d.ts +29 -38
- package/dist/src/analyze/select/tui/components/FieldEditor.js +309 -185
- package/dist/src/analyze/select/tui/components/FinalizeDialog.d.ts +13 -1
- package/dist/src/analyze/select/tui/components/FinalizeDialog.js +23 -2
- package/dist/src/analyze/select/tui/components/GotoBanner.d.ts +31 -0
- package/dist/src/analyze/select/tui/components/GotoBanner.js +30 -0
- package/dist/src/analyze/select/tui/components/GroupedSidebar.d.ts +91 -0
- package/dist/src/analyze/select/tui/components/GroupedSidebar.js +497 -0
- package/dist/src/analyze/select/tui/components/HelpOverlay.d.ts +13 -1
- package/dist/src/analyze/select/tui/components/HelpOverlay.js +9 -3
- package/dist/src/analyze/select/tui/components/JsonEditor.js +3 -3
- package/dist/src/analyze/select/tui/components/LineagePanel.d.ts +14 -0
- package/dist/src/analyze/select/tui/components/LineagePanel.js +22 -0
- package/dist/src/analyze/select/tui/components/RationalePanel.d.ts +0 -7
- package/dist/src/analyze/select/tui/components/RationalePanel.js +3 -15
- package/dist/src/analyze/select/tui/components/Sidebar.d.ts +0 -6
- package/dist/src/analyze/select/tui/components/Sidebar.js +11 -27
- package/dist/src/analyze/select/tui/components/StatusBar.js +2 -1
- package/dist/src/analyze/select/tui/components/removed-components-text.d.ts +7 -0
- package/dist/src/analyze/select/tui/components/removed-components-text.js +11 -0
- package/dist/src/analyze/select/tui/hooks/useImmediateInput.d.ts +1 -5
- package/dist/src/analyze/select/tui/hooks/useImmediateInput.js +8 -10
- package/dist/src/analyze/select/tui/theme.d.ts +15 -0
- package/dist/src/analyze/select/tui/theme.js +28 -0
- package/dist/src/analyze/selection-cascade.d.ts +3 -0
- package/dist/src/analyze/selection-cascade.js +19 -0
- package/dist/src/analyze/slot-graph.d.ts +11 -0
- package/dist/src/analyze/slot-graph.js +17 -0
- package/dist/src/apply/api-client.d.ts +2 -1
- package/dist/src/apply/api-client.js +40 -6
- package/dist/src/apply/command.d.ts +17 -1
- package/dist/src/apply/command.js +69 -11
- package/dist/src/apply/error-parser.d.ts +16 -0
- package/dist/src/apply/error-parser.js +117 -0
- package/dist/src/apply/tui/ServerPreviewView.js +3 -1
- package/dist/src/credentials-store.d.ts +6 -0
- package/dist/src/credentials-store.js +5 -1
- package/dist/src/generate/agent-runner.d.ts +6 -0
- package/dist/src/generate/agent-runner.js +24 -8
- package/dist/src/import/command.js +69 -31
- package/dist/src/import/cycle-auto-reject.d.ts +4 -0
- package/dist/src/import/cycle-auto-reject.js +14 -0
- package/dist/src/import/orchestrator.d.ts +20 -7
- package/dist/src/import/orchestrator.js +139 -35
- package/dist/src/import/strip-allowed-components.d.ts +18 -0
- package/dist/src/import/strip-allowed-components.js +22 -0
- package/dist/src/import/tui/CustomPromptBanner.d.ts +0 -5
- package/dist/src/import/tui/CustomPromptBanner.js +2 -1
- package/dist/src/import/tui/WizardApp.d.ts +10 -74
- package/dist/src/import/tui/WizardApp.js +234 -246
- package/dist/src/import/tui/ai-flag.d.ts +5 -0
- package/dist/src/import/tui/ai-flag.js +6 -0
- package/dist/src/import/tui/autocomplete.d.ts +5 -0
- package/dist/src/import/tui/autocomplete.js +32 -0
- package/dist/src/import/tui/components/AutoFilterBanner.d.ts +10 -0
- package/dist/src/import/tui/components/AutoFilterBanner.js +19 -0
- package/dist/src/import/tui/components/CounterStrip.d.ts +12 -0
- package/dist/src/import/tui/components/CounterStrip.js +12 -0
- package/dist/src/import/tui/components/LegendEntry.d.ts +2 -0
- package/dist/src/import/tui/components/LegendEntry.js +6 -0
- package/dist/src/import/tui/cycle-panel-scroll.d.ts +8 -0
- package/dist/src/import/tui/cycle-panel-scroll.js +33 -0
- package/dist/src/import/tui/final-review-host.d.ts +3 -7
- package/dist/src/import/tui/final-review-host.js +9 -4
- package/dist/src/import/tui/group-collapse.d.ts +2 -0
- package/dist/src/import/tui/group-collapse.js +11 -0
- package/dist/src/import/tui/history.d.ts +22 -0
- package/dist/src/import/tui/history.js +53 -0
- package/dist/src/import/tui/hooks/useLineage.d.ts +32 -0
- package/dist/src/import/tui/hooks/useLineage.js +50 -0
- package/dist/src/import/tui/hooks/useOverlayPanel.d.ts +13 -0
- package/dist/src/import/tui/hooks/useOverlayPanel.js +27 -0
- package/dist/src/import/tui/lineage-layout.d.ts +75 -0
- package/dist/src/import/tui/lineage-layout.js +82 -0
- package/dist/src/import/tui/runLivePreview.d.ts +11 -0
- package/dist/src/import/tui/runLivePreview.js +7 -1
- package/dist/src/import/tui/scope-gate-columns.d.ts +31 -0
- package/dist/src/import/tui/scope-gate-columns.js +94 -0
- package/dist/src/import/tui/scope-gate-host.d.ts +3 -1
- package/dist/src/import/tui/scope-gate-host.js +11 -3
- package/dist/src/import/tui/sidebar-width.d.ts +1 -0
- package/dist/src/import/tui/sidebar-width.js +3 -0
- package/dist/src/import/tui/step-filters.d.ts +19 -0
- package/dist/src/import/tui/step-filters.js +42 -0
- package/dist/src/import/tui/steps/AtomicGenerateReviewStep.d.ts +42 -0
- package/dist/src/import/tui/steps/AtomicGenerateReviewStep.js +726 -0
- package/dist/src/import/tui/steps/AtomicScopeGateStep.d.ts +3 -0
- package/dist/src/import/tui/steps/AtomicScopeGateStep.js +211 -0
- package/dist/src/import/tui/steps/CredentialsStep.js +5 -18
- package/dist/src/import/tui/steps/DoneStep.d.ts +0 -2
- package/dist/src/import/tui/steps/DoneStep.js +3 -2
- package/dist/src/import/tui/steps/ErrorStep.js +2 -1
- package/dist/src/import/tui/steps/GenerateReviewStep.d.ts +19 -25
- package/dist/src/import/tui/steps/GenerateReviewStep.js +1258 -229
- package/dist/src/import/tui/steps/PathValidationStep.js +3 -2
- package/dist/src/import/tui/steps/PreviewStep.js +2 -1
- package/dist/src/import/tui/steps/PushDecisionGateStep.d.ts +0 -7
- package/dist/src/import/tui/steps/PushDecisionGateStep.js +3 -6
- package/dist/src/import/tui/steps/PushingStep.js +2 -1
- package/dist/src/import/tui/steps/RunningStep.d.ts +4 -1
- package/dist/src/import/tui/steps/RunningStep.js +3 -2
- package/dist/src/import/tui/steps/ScopeGateStep.d.ts +24 -0
- package/dist/src/import/tui/steps/ScopeGateStep.js +850 -193
- package/dist/src/import/tui/steps/TokenInputStep.js +2 -1
- package/dist/src/import/tui/steps/WelcomeStep.js +2 -1
- package/dist/src/import/tui/steps/WizardPreviewStep.d.ts +6 -0
- package/dist/src/import/tui/steps/WizardPreviewStep.js +95 -56
- package/dist/src/import/tui/steps/auto-reject-decision.d.ts +7 -0
- package/dist/src/import/tui/steps/auto-reject-decision.js +9 -0
- package/dist/src/import/tui/steps/breaking-change-format.d.ts +2 -0
- package/dist/src/import/tui/steps/breaking-change-format.js +24 -0
- package/dist/src/import/tui/steps/enumerate-cycle-breaks.d.ts +14 -0
- package/dist/src/import/tui/steps/enumerate-cycle-breaks.js +0 -0
- package/dist/src/import/tui/steps/preview-diff.js +48 -5
- package/dist/src/import/tui/useFinalizePreview.d.ts +34 -0
- package/dist/src/import/tui/useFinalizePreview.js +0 -0
- package/dist/src/import/tui/useLivePreview.d.ts +3 -0
- package/dist/src/import/tui/useLivePreview.js +1 -0
- package/dist/src/import/tui/wizard-state-transitions.d.ts +5 -59
- package/dist/src/import/tui/wizard-state-transitions.js +5 -60
- package/dist/src/lib/composition-mode.d.ts +28 -0
- package/dist/src/lib/composition-mode.js +37 -0
- package/dist/src/lib/prompt-overrides.d.ts +38 -0
- package/dist/src/lib/prompt-overrides.js +69 -0
- package/dist/src/print/command.js +19 -1
- package/dist/src/runs/modify-launcher.d.ts +3 -0
- package/dist/src/runs/modify-launcher.js +2 -0
- package/dist/src/runs/replay-helpers.js +1 -0
- package/dist/src/runs/run-picker.js +2 -18
- package/dist/src/runs/store.d.ts +4 -0
- package/dist/src/session/db.d.ts +23 -40
- package/dist/src/session/db.js +110 -138
- package/dist/src/setup/composition-mode-prompt.d.ts +14 -0
- package/dist/src/setup/composition-mode-prompt.js +37 -0
- package/package.json +5 -4
- package/prompts/composition-dir-critic.md +7 -0
- package/prompts/composition-edges.md +8 -0
- package/prompts/composition-parser-repair-empty.md +1 -0
- package/prompts/composition-parser-repair-error.md +2 -0
- package/prompts/composition-parser.md +42 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export function computeDirectNeighborhood(matches, graph) {
|
|
2
|
+
const matchSet = new Set(matches);
|
|
3
|
+
const out = new Set(matchSet);
|
|
4
|
+
if (matchSet.size === 0)
|
|
5
|
+
return out;
|
|
6
|
+
for (const node of graph) {
|
|
7
|
+
const targets = [];
|
|
8
|
+
for (const slot of node.slots) {
|
|
9
|
+
for (const t of slot.allowedComponents ?? [])
|
|
10
|
+
targets.push(t);
|
|
11
|
+
}
|
|
12
|
+
if (matchSet.has(node.name)) {
|
|
13
|
+
for (const t of targets)
|
|
14
|
+
out.add(t);
|
|
15
|
+
}
|
|
16
|
+
for (const t of targets) {
|
|
17
|
+
if (matchSet.has(t)) {
|
|
18
|
+
out.add(node.name);
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
export function findAllAncestors(target, graph) {
|
|
26
|
+
const out = new Set([target]);
|
|
27
|
+
const parentsOf = new Map();
|
|
28
|
+
for (const node of graph) {
|
|
29
|
+
for (const slot of node.slots) {
|
|
30
|
+
for (const child of slot.allowedComponents ?? []) {
|
|
31
|
+
const list = parentsOf.get(child);
|
|
32
|
+
if (list) {
|
|
33
|
+
if (!list.includes(node.name))
|
|
34
|
+
list.push(node.name);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
parentsOf.set(child, [node.name]);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const queue = [target];
|
|
43
|
+
while (queue.length > 0) {
|
|
44
|
+
const cur = queue.shift();
|
|
45
|
+
const parents = parentsOf.get(cur);
|
|
46
|
+
if (!parents)
|
|
47
|
+
continue;
|
|
48
|
+
for (const p of parents) {
|
|
49
|
+
if (out.has(p))
|
|
50
|
+
continue;
|
|
51
|
+
out.add(p);
|
|
52
|
+
queue.push(p);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import { PALETTE } from './theme.js';
|
|
3
4
|
import { Box, Text, useStdout } from 'ink';
|
|
4
5
|
import { readFile } from 'node:fs/promises';
|
|
5
6
|
import { createReviewSessionDetail } from '../types.js';
|
|
@@ -139,7 +140,6 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
|
|
|
139
140
|
clearTimeout(previewDebounceRef.current);
|
|
140
141
|
};
|
|
141
142
|
}, []);
|
|
142
|
-
// Sync loaded session into local state
|
|
143
143
|
useEffect(() => {
|
|
144
144
|
if (loadedSession && !session) {
|
|
145
145
|
setSession(loadedSession);
|
|
@@ -173,7 +173,6 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
|
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
}, [session]);
|
|
176
|
-
// Lazy source code loading
|
|
177
176
|
useEffect(() => {
|
|
178
177
|
if (!session || !selectedId)
|
|
179
178
|
return;
|
|
@@ -195,7 +194,6 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
|
|
|
195
194
|
// Leave as null; SourcePanel shows [No source available]
|
|
196
195
|
});
|
|
197
196
|
}, [selectedId]);
|
|
198
|
-
// SIGINT handler
|
|
199
197
|
useEffect(() => {
|
|
200
198
|
const handler = () => {
|
|
201
199
|
if (Object.keys(draftsByComponentId).length > 0) {
|
|
@@ -316,7 +314,6 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
|
|
|
316
314
|
},
|
|
317
315
|
onToggleHelp: () => setShowHelp((prev) => !prev),
|
|
318
316
|
});
|
|
319
|
-
// Must be before early returns — Rules of Hooks
|
|
320
317
|
const sessionSummary = useMemo(() => sortComponentsForSidebar((session?.components ?? []).map((c) => {
|
|
321
318
|
const counts = countValidationIssues(c.originalProposal);
|
|
322
319
|
return {
|
|
@@ -334,10 +331,10 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
|
|
|
334
331
|
return _jsx(Text, { children: "Loading session..." });
|
|
335
332
|
}
|
|
336
333
|
if (sessionError) {
|
|
337
|
-
return (_jsxs(Text, { color:
|
|
334
|
+
return (_jsxs(Text, { color: PALETTE.error, children: [sessionError, '\nPress q to exit.'] }));
|
|
338
335
|
}
|
|
339
336
|
if (!session || !paths) {
|
|
340
|
-
return _jsx(Text, { color:
|
|
337
|
+
return _jsx(Text, { color: PALETTE.error, children: "Session unavailable." });
|
|
341
338
|
}
|
|
342
339
|
if (finalizedResult) {
|
|
343
340
|
return _jsx(FinalizedScreen, { result: finalizedResult });
|
|
@@ -363,10 +360,6 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
|
|
|
363
360
|
const collapsed = terminalWidth < 80;
|
|
364
361
|
const visibleCount = 20;
|
|
365
362
|
const longestName = session.components.reduce((max, c) => Math.max(max, c.name.length), 0);
|
|
366
|
-
// icon + badge + space + name + 2 border chars; min 14, max 22.
|
|
367
|
-
// The badge column is reserved (pilot R2) even when no annotation is set —
|
|
368
|
-
// see Sidebar.previewBadge — so the column width is stable as live-preview
|
|
369
|
-
// annotations flip in/out.
|
|
370
363
|
const sidebarWidth = collapsed ? 3 : Math.min(Math.max(longestName + 5, 14), 22);
|
|
371
364
|
const handleDraftSave = async (draft) => {
|
|
372
365
|
if (!selectedId || !session || !paths)
|
|
@@ -397,7 +390,6 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
|
|
|
397
390
|
type: 'draft_saved',
|
|
398
391
|
payload: { componentId: selectedId },
|
|
399
392
|
});
|
|
400
|
-
// Sync all edited proposals to pipeline DB (keep 'generated' for preview)
|
|
401
393
|
const allEdited = updatedSession.components.map((c) => c.editedProposal);
|
|
402
394
|
const syncDb = openPipelineDb();
|
|
403
395
|
try {
|
|
@@ -434,9 +426,6 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
|
|
|
434
426
|
excluded: needsReviewCount,
|
|
435
427
|
},
|
|
436
428
|
});
|
|
437
|
-
// Write all components back to DB, marking accepted as 'generated'
|
|
438
|
-
// so loadCDFComponents (push/preview) only picks up accepted ones,
|
|
439
|
-
// but loadRawComponents (editor re-entry) still finds all of them
|
|
440
429
|
const acceptedNames = new Set(session.components.filter((c) => c.status === 'accepted').map((c) => c.name));
|
|
441
430
|
const db = openPipelineDb();
|
|
442
431
|
try {
|
|
@@ -479,7 +468,7 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
|
|
|
479
468
|
}, onCancel: () => setShowQuitDialog(false) })), !showHelp && !showFinalizeDialog && !showQuitDialog && (_jsxs(Box, { flexGrow: 1, children: [_jsx(Sidebar, { components: sessionSummary, selectedId: selectedId, focused: sidebarFocused, scrollOffset: sidebarScrollOffset, visibleCount: visibleCount, onSelect: (id) => {
|
|
480
469
|
setSelectedId(id);
|
|
481
470
|
setJsonScrollOffset(0);
|
|
482
|
-
}, onScrollChange: setSidebarScrollOffset, collapsed: collapsed, width: sidebarWidth }), _jsx(Box, { flexGrow: 1, paddingLeft: 1, children: selectedDetail ? (_jsx(ComponentDetail, { component: selectedDetail, sourceCode: selectedRecord?.sourceCode ?? null, draftValue: selectedId ? (draftsByComponentId[selectedId] ?? '') : '', editMode: editMode, sourceVisible: sourceVisible, jsonScrollOffset: jsonScrollOffset, sourceScrollX: 0, sourceScrollY: 0, terminalWidth: terminalWidth, previewAnnotation: selectedRecord ? previewAnnotations[selectedRecord.name] : undefined, onSaveDraft: (value) => void handleDraftSave(value), onDiscardDraft: handleDraftDiscard, onScrollChange: setJsonScrollOffset })) : (_jsx(Text, { dimColor: true, children: "No component selected" })) })] })), _jsx(PreviewSummaryBar, { preview: previewResponse, loading: previewLoading }), previewError && _jsx(Text, { color:
|
|
471
|
+
}, onScrollChange: setSidebarScrollOffset, collapsed: collapsed, width: sidebarWidth }), _jsx(Box, { flexGrow: 1, paddingLeft: 1, children: selectedDetail ? (_jsx(ComponentDetail, { component: selectedDetail, sourceCode: selectedRecord?.sourceCode ?? null, draftValue: selectedId ? (draftsByComponentId[selectedId] ?? '') : '', editMode: editMode, sourceVisible: sourceVisible, jsonScrollOffset: jsonScrollOffset, sourceScrollX: 0, sourceScrollY: 0, terminalWidth: terminalWidth, previewAnnotation: selectedRecord ? previewAnnotations[selectedRecord.name] : undefined, onSaveDraft: (value) => void handleDraftSave(value), onDiscardDraft: handleDraftDiscard, onScrollChange: setJsonScrollOffset })) : (_jsx(Text, { dimColor: true, children: "No component selected" })) })] })), _jsx(PreviewSummaryBar, { preview: previewResponse, loading: previewLoading }), previewError && _jsx(Text, { color: PALETTE.warning, children: '⚠ Preview: ' + previewError }), saveError && _jsx(Text, { color: PALETTE.error, children: '⚠ ' + saveError }), !dialogOpen && (_jsx(StatusBar, { accepted: acceptedCount, rejected: rejectedCount, reviewed: reviewedCount, needsReview: needsReviewCount, onApproveAll: () => { }, onFinalize: () => setShowFinalizeDialog(true) }))] }));
|
|
483
472
|
}
|
|
484
473
|
function FinalizedScreen({ result, }) {
|
|
485
474
|
useImmediateInput((_input, key) => {
|
|
@@ -487,5 +476,5 @@ function FinalizedScreen({ result, }) {
|
|
|
487
476
|
process.exit(0);
|
|
488
477
|
}
|
|
489
478
|
});
|
|
490
|
-
return (_jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, gap: 1, children: [_jsx(Text, { bold: true, color:
|
|
479
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, gap: 1, children: [_jsx(Text, { bold: true, color: PALETTE.success, children: "\u2713 Finalized" }), _jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: PALETTE.success, children: "\u2713" }), _jsxs(Text, { children: [result.accepted, " accepted"] })] }), result.rejected > 0 && (_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: PALETTE.error, children: "\u2717" }), _jsxs(Text, { children: [result.rejected, " rejected"] })] })), result.excluded > 0 && (_jsxs(Box, { gap: 1, children: [_jsx(Text, { dimColor: true, children: "\u00B7" }), _jsxs(Text, { dimColor: true, children: [result.excluded, " excluded (unresolved)"] })] }))] }), _jsx(Text, { dimColor: true, children: "Decisions saved. Ready for the next step." }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "[Enter / q] Exit" }) })] }));
|
|
491
480
|
}
|
|
@@ -21,10 +21,6 @@ type RenderedLine = {
|
|
|
21
21
|
} | {
|
|
22
22
|
kind: 'blank';
|
|
23
23
|
};
|
|
24
|
-
/**
|
|
25
|
-
* Flatten the component rationale into a list of rendered lines so scrollOffset
|
|
26
|
-
* slicing matches what the operator sees.
|
|
27
|
-
*/
|
|
28
24
|
export declare function renderComponentRationaleLines(data: ComponentRationale, innerWidth: number): RenderedLine[];
|
|
29
25
|
export declare function ComponentRationalePanel({ data, scrollOffset, width, height, active, }: ComponentRationalePanelProps): React.ReactElement;
|
|
30
26
|
export {};
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { PALETTE } from '../theme.js';
|
|
2
3
|
import { Box, Text } from 'ink';
|
|
3
4
|
const PLACEHOLDER = '(no rationale captured)';
|
|
4
|
-
/**
|
|
5
|
-
* Word-wrap a paragraph to fit `innerWidth` columns. Mirrors the helper in
|
|
6
|
-
* RationalePanel.tsx so wrapping is identical across both panels.
|
|
7
|
-
*/
|
|
8
5
|
function wrapText(text, innerWidth) {
|
|
9
6
|
if (!text)
|
|
10
7
|
return [''];
|
|
@@ -51,10 +48,6 @@ function wrapText(text, innerWidth) {
|
|
|
51
48
|
lines.push(current);
|
|
52
49
|
return lines.length > 0 ? lines : [''];
|
|
53
50
|
}
|
|
54
|
-
/**
|
|
55
|
-
* Flatten the component rationale into a list of rendered lines so scrollOffset
|
|
56
|
-
* slicing matches what the operator sees.
|
|
57
|
-
*/
|
|
58
51
|
export function renderComponentRationaleLines(data, innerWidth) {
|
|
59
52
|
const out = [];
|
|
60
53
|
const pushSection = (heading, body) => {
|
|
@@ -65,10 +58,6 @@ export function renderComponentRationaleLines(data, innerWidth) {
|
|
|
65
58
|
}
|
|
66
59
|
out.push({ kind: 'blank' });
|
|
67
60
|
};
|
|
68
|
-
// "Description" section shows the human-facing component description.
|
|
69
|
-
// The `descriptionRationale` (WHY the component was classified this way)
|
|
70
|
-
// is appended as a small "why" line so the operator can see the LLM's
|
|
71
|
-
// reasoning without leaving the panel.
|
|
72
61
|
out.push({ kind: 'heading', text: 'Description' });
|
|
73
62
|
const descBody = data.description && data.description.trim().length > 0 ? data.description : PLACEHOLDER;
|
|
74
63
|
for (const ln of wrapText(descBody, Math.max(1, innerWidth - 2))) {
|
|
@@ -116,18 +105,17 @@ export function ComponentRationalePanel({ data, scrollOffset, width, height, act
|
|
|
116
105
|
const innerWidth = Math.max(1, width - 2);
|
|
117
106
|
const all = renderComponentRationaleLines(data, innerWidth);
|
|
118
107
|
const totalLines = all.length;
|
|
119
|
-
// Reserve one line at the bottom for the legend.
|
|
120
108
|
const contentHeight = Math.max(1, height - 1);
|
|
121
109
|
const visible = all.slice(scrollOffset, scrollOffset + contentHeight);
|
|
122
110
|
const overflowed = totalLines > contentHeight;
|
|
123
111
|
const visibleStart = totalLines === 0 ? 0 : scrollOffset + 1;
|
|
124
112
|
const visibleEnd = Math.min(totalLines, scrollOffset + contentHeight);
|
|
125
|
-
return (_jsxs(Box, { flexDirection: "column", width: width, height: height + 2, borderStyle: "single", borderColor: active ?
|
|
113
|
+
return (_jsxs(Box, { flexDirection: "column", width: width, height: height + 2, borderStyle: "single", borderColor: active ? PALETTE.inverse : undefined, children: [_jsx(Box, { children: _jsx(Text, { bold: true, dimColor: !active, children: `Component rationale: ${data.name}` }) }), visible.map((line, i) => {
|
|
126
114
|
if (line.kind === 'blank') {
|
|
127
115
|
return (_jsx(Box, { children: _jsx(Text, { children: " " }) }, i));
|
|
128
116
|
}
|
|
129
117
|
if (line.kind === 'heading') {
|
|
130
|
-
return (_jsx(Box, { children: _jsx(Text, { bold: true, color:
|
|
118
|
+
return (_jsx(Box, { children: _jsx(Text, { bold: true, color: PALETTE.info, dimColor: !active, children: line.text }) }, i));
|
|
131
119
|
}
|
|
132
120
|
if (line.kind === 'list-name') {
|
|
133
121
|
return (_jsxs(Box, { children: [_jsx(Text, { children: ' - ' }), _jsx(Text, { bold: true, dimColor: !active, children: line.text }), line.sublabel ? _jsx(Text, { dimColor: true, children: ' ' + line.sublabel }) : null] }, i));
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
|
-
* Optional; when omitted, the FieldEditor renders without rationale/source
|
|
4
|
-
* affordances (backwards-compatible with mounts that pre-date Feature 1). */
|
|
2
|
+
import { findSlotCycles, type ComponentSlotInfo } from '../../../cycle-detection.js';
|
|
5
3
|
export type PropMetadata = {
|
|
6
4
|
rationale?: string | null;
|
|
7
5
|
sourceStartLine?: number | null;
|
|
@@ -19,50 +17,43 @@ type FieldEditorProps = {
|
|
|
19
17
|
value: string;
|
|
20
18
|
width: number;
|
|
21
19
|
height: number;
|
|
22
|
-
/**
|
|
23
|
-
* When false, the editor is mounted but does not consume keystrokes.
|
|
24
|
-
* Used by callers (e.g. GenerateReviewStep) that toggle focus between
|
|
25
|
-
* a sidebar and this editor — the editor stays visible while the sidebar
|
|
26
|
-
* has the keyboard.
|
|
27
|
-
*/
|
|
28
20
|
active?: boolean;
|
|
29
21
|
onChange: (value: string) => void;
|
|
30
22
|
onSave: () => void;
|
|
31
23
|
onDiscard: () => void;
|
|
32
|
-
/**
|
|
33
|
-
* Called when the user requests to exit the panel from row-level (Esc).
|
|
34
|
-
* Distinct from onDiscard, which drops pending edits without changing focus.
|
|
35
|
-
* Callers that embed FieldEditor inside a sidebar+panel layout wire this to
|
|
36
|
-
* return focus to the sidebar (e.g. setSidebarFocused(true)). When omitted,
|
|
37
|
-
* row-level Esc falls back to onDiscard for backward compatibility.
|
|
38
|
-
*/
|
|
39
24
|
onExit?: () => void;
|
|
40
|
-
/** Feature 1: source code + LLM rationale metadata. Optional. */
|
|
41
25
|
metadata?: FieldEditorMetadata;
|
|
42
|
-
/**
|
|
43
|
-
* When provided, the parent owns the prop-rationale panel: pressing `i`
|
|
44
|
-
* inside FieldEditor calls this callback (subject to text-entry gating)
|
|
45
|
-
* instead of toggling internal state. The panel is rendered by the parent
|
|
46
|
-
* in place of FieldEditor — FieldEditor no longer renders its own panel.
|
|
47
|
-
*/
|
|
48
26
|
onTogglePropRationale?: () => void;
|
|
49
|
-
|
|
50
|
-
* When provided, the parent owns the component-rationale panel: pressing
|
|
51
|
-
* `I` (uppercase) calls this callback (subject to text-entry gating).
|
|
52
|
-
*/
|
|
27
|
+
propRationaleKey?: string;
|
|
53
28
|
onToggleComponentRationale?: () => void;
|
|
54
|
-
|
|
55
|
-
* When provided, the parent owns the source-view panel: pressing `s`
|
|
56
|
-
* calls this callback (subject to text-entry gating). FieldEditor will not
|
|
57
|
-
* render its own source panel in that case.
|
|
58
|
-
*/
|
|
29
|
+
componentRationaleKey?: string;
|
|
59
30
|
onToggleSourceExternal?: () => void;
|
|
60
|
-
/**
|
|
61
|
-
* Reports text-entry-active state changes to the parent so the parent can
|
|
62
|
-
* gate top-level keybinds (i/I/s) against literal keystrokes inside
|
|
63
|
-
* description editors, string default editors, and value-list text entry.
|
|
64
|
-
*/
|
|
65
31
|
onTextEntryActiveChange?: (active: boolean) => void;
|
|
32
|
+
projectSlotGraph?: ComponentSlotInfo[];
|
|
33
|
+
currentComponentName?: string;
|
|
34
|
+
onDirtyChange?: (isDirty: boolean) => void;
|
|
35
|
+
discardTrigger?: number;
|
|
36
|
+
initialFocusTarget?: {
|
|
37
|
+
kind: 'prop' | 'slot';
|
|
38
|
+
name: string;
|
|
39
|
+
};
|
|
66
40
|
};
|
|
67
|
-
export declare function
|
|
41
|
+
export declare function simulateGraphWithCandidate(projectSlotGraph: ComponentSlotInfo[], selfName: string, currentSlots: {
|
|
42
|
+
name: string;
|
|
43
|
+
allowedComponents: string[];
|
|
44
|
+
}[], targetSlotName: string, candidate: string): ComponentSlotInfo[];
|
|
45
|
+
export declare function introducesNewCycle(before: ReturnType<typeof findSlotCycles>, next: ReturnType<typeof findSlotCycles>): boolean;
|
|
46
|
+
export declare function computeAllowedComponentCandidates(projectSlotGraph: ComponentSlotInfo[], selfName: string, currentSlots: {
|
|
47
|
+
name: string;
|
|
48
|
+
allowedComponents: string[];
|
|
49
|
+
}[], targetSlotName: string): string[];
|
|
50
|
+
export declare function simulateGraphWithReplacement(projectSlotGraph: ComponentSlotInfo[], selfName: string, currentSlots: {
|
|
51
|
+
name: string;
|
|
52
|
+
allowedComponents: string[];
|
|
53
|
+
}[], targetSlotName: string, replaceIndex: number, candidate: string): ComponentSlotInfo[];
|
|
54
|
+
export declare function computeAllowedComponentReplacementCandidates(projectSlotGraph: ComponentSlotInfo[], selfName: string, currentSlots: {
|
|
55
|
+
name: string;
|
|
56
|
+
allowedComponents: string[];
|
|
57
|
+
}[], targetSlotName: string, replaceIndex: number): string[];
|
|
58
|
+
export declare function FieldEditor({ value, width, height, active, onChange, onSave, onDiscard, onExit, metadata, onTogglePropRationale, propRationaleKey, onToggleComponentRationale, componentRationaleKey, onToggleSourceExternal, onTextEntryActiveChange, projectSlotGraph, currentComponentName, onDirtyChange, discardTrigger, initialFocusTarget, }: FieldEditorProps): React.ReactElement;
|
|
68
59
|
export {};
|