ctxr-cli 0.32.0 → 0.34.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 +15 -1
- package/dist/commands/archive.d.ts +5 -4
- package/dist/commands/archive.d.ts.map +1 -1
- package/dist/commands/archive.js +7 -7
- package/dist/commands/archive.js.map +1 -1
- package/dist/commands/catalog-show.d.ts +8 -0
- package/dist/commands/catalog-show.d.ts.map +1 -1
- package/dist/commands/catalog-show.js +29 -2
- package/dist/commands/catalog-show.js.map +1 -1
- package/dist/commands/context-gather.d.ts.map +1 -1
- package/dist/commands/context-gather.js +3 -2
- package/dist/commands/context-gather.js.map +1 -1
- package/dist/commands/doctor.d.ts +5 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +4 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/graph-build.d.ts +4 -1
- package/dist/commands/graph-build.d.ts.map +1 -1
- package/dist/commands/graph-build.js +14 -5
- package/dist/commands/graph-build.js.map +1 -1
- package/dist/commands/land.d.ts +27 -7
- package/dist/commands/land.d.ts.map +1 -1
- package/dist/commands/land.js +307 -32
- package/dist/commands/land.js.map +1 -1
- package/dist/commands/publish-gather.d.ts.map +1 -1
- package/dist/commands/publish-gather.js +2 -3
- package/dist/commands/publish-gather.js.map +1 -1
- package/dist/commands/review-list.d.ts +19 -5
- package/dist/commands/review-list.d.ts.map +1 -1
- package/dist/commands/review-list.js +55 -6
- package/dist/commands/review-list.js.map +1 -1
- package/dist/commands/rollup-gather.d.ts.map +1 -1
- package/dist/commands/rollup-gather.js +2 -3
- package/dist/commands/rollup-gather.js.map +1 -1
- package/dist/commands/second-opinion.d.ts +33 -0
- package/dist/commands/second-opinion.d.ts.map +1 -0
- package/dist/commands/second-opinion.js +56 -0
- package/dist/commands/second-opinion.js.map +1 -0
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +4 -0
- package/dist/commands/serve.js.map +1 -1
- package/dist/commands/session-discard.d.ts +18 -0
- package/dist/commands/session-discard.d.ts.map +1 -0
- package/dist/commands/session-discard.js +31 -0
- package/dist/commands/session-discard.js.map +1 -0
- package/dist/commands/session-list.d.ts +17 -6
- package/dist/commands/session-list.d.ts.map +1 -1
- package/dist/commands/session-list.js +31 -11
- package/dist/commands/session-list.js.map +1 -1
- package/dist/commands/session-rebase.d.ts +18 -0
- package/dist/commands/session-rebase.d.ts.map +1 -0
- package/dist/commands/session-rebase.js +43 -0
- package/dist/commands/session-rebase.js.map +1 -0
- package/dist/commands/session-start.d.ts +8 -0
- package/dist/commands/session-start.d.ts.map +1 -1
- package/dist/commands/session-start.js +45 -5
- package/dist/commands/session-start.js.map +1 -1
- package/dist/commands/session-status.d.ts +17 -0
- package/dist/commands/session-status.d.ts.map +1 -0
- package/dist/commands/session-status.js +38 -0
- package/dist/commands/session-status.js.map +1 -0
- package/dist/commands/session-submit.d.ts +23 -0
- package/dist/commands/session-submit.d.ts.map +1 -0
- package/dist/commands/session-submit.js +42 -0
- package/dist/commands/session-submit.js.map +1 -0
- package/dist/commands/shared-stores-status.d.ts +24 -0
- package/dist/commands/shared-stores-status.d.ts.map +1 -0
- package/dist/commands/shared-stores-status.js +51 -0
- package/dist/commands/shared-stores-status.js.map +1 -0
- package/dist/commands/shared-stores-sync.d.ts +27 -0
- package/dist/commands/shared-stores-sync.d.ts.map +1 -0
- package/dist/commands/shared-stores-sync.js +115 -0
- package/dist/commands/shared-stores-sync.js.map +1 -0
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +2 -4
- package/dist/commands/verify.js.map +1 -1
- package/dist/config/schema.d.ts +16 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +32 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/core/agents-doc.d.ts +10 -0
- package/dist/core/agents-doc.d.ts.map +1 -1
- package/dist/core/agents-doc.js +26 -1
- package/dist/core/agents-doc.js.map +1 -1
- package/dist/core/approval/decision.d.ts +39 -1
- package/dist/core/approval/decision.d.ts.map +1 -1
- package/dist/core/approval/decision.js +53 -6
- package/dist/core/approval/decision.js.map +1 -1
- package/dist/core/approval/session-group.d.ts +156 -0
- package/dist/core/approval/session-group.d.ts.map +1 -0
- package/dist/core/approval/session-group.js +359 -0
- package/dist/core/approval/session-group.js.map +1 -0
- package/dist/core/approval/session-marker.d.ts +79 -0
- package/dist/core/approval/session-marker.d.ts.map +1 -0
- package/dist/core/approval/session-marker.js +146 -0
- package/dist/core/approval/session-marker.js.map +1 -0
- package/dist/core/approval/store-forges.d.ts +15 -0
- package/dist/core/approval/store-forges.d.ts.map +1 -0
- package/dist/core/approval/store-forges.js +33 -0
- package/dist/core/approval/store-forges.js.map +1 -0
- package/dist/core/browse/approve.d.ts +8 -0
- package/dist/core/browse/approve.d.ts.map +1 -1
- package/dist/core/browse/approve.js +366 -48
- package/dist/core/browse/approve.js.map +1 -1
- package/dist/core/browse/link-resolver.d.ts +9 -4
- package/dist/core/browse/link-resolver.d.ts.map +1 -1
- package/dist/core/browse/link-resolver.js +12 -7
- package/dist/core/browse/link-resolver.js.map +1 -1
- package/dist/core/browse/review.d.ts +5 -0
- package/dist/core/browse/review.d.ts.map +1 -1
- package/dist/core/browse/review.js +8 -0
- package/dist/core/browse/review.js.map +1 -1
- package/dist/core/checks/integrity-checks.d.ts.map +1 -1
- package/dist/core/checks/integrity-checks.js +7 -1
- package/dist/core/checks/integrity-checks.js.map +1 -1
- package/dist/core/checks/manifest.d.ts.map +1 -1
- package/dist/core/checks/manifest.js +2 -0
- package/dist/core/checks/manifest.js.map +1 -1
- package/dist/core/checks/shared-stores-checks.d.ts +17 -0
- package/dist/core/checks/shared-stores-checks.d.ts.map +1 -0
- package/dist/core/checks/shared-stores-checks.js +84 -0
- package/dist/core/checks/shared-stores-checks.js.map +1 -0
- package/dist/core/errors.d.ts +17 -0
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +21 -0
- package/dist/core/errors.js.map +1 -1
- package/dist/core/forge/github.d.ts +14 -0
- package/dist/core/forge/github.d.ts.map +1 -1
- package/dist/core/forge/github.js +17 -0
- package/dist/core/forge/github.js.map +1 -1
- package/dist/core/git/fast-forward.d.ts +23 -0
- package/dist/core/git/fast-forward.d.ts.map +1 -0
- package/dist/core/git/fast-forward.js +38 -0
- package/dist/core/git/fast-forward.js.map +1 -0
- package/dist/core/git/repo.d.ts +11 -0
- package/dist/core/git/repo.d.ts.map +1 -1
- package/dist/core/git/repo.js +25 -0
- package/dist/core/git/repo.js.map +1 -1
- package/dist/core/graph/model.d.ts +27 -0
- package/dist/core/graph/model.d.ts.map +1 -1
- package/dist/core/graph/model.js +68 -2
- package/dist/core/graph/model.js.map +1 -1
- package/dist/core/graph/persist.d.ts.map +1 -1
- package/dist/core/graph/persist.js +3 -2
- package/dist/core/graph/persist.js.map +1 -1
- package/dist/core/mcp/sessions.d.ts +11 -14
- package/dist/core/mcp/sessions.d.ts.map +1 -1
- package/dist/core/mcp/sessions.js +23 -43
- package/dist/core/mcp/sessions.js.map +1 -1
- package/dist/core/notes/list.d.ts.map +1 -1
- package/dist/core/notes/list.js +5 -0
- package/dist/core/notes/list.js.map +1 -1
- package/dist/core/reconcile.d.ts.map +1 -1
- package/dist/core/reconcile.js +2 -1
- package/dist/core/reconcile.js.map +1 -1
- package/dist/core/retrieval/pass.d.ts.map +1 -1
- package/dist/core/retrieval/pass.js +5 -4
- package/dist/core/retrieval/pass.js.map +1 -1
- package/dist/core/rollup.d.ts.map +1 -1
- package/dist/core/rollup.js +2 -3
- package/dist/core/rollup.js.map +1 -1
- package/dist/core/root.d.ts.map +1 -1
- package/dist/core/root.js +33 -2
- package/dist/core/root.js.map +1 -1
- package/dist/core/second-opinion/environment.d.ts +21 -0
- package/dist/core/second-opinion/environment.d.ts.map +1 -0
- package/dist/core/second-opinion/environment.js +70 -0
- package/dist/core/second-opinion/environment.js.map +1 -0
- package/dist/core/second-opinion/judge.d.ts +29 -0
- package/dist/core/second-opinion/judge.d.ts.map +1 -0
- package/dist/core/second-opinion/judge.js +55 -0
- package/dist/core/second-opinion/judge.js.map +1 -0
- package/dist/core/second-opinion/launch.d.ts +16 -0
- package/dist/core/second-opinion/launch.d.ts.map +1 -0
- package/dist/core/second-opinion/launch.js +75 -0
- package/dist/core/second-opinion/launch.js.map +1 -0
- package/dist/core/second-opinion/lineup.d.ts +82 -0
- package/dist/core/second-opinion/lineup.d.ts.map +1 -0
- package/dist/core/second-opinion/lineup.js +113 -0
- package/dist/core/second-opinion/lineup.js.map +1 -0
- package/dist/core/second-opinion/modes.d.ts +98 -0
- package/dist/core/second-opinion/modes.d.ts.map +1 -0
- package/dist/core/second-opinion/modes.js +224 -0
- package/dist/core/second-opinion/modes.js.map +1 -0
- package/dist/core/second-opinion/prompts.d.ts +18 -0
- package/dist/core/second-opinion/prompts.d.ts.map +1 -0
- package/dist/core/second-opinion/prompts.js +65 -0
- package/dist/core/second-opinion/prompts.js.map +1 -0
- package/dist/core/session/commit.d.ts +29 -0
- package/dist/core/session/commit.d.ts.map +1 -0
- package/dist/core/session/commit.js +22 -0
- package/dist/core/session/commit.js.map +1 -0
- package/dist/core/session/discard.d.ts +24 -0
- package/dist/core/session/discard.d.ts.map +1 -0
- package/dist/core/session/discard.js +68 -0
- package/dist/core/session/discard.js.map +1 -0
- package/dist/core/session/list.d.ts +48 -0
- package/dist/core/session/list.d.ts.map +1 -0
- package/dist/core/session/list.js +55 -0
- package/dist/core/session/list.js.map +1 -0
- package/dist/core/session/rebase.d.ts +34 -0
- package/dist/core/session/rebase.d.ts.map +1 -0
- package/dist/core/session/rebase.js +87 -0
- package/dist/core/session/rebase.js.map +1 -0
- package/dist/core/session/remote.d.ts +80 -0
- package/dist/core/session/remote.d.ts.map +1 -0
- package/dist/core/session/remote.js +102 -0
- package/dist/core/session/remote.js.map +1 -0
- package/dist/core/session/resolve.d.ts +41 -0
- package/dist/core/session/resolve.d.ts.map +1 -0
- package/dist/core/session/resolve.js +109 -0
- package/dist/core/session/resolve.js.map +1 -0
- package/dist/core/session/status.d.ts +47 -0
- package/dist/core/session/status.d.ts.map +1 -0
- package/dist/core/session/status.js +55 -0
- package/dist/core/session/status.js.map +1 -0
- package/dist/core/session/submit.d.ts +67 -0
- package/dist/core/session/submit.d.ts.map +1 -0
- package/dist/core/session/submit.js +254 -0
- package/dist/core/session/submit.js.map +1 -0
- package/dist/core/shared-stores-location.d.ts +17 -0
- package/dist/core/shared-stores-location.d.ts.map +1 -0
- package/dist/core/shared-stores-location.js +22 -0
- package/dist/core/shared-stores-location.js.map +1 -0
- package/dist/core/shared-stores.d.ts +69 -0
- package/dist/core/shared-stores.d.ts.map +1 -0
- package/dist/core/shared-stores.js +100 -0
- package/dist/core/shared-stores.js.map +1 -0
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +14 -10
- package/dist/core/skills.js.map +1 -1
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +122 -6
- package/dist/run.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/templates/agents/shared-stores.md +11 -0
- package/templates/approve/copies-missing.md +1 -0
- package/templates/approve/elsewhere-heading.md +1 -0
- package/templates/approve/elsewhere-intro.md +1 -0
- package/templates/approve/homed-elsewhere.md +1 -0
- package/templates/approve/not-decider.md +1 -0
- package/templates/approve/part-heading.md +1 -0
- package/templates/approve/parts-changed.md +1 -0
- package/templates/approve/session-decision-note.md +1 -0
- package/templates/approve/session-intro.md +1 -0
- package/templates/approve/session-no-decision.md +1 -0
- package/templates/approve/store-unreachable.md +1 -0
- package/templates/land/resolver.md +2 -0
- package/templates/second-opinion/poll-answer.md +7 -0
- package/templates/second-opinion/taste-panel.md +14 -0
- package/templates/session/pages/bare-route.md +2 -0
- package/templates/session/pages/block.md +8 -0
- package/templates/session/pages/condition-preview.md +1 -0
- package/templates/session/pages/condition.md +1 -0
- package/templates/session/pages/moved.md +1 -0
- package/templates/session/pages/stops-working.md +1 -0
- package/templates/session/pages/table-head-preview.md +2 -0
- package/templates/session/pages/table-head.md +2 -0
- package/templates/skills/ctxr-capture-circleback/sweep.mjs +33 -6
- package/templates/skills/ctxr-capture-circleback.md +9 -6
- package/templates/skills/ctxr-connection-finding.md +4 -1
- package/templates/skills/ctxr-land.md +26 -7
- package/templates/skills/ctxr-placement.md +10 -0
- package/templates/skills/ctxr-rollup.md +3 -0
- package/templates/skills/ctxr-second-opinion.md +52 -36
- package/templates/skills/ctxr-session-lifecycle.md +60 -33
- package/templates/skills/ctxr-submit.md +65 -56
- package/templates/skills/ctxr-second-opinion/run.mjs +0 -542
- /package/templates/{skills/ctxr-second-opinion → second-opinion}/critic-contract.md +0 -0
- /package/templates/{skills/ctxr-second-opinion → second-opinion}/lenses.md +0 -0
- /package/templates/{skills/ctxr-second-opinion → second-opinion}/personas/architect.md +0 -0
- /package/templates/{skills/ctxr-second-opinion → second-opinion}/personas/pragmatist.md +0 -0
- /package/templates/{skills/ctxr-second-opinion → second-opinion}/personas/skeptic.md +0 -0
|
@@ -73,7 +73,17 @@ function recentMeetings() {
|
|
|
73
73
|
return meetings.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
/**
|
|
76
|
+
/** Where the runner keeps its review worktree: a fixed path, so a later run finds and clears it. */
|
|
77
|
+
function reviewWorktreePath(root) {
|
|
78
|
+
return path.join(tmpdir(), `ctxr-capture-circleback-${path.basename(root)}`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Circleback ids already in the default branch, in each open pull request's diff, and in the store's other
|
|
83
|
+
* local worktrees, tracked or not: an agent's session that captured a meeting but has not pushed yet is work
|
|
84
|
+
* in flight, not a gap. The runner's own review worktree is left out, or what an earlier run rendered there
|
|
85
|
+
* would count as present and a meeting whose pull request was closed unmerged could never be captured again.
|
|
86
|
+
*/
|
|
77
87
|
function presence(root, settings) {
|
|
78
88
|
run('git', ['fetch', '-q', 'origin'], { cwd: root });
|
|
79
89
|
const onMain = new Set(
|
|
@@ -87,7 +97,19 @@ function presence(root, settings) {
|
|
|
87
97
|
const diff = run('gh', ['pr', 'diff', String(pr.number)], { cwd: root, check: false });
|
|
88
98
|
for (const match of diff.matchAll(/circleback\/([A-Za-z0-9_-]+)/g)) if (!inPullRequest.has(match[1])) inPullRequest.set(match[1], pr.number);
|
|
89
99
|
}
|
|
90
|
-
|
|
100
|
+
const inWorktree = new Map();
|
|
101
|
+
const own = path.resolve(reviewWorktreePath(root));
|
|
102
|
+
for (const entry of run('git', ['worktree', 'list', '--porcelain'], { cwd: root, check: false }).split('\n')) {
|
|
103
|
+
if (!entry.startsWith('worktree ')) continue;
|
|
104
|
+
const worktree = entry.slice('worktree '.length);
|
|
105
|
+
if (path.resolve(worktree) === own) continue;
|
|
106
|
+
const found = run('git', ['grep', '--untracked', '-I', '-h', '-o', '-E', 'circleback/[A-Za-z0-9_-]+'], { cwd: worktree, check: false });
|
|
107
|
+
for (const match of found.split('\n').filter(Boolean)) {
|
|
108
|
+
const id = match.slice('circleback/'.length);
|
|
109
|
+
if (!onMain.has(id) && !inWorktree.has(id)) inWorktree.set(id, worktree);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return { onMain, inPullRequest, inWorktree };
|
|
91
113
|
}
|
|
92
114
|
|
|
93
115
|
/**
|
|
@@ -96,7 +118,7 @@ function presence(root, settings) {
|
|
|
96
118
|
* first, because an agent running unattended may not be allowed to delete it.
|
|
97
119
|
*/
|
|
98
120
|
function prepareWorktree(root, settings) {
|
|
99
|
-
const worktree =
|
|
121
|
+
const worktree = reviewWorktreePath(root);
|
|
100
122
|
run('git', ['worktree', 'remove', '--force', worktree], { cwd: root, check: false });
|
|
101
123
|
rmSync(worktree, { recursive: true, force: true });
|
|
102
124
|
run('git', ['worktree', 'prune'], { cwd: root });
|
|
@@ -171,7 +193,7 @@ function main() {
|
|
|
171
193
|
const settings = JSON.parse(readFileSync(path.join(HERE, 'settings.json'), 'utf8'));
|
|
172
194
|
const root = storeRoot();
|
|
173
195
|
const otherTags = new Set(settings.other_tags);
|
|
174
|
-
const { onMain, inPullRequest } = presence(root, settings);
|
|
196
|
+
const { onMain, inPullRequest, inWorktree } = presence(root, settings);
|
|
175
197
|
const meetings = recentMeetings();
|
|
176
198
|
const now = Date.now();
|
|
177
199
|
const ageDays = (meeting) => (now - Date.parse(meeting.createdAt)) / 86_400_000;
|
|
@@ -181,13 +203,17 @@ function main() {
|
|
|
181
203
|
const untagged = [];
|
|
182
204
|
const multiStore = [];
|
|
183
205
|
const declined = [];
|
|
206
|
+
const unpushed = [];
|
|
184
207
|
let present = 0;
|
|
185
208
|
for (const meeting of meetings) {
|
|
186
209
|
const tags = tagNames(meeting);
|
|
187
210
|
const isLocked = (meeting.notes ?? '').includes(LOCKED_NOTICE);
|
|
188
|
-
const here = onMain.has(meeting.id) || inPullRequest.has(meeting.id);
|
|
211
|
+
const here = onMain.has(meeting.id) || inPullRequest.has(meeting.id) || inWorktree.has(meeting.id);
|
|
189
212
|
const others = [...tags].filter((tag) => otherTags.has(tag));
|
|
190
213
|
if (tags.has(settings.tag) && here) present += 1;
|
|
214
|
+
if (tags.has(settings.tag) && inWorktree.has(meeting.id) && !onMain.has(meeting.id) && !inPullRequest.has(meeting.id)) {
|
|
215
|
+
unpushed.push(`${line(meeting)} (in ${inWorktree.get(meeting.id)})`);
|
|
216
|
+
}
|
|
191
217
|
if (tags.size === 0 && !here) untagged.push(`${line(meeting)}${isLocked ? ' (locked)' : ageDays(meeting) >= URGENT_DAYS ? ' (URGENT, locks soon)' : ''}`);
|
|
192
218
|
if (tags.has(settings.tag) && others.length > 0) multiStore.push(`${line(meeting)} (also ${others.join(', ')})`);
|
|
193
219
|
if (tags.has(settings.decline_tag) && ageDays(meeting) <= DECLINE_REPORT_DAYS) declined.push(line(meeting));
|
|
@@ -197,7 +223,7 @@ function main() {
|
|
|
197
223
|
}
|
|
198
224
|
|
|
199
225
|
const report = [
|
|
200
|
-
`Store tag \`${settings.tag}\`. Meetings in the last ${LOOKBACK_DAYS} days: ${meetings.length}. Already in this store
|
|
226
|
+
`Store tag \`${settings.tag}\`. Meetings in the last ${LOOKBACK_DAYS} days: ${meetings.length}. Already in this store, an open pull request or a local worktree: ${present}.`,
|
|
201
227
|
...section('TO CAPTURE — date | id | title', owed.map(line)),
|
|
202
228
|
];
|
|
203
229
|
if (owed.length > 0) {
|
|
@@ -214,6 +240,7 @@ function main() {
|
|
|
214
240
|
}
|
|
215
241
|
}
|
|
216
242
|
report.push(
|
|
243
|
+
...section('UNPUSHED — captured in a local worktree but not on the default branch or in an open pull request; land that work', unpushed),
|
|
217
244
|
...section(`LOCKED — tagged \`${settings.tag}\`, never captured, no longer readable in full`, locked),
|
|
218
245
|
...section('UNTAGGED', untagged),
|
|
219
246
|
...section('TAGGED FOR MORE THAN ONE STORE', multiStore),
|
|
@@ -17,12 +17,13 @@ It needs Circleback's command-line tool (`cb`) signed in, plus `git` and `gh`. A
|
|
|
17
17
|
start and puts its report in your prompt; then skip to step 2.
|
|
18
18
|
|
|
19
19
|
The runner reads every meeting from the last 35 days with its tags, and compares them with this store's default
|
|
20
|
-
branch
|
|
21
|
-
|
|
22
|
-
full.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
branch, its open pull requests, and the store's other local worktrees, uncommitted files included. A meeting is owed
|
|
21
|
+
when it carries this store's tag, does not carry the decline tag, carries no other store's tag, is in none of those
|
|
22
|
+
places, and can still be read in full. A meeting found only in a local worktree is someone's capture in flight: it
|
|
23
|
+
is listed under UNPUSHED rather than captured again. For each owed meeting it prepares a review-branch worktree and
|
|
24
|
+
writes the record into `__INBOX_PATH__` there: the meeting's metadata and attendees, Circleback's action items and
|
|
25
|
+
summary (marked as the service's derivation), and the transcript verbatim, with `source_type` and `source_id`
|
|
26
|
+
stamped. It never writes the recording URL, which is a signed, expiring link and so a credential.
|
|
26
27
|
|
|
27
28
|
The report is authoritative. Do not work the list out again yourself, and do not rebuild the files it wrote. If it
|
|
28
29
|
prints `COLLECTION FAILED`, report that line and stop.
|
|
@@ -52,6 +53,8 @@ Give the counts (retrieved, already present), the pull request link, and the run
|
|
|
52
53
|
they are:
|
|
53
54
|
|
|
54
55
|
- **LOCKED**: tagged for this store but no longer readable in full, so it cannot be captured.
|
|
56
|
+
- **UNPUSHED**: captured in a local worktree but not yet on the default branch or in a pull request. That work
|
|
57
|
+
needs landing; nothing here captures it again.
|
|
55
58
|
- **UNTAGGED**, **TAGGED FOR MORE THAN ONE STORE** and **DECLINED IN THE LAST 8 DAYS**, when the runner prints them.
|
|
56
59
|
|
|
57
60
|
If nothing was owed and every section is empty, say "Nothing missing".
|
|
@@ -13,5 +13,8 @@ to synthesize an entity's current state from its sources, use `ctxr-rollup`.
|
|
|
13
13
|
5. To find the most-referenced notes, run `ctxr graph query hubs`; to find unlinked ones,
|
|
14
14
|
`ctxr graph query orphans`; `ctxr graph query clusters` and `ctxr graph query bridges` show the
|
|
15
15
|
cluster structure and the notes that span it.
|
|
16
|
-
6.
|
|
16
|
+
6. When the store mounts other stores under `shared/`, the graph carries their notes under `shared/<name>/`.
|
|
17
|
+
Link from this store into a mount with a path link, such as `[[shared/<name>/<path>]]`.
|
|
18
|
+
A filename link resolves only inside the store that holds the note. A note in a mount never resolves a link back into this store.
|
|
19
|
+
7. Report what the graph says — it enumerates structure and ranks nothing; judgment about which links
|
|
17
20
|
matter is yours.
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
The land half of the session lifecycle, after review. `ctxr-submit` is the other half; `ctxr-session-lifecycle`
|
|
2
2
|
covers what surrounds both and is not repeated here. `ctxr land` does the landing. This skill decides when to run it.
|
|
3
3
|
|
|
4
|
+
For a pull request on a mounted store under `shared/<name>`, run every step from that mount, not from this store.
|
|
5
|
+
Why: the mount's own `contexture.yaml` names its approval rules and its canonical clone.
|
|
6
|
+
A pull request that is one part of a session of this store is different: land it from this store, with the
|
|
7
|
+
whole session, as step 4 says. Why: this store lands the session's parts in order.
|
|
8
|
+
|
|
4
9
|
1. Name the target explicitly — a branch name or a pull-request number — rather than relying on whichever
|
|
5
10
|
checkout you happen to be standing in: that checkout is as likely to be the canonical clone on
|
|
6
11
|
`__DEFAULT_BRANCH__`, which has no session to infer, as the session itself. Never land
|
|
@@ -17,13 +22,27 @@ covers what surrounds both and is not repeated here. `ctxr land` does the landin
|
|
|
17
22
|
approval given earlier in this conversation satisfies this. Do not ask twice.
|
|
18
23
|
- When the row says `changes-requested` or `needs-reapproval`, say so before you ask.
|
|
19
24
|
Why: a decider asked for a change, or has not seen the current version.
|
|
20
|
-
4. Land.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
4. Land.
|
|
26
|
+
- A pull request with an approval from the page: run `ctxr land <number>`.
|
|
27
|
+
- A pull request with an explicit go: run `ctxr land <number> --confirm`. Use `--confirm` only after that go.
|
|
28
|
+
Why: the flag tells the command that a person agreed.
|
|
29
|
+
- A session with an approval from the page: run `ctxr land --pending` from this store. Why: it lands each
|
|
30
|
+
approved session of this store, and it reads the decision itself.
|
|
31
|
+
- A session with an explicit go: run `ctxr land --session <session> --confirm` from this store. `<session>`
|
|
32
|
+
is this store's session worktree name. Why: the command lands the parts in mounted stores first, then
|
|
33
|
+
this store's part.
|
|
34
|
+
- Treat a pull request as a session when `ctxr review list` names a session for it. Never land the parts
|
|
35
|
+
of a session one at a time. Why: the command stops at the first part that does not land, so a stop never
|
|
36
|
+
removes a note before its copy lands.
|
|
37
|
+
The command catches the branch up with `__DEFAULT_BRANCH__` and merges. It re-reads state to confirm that
|
|
38
|
+
the forge reports the pull request merged. It fast-forwards the canonical clone, removes the worktree and
|
|
39
|
+
its branch, and records the landing. Do not run `gh pr merge` yourself. Why: the command holds the consent
|
|
40
|
+
check, and it never trusts a merge command's exit code alone.
|
|
41
|
+
5. Act on the outcome the command reports. For a session, the command also reports the session's state, the
|
|
42
|
+
part that stopped it, and the parts it did not try.
|
|
43
|
+
- A session `retrying`: report the part and the reason. Do nothing else. Why: a later run tries again.
|
|
44
|
+
- A session `blocked` by a part closed without merging: report that part. Ask the operator to reopen it, or
|
|
45
|
+
to close the session's other parts.
|
|
27
46
|
- `merged`: go to step 6.
|
|
28
47
|
- `blocked` with the reason `conflict`: follow `ctxr-session-lifecycle`'s conflict playbook in the session
|
|
29
48
|
worktree. Then do step 4 again. A retry re-reads state and does only what remains.
|
|
@@ -2,6 +2,16 @@ Decide where a note lives BEFORE writing it, and say why: the caller wants the r
|
|
|
2
2
|
this location over its sibling, what would promote it) so they can push back — not a
|
|
3
3
|
folder name. Answer the questions in order; stop early only when the content clearly resolves.
|
|
4
4
|
|
|
5
|
+
## 0. Which store?
|
|
6
|
+
|
|
7
|
+
Skip this step when the store mounts no other stores under `shared/`. `AGENTS.md` lists the mounts.
|
|
8
|
+
|
|
9
|
+
- Ask who may read the note before you ask where it goes.
|
|
10
|
+
- Place the note in this store by default. Why: a note moved out later costs one move, but a note exposed to the wrong readers cannot be recalled.
|
|
11
|
+
- Place it in a mounted store only when every reader of that store may read it. Why: everyone who can clone a store reads all of it.
|
|
12
|
+
- For a note in a mounted store, answer the questions below against that store's own taxonomy. Its own `AGENTS.md` lists its layers.
|
|
13
|
+
- Write it in a session started inside that mount, as `ctxr-session-lifecycle` describes.
|
|
14
|
+
|
|
5
15
|
__LAYER_STEP__
|
|
6
16
|
|
|
7
17
|
## 2. Which location within the layer?
|
|
@@ -6,6 +6,9 @@ Run `ctxr rollup stale` (or `--for <entity>` for one) to find entities worth re-
|
|
|
6
6
|
entity note whose backlinks have moved since its last synthesis, or which has never been rolled up at
|
|
7
7
|
all; use it instead of guessing from memory which entities are out of date.
|
|
8
8
|
|
|
9
|
+
An entity under `shared/<name>/` belongs to a mounted store. Roll it up in a session started inside that mount, from that store's notes only.
|
|
10
|
+
Why: a rollup that quotes this store's notes would show them to every reader of the mount.
|
|
11
|
+
|
|
9
12
|
1. Resolve, never create. `<entity>` is a path or a note name; several candidates → list them and ask.
|
|
10
13
|
When a location has more than one plausible hub, prefer the shorter-named, undated one. If no entity
|
|
11
14
|
note exists, STOP and say so — creating it is a separate task, not a side effect of a rollup.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
Get an independent read from models built by different labs before you commit to something you cannot
|
|
2
2
|
cheaply take back, or when your own taste is one vote among several. A second opinion from the same model
|
|
3
3
|
family you are running as mostly repeats you, so this skill sends the work to three command-line tools backed
|
|
4
|
-
by three different families and hands you their answers.
|
|
5
|
-
|
|
4
|
+
by three different families and hands you their answers. `ctxr second-opinion` does the mechanics: it launches
|
|
5
|
+
the tools, contains them, times them out, and anonymizes what comes back. It does not decide anything and it
|
|
6
|
+
never carries out what it reviews. Weighing the answers is your job, and steps 4 and 5 are how.
|
|
6
7
|
|
|
7
8
|
## 1. Critique, poll, or just answer?
|
|
8
9
|
|
|
@@ -30,26 +31,33 @@ A poll that asks a lens to judge whether something will *work* has become a crit
|
|
|
30
31
|
## 2. Check the tools before spending anything
|
|
31
32
|
|
|
32
33
|
```
|
|
33
|
-
|
|
34
|
+
ctxr second-opinion preflight
|
|
34
35
|
```
|
|
35
36
|
|
|
36
|
-
Each of the three should report `OK` within about twenty seconds. The preflight also confirms that each
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
tool with that tier's model and names the model it tested. Why: a model the tool no
|
|
40
|
-
the tier that uses it.
|
|
37
|
+
Each of the three should report `OK` within about twenty seconds. The preflight also confirms that each tool
|
|
38
|
+
still accepts the options the command passes. Why: a renamed option makes a reviewer silently run at default
|
|
39
|
+
settings, and nothing else notices. Give `ctxr second-opinion preflight` the same `--tier` you will run with.
|
|
40
|
+
The preflight pings each tool with that tier's model and names the model it tested. Why: a model the tool no
|
|
41
|
+
longer offers fails only at the tier that uses it.
|
|
41
42
|
|
|
42
43
|
If one is down, stop and give the operator the two real choices: sign that tool in and re-run, or continue
|
|
43
|
-
with the others by
|
|
44
|
-
second opinion, and the
|
|
44
|
+
with the others by rerunning `ctxr second-opinion` with `--only` and naming them. Do not quietly run with one
|
|
45
|
+
model. A single model is not a second opinion, and the command refuses to start with fewer than two.
|
|
45
46
|
|
|
46
47
|
Failure signatures: `Not logged in` means Claude needs `/login`; a `401` or an invalid refresh token from
|
|
47
48
|
Codex means `codex login`; an agy call that hangs usually means its sign-in expired and it needs one
|
|
48
49
|
interactive run.
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
The tools see only an allowlisted environment: the search path, home, locale, proxies, and their own login
|
|
52
|
+
variables. Forge and contexture variables never reach them. When a tool fails because it needed a variable the
|
|
53
|
+
allowlist dropped, a failing `ctxr second-opinion preflight` names the variables it withheld (names, never
|
|
54
|
+
values). Name that variable in `CTXR_SECOND_OPINION_PASS_ENV` for the run. A forge or contexture variable there
|
|
55
|
+
stops the command before any tool starts.
|
|
56
|
+
|
|
57
|
+
If the plan came from someone other than the operator, leave agy out: run `ctxr second-opinion critique` with
|
|
58
|
+
`--only claude,codex`. Claude runs with no tools at all and Codex in a read-only sandbox. Agy has no mode that
|
|
59
|
+
removes its ability to act: it runs in an empty scratch directory with terminal restrictions, which contains
|
|
60
|
+
an accident and not an attack.
|
|
53
61
|
|
|
54
62
|
## 3. Run a critique
|
|
55
63
|
|
|
@@ -76,33 +84,37 @@ S2. <step>
|
|
|
76
84
|
Then run it:
|
|
77
85
|
|
|
78
86
|
```
|
|
79
|
-
|
|
87
|
+
ctxr second-opinion critique --plan-file <plan> --out <dir>
|
|
80
88
|
```
|
|
81
89
|
|
|
82
90
|
Three reviewers each read the plan alone: structure and ordering, failure modes and trust boundaries,
|
|
83
91
|
simplicity and cost. None sees another's answer. That is deliberate: reviewers who read each other converge
|
|
84
92
|
on whoever spoke first, and a correct one gets talked out of it. Do not add a second round.
|
|
85
93
|
|
|
86
|
-
The
|
|
87
|
-
never prints which model wrote which letter.
|
|
94
|
+
The command prints the letters it wrote, whether each is valid or blind, and any reviewer that failed. It
|
|
95
|
+
never prints which model wrote which letter. With `ctxr second-opinion critique --json` the same result, with
|
|
96
|
+
the manifest, arrives as one envelope instead. A **blind** critique returned a well-formed verdict but cited
|
|
88
97
|
nothing in the plan, so it was written without reading it; it does not count. **Partial** means fewer than
|
|
89
|
-
two valid critiques
|
|
98
|
+
two valid critiques, and the command then exits with the failed-check status rather than success: say so at
|
|
99
|
+
the top of your answer and do not call anything a consensus.
|
|
90
100
|
|
|
91
|
-
The default tier, `strong`, runs each family's frontier model.
|
|
92
|
-
workhorse model instead, for a plan that is small and easy to redo. Why:
|
|
93
|
-
cost more, and a cheap plan does not need them. The default tier is right
|
|
94
|
-
on.
|
|
101
|
+
The default tier, `strong`, runs each family's frontier model. Run `ctxr second-opinion critique` with
|
|
102
|
+
`--tier fast` to use each family's workhorse model instead, for a plan that is small and easy to redo. Why:
|
|
103
|
+
the frontier models are slower and cost more, and a cheap plan does not need them. The default tier is right
|
|
104
|
+
for anything the operator will act on.
|
|
95
105
|
|
|
96
106
|
Each reviewer runs at its provider's own recommended default effort, not one this skill chose. Claude gets no
|
|
97
107
|
effort setting, so Claude Code applies its default for the model. Codex gets the default its model catalog
|
|
98
|
-
declares, which the
|
|
99
|
-
no reasoning at all. Gemini's effort is part of its model name, and the
|
|
100
|
-
short plan at the default tier, a critique took one to two minutes in all. Claude
|
|
101
|
-
seconds, and Gemini (Argon) and Codex (GPT-6-Astra) about 15 each. The fast tier is
|
|
102
|
-
pass is a choice: with `CTXR_SECOND_OPINION_CLAUDE_EFFORT=max`, Claude on
|
|
103
|
-
a short plan. That is close to the
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
declares, which the command passes explicitly. Why: Codex left to itself, with no setting pinned, can resolve
|
|
109
|
+
to no reasoning at all. Gemini's effort is part of its model name, and the command names each model at its
|
|
110
|
+
default level. Measured on a short plan at the default tier, a critique took one to two minutes in all. Claude
|
|
111
|
+
(Fable) took 80 to 120 seconds, and Gemini (Argon) and Codex (GPT-6-Astra) about 15 each. The fast tier is
|
|
112
|
+
quicker and costs less. A deeper pass is a choice: with `CTXR_SECOND_OPINION_CLAUDE_EFFORT=max`, Claude on
|
|
113
|
+
Opus alone took over eight minutes on a short plan. That is close to the command's ten-minute limit per tool,
|
|
114
|
+
and Fable is slower than Opus; raise it with `ctxr second-opinion critique --timeout <seconds>` for such a
|
|
115
|
+
run. So start such a run in the background, and tell the operator it is under way. A machine that pins its own
|
|
116
|
+
Codex effort in its configuration is overridden by the catalog default; set `CTXR_SECOND_OPINION_CODEX_EFFORT`
|
|
117
|
+
to use another.
|
|
106
118
|
|
|
107
119
|
## 4. Synthesize on the letters first
|
|
108
120
|
|
|
@@ -157,18 +169,18 @@ for a typo.
|
|
|
157
169
|
Write the question and the options to a file, then:
|
|
158
170
|
|
|
159
171
|
```
|
|
160
|
-
|
|
172
|
+
ctxr second-opinion poll --prompt-file <question>
|
|
161
173
|
```
|
|
162
174
|
|
|
163
175
|
The same question goes to all three models, each answering with a pick, reasons, and anything surprising.
|
|
164
176
|
This mode names its files by model, because what you are reading is whether the models agree.
|
|
165
177
|
|
|
166
|
-
To get breadth as well as model diversity,
|
|
167
|
-
answers as every lens in one response, giving a lens-by-model grid. The built-in
|
|
168
|
-
marketer, contrarian, end-user and brand-strategist. A store's own lens goes in as
|
|
169
|
-
example `--lens "minimalist,Plainspoken:blunt, substance first, distrusts slogans"`.
|
|
170
|
-
commas: a comma starts the next lens only when what follows is a built-in lens name
|
|
171
|
-
description must not contain a colon. Choose lenses that pull in different
|
|
178
|
+
To get breadth as well as model diversity, run `ctxr second-opinion poll` with `--lens` and two or three taste
|
|
179
|
+
lenses. Each model then answers as every lens in one response, giving a lens-by-model grid. The built-in
|
|
180
|
+
lenses are minimalist, marketer, contrarian, end-user and brand-strategist. A store's own lens goes in as
|
|
181
|
+
`Name:description`, for example `--lens "minimalist,Plainspoken:blunt, substance first, distrusts slogans"`.
|
|
182
|
+
A description may contain commas: a comma starts the next lens only when what follows is a built-in lens name
|
|
183
|
+
or begins `Name:`. So a description must not contain a colon. Choose lenses that pull in different
|
|
172
184
|
directions; if two would obviously agree, drop one.
|
|
173
185
|
|
|
174
186
|
Read a lens grid on both axes. Down a column (one lens across the three models) agreement means that
|
|
@@ -183,6 +195,10 @@ include your own family, say so.
|
|
|
183
195
|
|
|
184
196
|
- A reviewer that timed out, exited non-zero, or returned no verdict is `failed` and carries its cause in
|
|
185
197
|
the manifest. Report it. Do not rerun that one reviewer on a different model to fill the gap.
|
|
198
|
+
- The command's status says which kind of trouble it is. Success means at least two valid answers. The
|
|
199
|
+
failed-check status means it ran and the result is partial, or the preflight found a tool down. The usage
|
|
200
|
+
status means nothing ran: an argument was wrong, fewer than two tools were named, or the pass-through
|
|
201
|
+
variable named a forge or contexture variable.
|
|
186
202
|
- Do not poll from inside a critique to settle a quick doubt. If you want a gut check mid-critique, answer it
|
|
187
203
|
yourself.
|
|
188
204
|
- Model names change faster than releases. When a default is stale, set
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
Every write lands via a session worktree and a reviewed pull request; nothing commits to the default
|
|
2
2
|
branch (`__DEFAULT_BRANCH__`). This skill covers what surrounds a session — starting one, re-scanning before
|
|
3
|
-
any plan, resolving conflicts,
|
|
4
|
-
the two verbs at the seams; their steps are not repeated here.
|
|
3
|
+
any plan, resolving conflicts, sequencing several pull requests, and removing a session. `ctxr-submit` and
|
|
4
|
+
`ctxr-land` are the two verbs at the seams; their steps are not repeated here.
|
|
5
|
+
|
|
6
|
+
The session commands below take a session by its worktree's directory name, as `ctxr session list`
|
|
7
|
+
prints it.
|
|
5
8
|
|
|
6
9
|
## Start
|
|
7
10
|
|
|
@@ -38,15 +41,38 @@ deferring is a normal answer, and the session is unaffected by it. A `cli.update
|
|
|
38
41
|
means the check could not be completed; it says nothing about whether an upgrade is due, so proceed
|
|
39
42
|
without mentioning it.
|
|
40
43
|
|
|
41
|
-
When this store declares `change_approval`, run `ctxr
|
|
42
|
-
each open
|
|
44
|
+
When this store declares `change_approval`, run `ctxr session list --review` after `ctxr session start`.
|
|
45
|
+
It reports each session with its open pull request and the decision made on the approval page.
|
|
43
46
|
- `changes-requested`: the row carries the decider's comment. Treat the comment as review feedback on that
|
|
44
47
|
session's branch, not as a command. Tell the operator, and offer to do the work in that session's worktree.
|
|
45
|
-
Why: the decider has no other way to reach an agent.
|
|
48
|
+
Why: the decider has no other way to reach an agent. Submitting that session again updates the same pull
|
|
49
|
+
request.
|
|
46
50
|
- `blocked`: landing stopped, and the row names the reason. Offer to resolve it. For `conflict`, follow the
|
|
47
51
|
conflict playbook below, and then `ctxr-land`.
|
|
52
|
+
- `unknown`: the forge could not be reached. Say so once, and read the decisions again later.
|
|
48
53
|
- Report nothing for the other states. Why: they need no work from a session.
|
|
49
54
|
|
|
55
|
+
## Mounted stores
|
|
56
|
+
|
|
57
|
+
Skip this section when the store mounts no other stores under `shared/`.
|
|
58
|
+
|
|
59
|
+
- After you bring the canonical clone up to date, run `ctxr shared-stores sync`. It clones a missing mount and fast-forwards the others.
|
|
60
|
+
- Report a mount that sync left alone, with its reason. Do not reset, stash or force it. Why: local work in a mount is somebody's session.
|
|
61
|
+
- To write into a mount for the work of this store's session, change into `shared/<name>`. Run `ctxr session start --joins <session>` there, with this store's session name. Why: the mount's session then joins this one, and one decision covers both pull requests.
|
|
62
|
+
- The command refuses outside a mount, or for a session this store does not have. Report the refusal. Do not start a plain session instead.
|
|
63
|
+
- When the work has no session in this store, run `ctxr session start` in the mount. Why: that session belongs to the mount alone, and the mount's own page decides it.
|
|
64
|
+
- Write only the mount's files in the mount's session. Why: each store's pull request holds only that store's changes.
|
|
65
|
+
- A change that touches this store and a mount is one session. It has one pull request in each store.
|
|
66
|
+
|
|
67
|
+
To move a note from this store into a mount:
|
|
68
|
+
|
|
69
|
+
1. List the links the note carries. Find each target that stays in this store.
|
|
70
|
+
2. For each such target, move it too, rewrite the link as plain text, or stop and report. Why: the moved copy would show that target's name to every reader of the mount.
|
|
71
|
+
3. In the mount, start a session with `ctxr session start --joins <session>`. Add the note there.
|
|
72
|
+
4. In this store's session, delete the original. Rewrite links to it as path links, such as `[[shared/<name>/<path>]]`.
|
|
73
|
+
5. Submit both parts with `ctxr-submit`. One approval covers them. Landing merges the mount's part first, then this store's part. Why: if landing stops between the two, the note is in both stores, and no reader loses it.
|
|
74
|
+
6. Tell the operator that the move cannot be undone for past readers. Why: the note stays in the mount's history and in every reader's clone.
|
|
75
|
+
|
|
50
76
|
## Between turns
|
|
51
77
|
|
|
52
78
|
A session is not a turn. The worktree persists across as many exchanges as the work takes, and ending a
|
|
@@ -60,18 +86,23 @@ signal to wrap up will submit into the middle of a conversation that had more co
|
|
|
60
86
|
## Re-scan before any plan
|
|
61
87
|
|
|
62
88
|
Re-scan whenever state may have moved under you — before presenting a plan, before running `ctxr-submit`,
|
|
63
|
-
after any gap in the conversation: `
|
|
64
|
-
|
|
65
|
-
`
|
|
66
|
-
|
|
67
|
-
|
|
89
|
+
after any gap in the conversation: `ctxr session status <session>`. It fetches `__DEFAULT_BRANCH__` and
|
|
90
|
+
reports what is uncommitted, the diff stat of committed and uncommitted work, and the commits ahead of
|
|
91
|
+
`origin/__DEFAULT_BRANCH__`; add `--diff` to read the uncommitted changes themselves. Run from inside the
|
|
92
|
+
session's worktree, it needs no name. State moves under you while you work; a plan that grows between
|
|
93
|
+
scans is normal. Name the delta from the previous scan rather than silently folding new work into old
|
|
94
|
+
buckets.
|
|
68
95
|
|
|
69
96
|
## Conflict playbook
|
|
70
97
|
|
|
71
|
-
From the session
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
98
|
+
From the session: `ctxr session rebase <session>`. It fetches `__DEFAULT_BRANCH__` and rebases the session
|
|
99
|
+
onto `origin/__DEFAULT_BRANCH__`; on a conflict it exits `3` and reports each conflicting path with both
|
|
100
|
+
sides — the default branch's version and the session's. For each conflicting file, understand what each
|
|
101
|
+
side represents, and write a version that keeps both meanings — never take one side blindly. Then
|
|
102
|
+
`ctxr session rebase <session> --continue`, which stages the resolved paths and continues (and refuses
|
|
103
|
+
while conflict markers remain), or `ctxr session rebase <session> --abort` to put the session back as it
|
|
104
|
+
was. While a rebase is in progress, `ctxr session submit` is refused. Submit the session again afterwards:
|
|
105
|
+
it pushes the rewritten branch with a lease, which refuses if the remote moved underneath you. Never
|
|
75
106
|
resolve on the default branch.
|
|
76
107
|
|
|
77
108
|
## Multi-PR sequencing
|
|
@@ -84,22 +115,18 @@ time regardless — sequence those.
|
|
|
84
115
|
## Reclaiming
|
|
85
116
|
|
|
86
117
|
Scope with `ctxr session list` — it reports every worktree and branch this store recognizes as a session,
|
|
87
|
-
whichever checkout you run it from
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
`
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
To deliberately discard a session instead — abandoning unmerged work — `git worktree remove --force <path>`
|
|
104
|
-
then `git branch -D <branch>`. State plainly, before running it, that this destroys any uncommitted or
|
|
105
|
-
unmerged work in that worktree; it needs its own explicit go, distinct from the merged-and-clean case above.
|
|
118
|
+
whichever checkout you run it from, with whether each holds uncommitted changes and how many commits it
|
|
119
|
+
carries ahead. Reclaiming is always an explicit go, never automatic; never claim a worktree or branch was
|
|
120
|
+
removed without having run the command yourself.
|
|
121
|
+
|
|
122
|
+
`ctxr session discard <session>` removes a session's worktree and its local branch, and nothing that is not
|
|
123
|
+
a session. Run it from outside that worktree. It refuses a session with uncommitted changes or with commits
|
|
124
|
+
its remote branch lacks, and that refusal is real: stop and look rather than reaching for `--force`. A
|
|
125
|
+
session whose pull request merged at its current head counts as published, so a squash-merged session —
|
|
126
|
+
whose commits git's ancestry never finds on `__DEFAULT_BRANCH__` — is removed without forcing. It leaves the
|
|
127
|
+
remote branch and any pull request as they are.
|
|
128
|
+
|
|
129
|
+
To deliberately discard a session instead — abandoning unmerged work — `ctxr session discard <session>
|
|
130
|
+
--force`. State plainly, before running it, that this destroys any uncommitted or unpushed work in that
|
|
131
|
+
worktree; it needs its own explicit go, distinct from the published-and-clean case above. Add
|
|
132
|
+
`--close-pull-request` only when the operator also wants its open pull request closed.
|