@useshifu/coding-harness 0.3.29 → 0.3.31
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 +59 -6
- package/bin/continuity-preparation.js +186 -0
- package/bin/continuity-state.js +202 -0
- package/bin/cursor-config.js +86 -0
- package/bin/cursor-mcp.js +96 -0
- package/bin/cursor-native.js +70 -0
- package/bin/cursor-sessions.js +197 -0
- package/bin/native-preparation.js +14 -10
- package/bin/onboarding-ui.js +1 -0
- package/bin/shifu-harness.js +238 -48
- package/bin/source-review.js +28 -2
- package/bin/v5-payload.js +1 -1
- package/package.json +1 -1
- package/skills/shifu-context/SKILL.md +1 -1
- package/skills/shifu-sync/SKILL.md +7 -1
package/bin/source-review.js
CHANGED
|
@@ -120,7 +120,7 @@ function openCodeSources(selection, rows, scheduled = false) {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
function sourcePacket(selection, records, scheduled) {
|
|
123
|
-
const adapters = { codex: codexSources, claude_code: claudeSources, opencode: openCodeSources };
|
|
123
|
+
const adapters = { codex: codexSources, claude_code: claudeSources, opencode: openCodeSources, cursor: require("./cursor-sessions.js").sources };
|
|
124
124
|
if (scheduled && selection.toTurn > completedSourceTurn(selection, records)) throw new Error("The selected original range includes an unfinished turn. Nothing was synced.");
|
|
125
125
|
const { turnCount, sources } = adapters[selection.harness](selection, records, scheduled);
|
|
126
126
|
if (selection.toTurn > turnCount) throw new Error("The selected original turns are unavailable locally. Nothing was reconstructed or synced.");
|
|
@@ -142,6 +142,7 @@ function scheduledSourcePacket(selection, records) {
|
|
|
142
142
|
// A later human message closes its predecessor. The trailing human turn needs
|
|
143
143
|
// explicit terminal metadata; age and intermediate text never close it.
|
|
144
144
|
function completedSourceTurn(selection, records) {
|
|
145
|
+
if (selection.harness === "cursor") return require("./cursor-sessions.js").completedTurn(records);
|
|
145
146
|
let turnCount = 0;
|
|
146
147
|
let closed = false;
|
|
147
148
|
if (selection.harness === "codex") {
|
|
@@ -198,4 +199,29 @@ function completedSourceTurn(selection, records) {
|
|
|
198
199
|
return Math.max(0, turnCount - (closed ? 0 : 1));
|
|
199
200
|
}
|
|
200
201
|
|
|
201
|
-
|
|
202
|
+
function continuitySourcePacket(selection, records, minimumTurn = 1) {
|
|
203
|
+
const packet = scheduledSourcePacket(selection, records);
|
|
204
|
+
let first = Math.max(1, selection.fromTurn - 6, minimumTurn);
|
|
205
|
+
const adapters = { codex: codexSources, claude_code: claudeSources, opencode: openCodeSources, cursor: require("./cursor-sessions.js").sources };
|
|
206
|
+
const references = first < selection.fromTurn
|
|
207
|
+
? adapters[selection.harness]({ ...selection, fromTurn: first, toTurn: selection.fromTurn - 1 }, records, true).sources : [];
|
|
208
|
+
const originalFirst = first;
|
|
209
|
+
let referenceSources = references;
|
|
210
|
+
function oversized() {
|
|
211
|
+
return Buffer.byteLength(JSON.stringify(referenceSources)) > 64 * 1024 ||
|
|
212
|
+
packet.sources.length + referenceSources.length > MAX_SOURCE_MESSAGES ||
|
|
213
|
+
Buffer.byteLength(JSON.stringify({ ...packet, referenceSources })) + 512 > MAX_PACKET_BYTES;
|
|
214
|
+
}
|
|
215
|
+
while (referenceSources.length && oversized()) {
|
|
216
|
+
first = referenceSources[0].turn + 1;
|
|
217
|
+
referenceSources = references.filter((source) => source.turn >= first);
|
|
218
|
+
}
|
|
219
|
+
return { ...packet, referenceSources, referenceCoverage: {
|
|
220
|
+
fromTurn: referenceSources.length ? referenceSources[0].turn : selection.fromTurn,
|
|
221
|
+
toTurn: selection.fromTurn - 1,
|
|
222
|
+
limited: first > Math.max(1, selection.fromTurn - 6) || minimumTurn > Math.max(1, selection.fromTurn - 6),
|
|
223
|
+
droppedTurns: Math.max(0, first - originalFirst),
|
|
224
|
+
} };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
module.exports = { selectedSourcePacket, scheduledSourcePacket, continuitySourcePacket, completedSourceTurn };
|
package/bin/v5-payload.js
CHANGED
|
@@ -76,7 +76,7 @@ function itemReferences(value, count, maximum, field, index, target) {
|
|
|
76
76
|
|
|
77
77
|
function preparedPayload(packet, output) {
|
|
78
78
|
exactObject(output, ["title", "summary", "decisions", "verification", "evidence"]);
|
|
79
|
-
if (!packet || !["codex", "claude_code", "opencode"].includes(packet.harness) || typeof packet.sessionRef !== "string" ||
|
|
79
|
+
if (!packet || !["codex", "claude_code", "opencode", "cursor"].includes(packet.harness) || typeof packet.sessionRef !== "string" ||
|
|
80
80
|
!Number.isInteger(packet.fromTurn) || !Number.isInteger(packet.toTurn) || packet.fromTurn < 1 || packet.toTurn < packet.fromTurn ||
|
|
81
81
|
packet.toTurn > 1_000_000 || packet.toTurn - packet.fromTurn >= 12 || !Array.isArray(packet.sources)) {
|
|
82
82
|
throw new Error("The selected source packet has invalid trusted metadata.");
|
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@ Before first connection or MCP personalization, ask for any choices that are not
|
|
|
12
12
|
When asked to connect Shifu context, run:
|
|
13
13
|
|
|
14
14
|
```sh
|
|
15
|
-
npx --yes @useshifu/coding-harness@0.3.
|
|
15
|
+
npx --yes @useshifu/coding-harness@0.3.30 mcp-setup --harness codex
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
MCP setup verifies the connection and tools, saves the choices and installs instructions; it does not sync sessions or upload the selected history. History selection governs eligible work for subsequent sync. Do not start sync as part of this setup unless the user separately asks for it. If a saved connection exists, reuse its key and do not run `connect` again.
|
|
@@ -117,7 +117,7 @@ For an explicit sync request, first read `status` to determine the saved approva
|
|
|
117
117
|
|
|
118
118
|
Use `kind: "activity"` for general harness work; it does not require a technical scope. Evidence may be empty when the reviewed source contains no durable context. Never invent impact, ownership, verification, or outcomes. A requested check, assistant proposal, or reported result must retain that status even when it is useful context.
|
|
119
119
|
|
|
120
|
-
Make each supported item useful for later recall: retain the described action, feature or project purpose, specific problem, approach, and reported verification or outcome with its status and ownership intact. Preserve supported technologies, design patterns, configuration choices, and measured results; these are useful work details, not identifiers to redact. A descriptive project label such as "payment reconciliation service" is useful; synthesize it from the work's purpose instead of copying a raw project label that might contain a company or person's name. Preserve supported decisions and their rationale, accepted and rejected tradeoffs, lessons, and observed outcomes. Keep proposals explicitly labeled as proposals; do not turn an agent suggestion into a user-adopted decision or infer personal ownership. Use statements, per-item work context, linked decisions and verification, and permitted source metadata. Keep distinct facts separate, including two fixes in one feature that addressed different problems.
|
|
120
|
+
Make each supported item useful for later recall: retain the described action, feature or project purpose, specific problem, approach, and reported verification or outcome with its status and ownership intact. Preserve supported technologies, design patterns, configuration choices, and measured results; these are useful work details, not identifiers to redact. A descriptive project label such as "payment reconciliation service" is useful; synthesize it from the work's purpose instead of copying a raw project label that might contain a company or person's name. Preserve supported decisions and their rationale, accepted and rejected tradeoffs, lessons, and observed outcomes. Keep proposals explicitly labeled as proposals; do not turn an agent suggestion into a user-adopted decision or infer personal ownership. Use statements, per-item work context, linked decisions and verification, and permitted source metadata. Keep distinct facts separate, including two fixes in one feature that addressed different problems. Preserve the code-permitted public technology labels Turbopuffer, PostgreSQL, Go, TypeScript, React and Node.js when grounded and relevant. This does not authorize confidential customer or employer relationships. Omit other company and person names, customer details, proprietary identifiers, paths, code snippets, credentials, and unsupported impact. If a detail cannot be safely described, keep the supported parts. Prefer a summary that names the main distinct work items over a generic count alone.
|
|
121
121
|
|
|
122
122
|
```json
|
|
123
123
|
{
|
|
@@ -157,3 +157,9 @@ Only when the user explicitly asks to force-sync, add `--force` to `sessions` wi
|
|
|
157
157
|
Re-review each returned range with `review --harness codex --session-ref <sessionRef> --force --from-turn <fromTurn> --to-turn <toTurn>` and the same window (or `--all` for explicitly selected backfill/count selection). No prior sync ID is required. Read the returned final notes semantically and synthesize meaningful, attributable work evidence; do not use `payloadForSegment` or its unattended keyword projection for force sync. Completed work remains supported when the note uses Markdown such as `**Implemented**` or names a technique in inline code such as `Rust`. Retain supported technologies, design patterns, the problem, approach, and verified result while redacting names and sensitive identifiers. Never send an empty evidence list or a title-only replacement. If the notes support no work items, report that range as not replaced and leave its existing work and checkpoints untouched. Keep the returned reference and range unchanged and include `force: true` in the prepared payload. Send with `sync --harness codex --force` (plus `--approved` only after manual approval). If accepted ranges changed and partially overlap the selection, stop and re-discover/re-review the complete ranges instead of guessing boundaries.
|
|
158
158
|
|
|
159
159
|
Force sync creates missing ranges or replaces existing exact ranges, preserves sync history, and never resets or lowers checkpoints. Automatic retries preserve the accepted result even if another force sync finishes meanwhile. A new invocation is a new explicit force request. Existing AI Profile observations stay unchanged. Do not add force to scheduled sync, approval queues, or file sync. Existing conversations keep their context; start a new chat in Shifu to use the latest work context.
|
|
160
|
+
|
|
161
|
+
## Continuity preparation and review holds
|
|
162
|
+
|
|
163
|
+
Scheduled preparation and pending review use bounded original lookback, code-bound entity placeholders and a separate local continuity outbox. Never add continuity fields to a v5 payload or rewrite a frozen queued body. `status` separates preparation, base receipt and companion attachment. A base receipt does not establish successful continuity attachment. Missing server capability leaves the frozen metadata pending. Do not guess a target sync from turn ranges.
|
|
164
|
+
|
|
165
|
+
A preparation hold survives restarts and stops after two native attempts for unchanged input. Inspect its code-owned reason. Genuine neutral empties stay valid; never create filler evidence to clear a hold. A specific authorized retry of an unqueued held range can use `retry-preparation --harness codex --session-ref <opaque-session> --from-turn <original-start>`; this cannot replay accepted history or regenerate frozen transport. Replacing the key or API endpoint quarantines old checkpoints, queues, local entity dictionaries and continuity metadata. An interrupted replacement holds sync until connect resumes with the same selected connection. Do not upload, display or copy the raw-name dictionary into chat.
|