@useshifu/coding-harness 0.3.19 → 0.3.20
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 +6 -4
- package/bin/shifu-harness.js +33 -6
- package/commands/shifu-sync.md +2 -0
- package/package.json +1 -1
- package/skills/shifu-context/SKILL.md +1 -1
- package/skills/shifu-sync/SKILL.md +3 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Shifu coding-harness connector
|
|
2
2
|
|
|
3
|
-
`@useshifu/coding-harness` connects Codex, Claude Code, or OpenCode to Shifu and watches one local input folder.
|
|
3
|
+
`@useshifu/coding-harness` connects Codex, Claude Code, or OpenCode to Shifu and watches one local input folder. Session sync includes coding work and non-coding work chats: research, planning, writing, marketing, career development, leadership, and learning discussions. It reads final-assistant notes, never sends user prompts or raw transcripts, and sends incremental redacted activity through durable checkpoints. Folder files are sent over TLS for server-side parsing, sanitization, and user-attribution checks; the local runner does not redact file contents.
|
|
4
4
|
|
|
5
5
|
## Connect
|
|
6
6
|
|
|
@@ -32,6 +32,8 @@ To disconnect this device, run `npx --yes @useshifu/coding-harness disconnect --
|
|
|
32
32
|
|
|
33
33
|
## Operate
|
|
34
34
|
|
|
35
|
+
Version `0.3.20` expands the shared extractor to capture recognized work discussions and explanatory final answers without requiring code changes or completed-action wording. Discussion evidence uses neutral wording and excludes measured outcomes from explanations; proposals remain separate from adopted decisions. Automatic extraction uses controlled topics and details, so unfamiliar subjects may still need semantic review through the sync skill. Previously checkpointed chats are not replayed by an upgrade; an explicit force sync can re-review missed content.
|
|
36
|
+
|
|
35
37
|
Version `0.3.11` adds rolling days-based windows and explicit force replacement of reviewed segments. Force replacement requires backend migration 049 and the matching connector endpoints to be deployed first.
|
|
36
38
|
|
|
37
39
|
Version `0.3.12` makes force sync independent of local and server checkpoints, creates missing work, and protects automatic retries from overwriting a newer force sync. Deploy backend migrations 049 and 050 before using it.
|
|
@@ -112,7 +114,7 @@ Setup preserves other instruction text and MCP settings. Package installation re
|
|
|
112
114
|
The context branch adds a remote MCP connection using the same saved Codex key:
|
|
113
115
|
|
|
114
116
|
```sh
|
|
115
|
-
npx --yes @useshifu/coding-harness@0.3.
|
|
117
|
+
npx --yes @useshifu/coding-harness@0.3.20 mcp-setup --harness codex --mcp-url https://YOUR-BRANCH-HOST/mcp
|
|
116
118
|
```
|
|
117
119
|
|
|
118
120
|
For development, install dependencies and run from the checkout root:
|
|
@@ -143,7 +145,7 @@ Official configuration reference: https://learn.chatgpt.com/docs/config-file/con
|
|
|
143
145
|
OpenCode uses the same `/mcp` endpoint and three tools, authenticated with its own saved OpenCode connection key:
|
|
144
146
|
|
|
145
147
|
```sh
|
|
146
|
-
npx --yes @useshifu/coding-harness@0.3.
|
|
148
|
+
npx --yes @useshifu/coding-harness@0.3.20 mcp-setup --harness opencode --mcp-url https://YOUR-SHIFU-HOST/mcp
|
|
147
149
|
```
|
|
148
150
|
|
|
149
151
|
For checkout usage, install dependencies with `npm ci --prefix packages/shifu-coding-harness --ignore-scripts` from the checkout root, then run the checkout CLI with the same arguments. Setup preserves existing sync settings and other MCP servers, checks authenticated initialization and tool discovery, and installs the `shifu-context` usage instructions. A missing OpenCode connection prompts for its key in the terminal. A Codex key cannot authorize an OpenCode connection.
|
|
@@ -159,7 +161,7 @@ Official references: [MCP servers](https://docs.opencode.ai/docs/mcp-servers/) a
|
|
|
159
161
|
Claude Code connects to the same `/mcp` endpoint and three tools with its own saved connection key:
|
|
160
162
|
|
|
161
163
|
```sh
|
|
162
|
-
npx --yes @useshifu/coding-harness@0.3.
|
|
164
|
+
npx --yes @useshifu/coding-harness@0.3.20 mcp-setup --harness claude_code --mcp-url https://YOUR-SHIFU-HOST/mcp
|
|
163
165
|
```
|
|
164
166
|
|
|
165
167
|
For checkout usage, install dependencies as above and run the checkout CLI with these arguments. Setup checks the existing Claude Code key, authenticated initialization and tool discovery, and installs the `shifu-context` skill. It preserves the sync endpoint, schedule, checkpoints and other MCP servers. A missing connection prompts for a Claude Code key in the terminal; do not substitute a Codex or OpenCode key.
|
package/bin/shifu-harness.js
CHANGED
|
@@ -40,7 +40,7 @@ const MAX_TURNS_PER_SEGMENT = 12;
|
|
|
40
40
|
const MAX_TITLE_LENGTH = 160;
|
|
41
41
|
const MAX_WORK_DETAIL_LENGTH = 600;
|
|
42
42
|
const CONFIG_VERSION = 2;
|
|
43
|
-
const RUNNER_VERSION = "0.3.
|
|
43
|
+
const RUNNER_VERSION = "0.3.20";
|
|
44
44
|
const REDACTION_VERSION = 4;
|
|
45
45
|
const DEFAULT_INTERVAL_HOURS = 1;
|
|
46
46
|
const LEGACY_INTERVAL_HOURS = 4;
|
|
@@ -608,6 +608,10 @@ const WORK_ACTIONS = [
|
|
|
608
608
|
{ key: "rejected", title: "Rejected", pattern: /^(?:I\s+|We\s+)?(?:rejected|ruled out)\b/i },
|
|
609
609
|
{ key: "proposed", title: "Proposed", pattern: /^(?:I\s+|We\s+)?(?:proposed|recommended|suggested)\b/i },
|
|
610
610
|
{ key: "learned", title: "Learned", pattern: /^(?:I\s+|We\s+)?(?:learned|learnt)\b/i },
|
|
611
|
+
{ key: "discussed", title: "Discussed", pattern: /^(?:I\s+|We\s+)?(?:discussed|explored)\b/i },
|
|
612
|
+
{ key: "explained", title: "Explained", pattern: /^(?:I\s+|We\s+)?(?:explained|clarified)\b/i },
|
|
613
|
+
{ key: "outlined", title: "Outlined", pattern: /^(?:I\s+|We\s+)?outlined\b/i },
|
|
614
|
+
{ key: "analyzed", title: "Analyzed", pattern: /^(?:I\s+|We\s+)?analy[sz]ed\b/i },
|
|
611
615
|
];
|
|
612
616
|
|
|
613
617
|
const WORK_OBJECTS = [
|
|
@@ -642,6 +646,11 @@ const WORK_OBJECTS = [
|
|
|
642
646
|
{ key: "security", title: "security controls", pattern: /\b(?:security|vulnerability|secret handling)\b/i },
|
|
643
647
|
{ key: "research", title: "product research", pattern: /\b(?:product discovery|user research|customer research)\b/i },
|
|
644
648
|
{ key: "planning", title: "project plan", pattern: /\b(?:roadmap|project plan|delivery plan)\b/i },
|
|
649
|
+
{ key: "marketing", title: "marketing strategy", pattern: /\b(?:marketing|go.to.market|customer acquisition|content strategy)\b/i },
|
|
650
|
+
{ key: "business", title: "business planning", pattern: /\b(?:business plan|business strategy|pricing strategy|market positioning)\b/i },
|
|
651
|
+
{ key: "career", title: "career planning", pattern: /\b(?:career|job search|interview preparation|resume|résumé)\b/i },
|
|
652
|
+
{ key: "leadership", title: "leadership practices", pattern: /\b(?:leadership|team management|mentoring|delegation)\b/i },
|
|
653
|
+
{ key: "architecture", title: "system design", pattern: /\b(?:architecture|system design|service boundaries)\b/i },
|
|
645
654
|
];
|
|
646
655
|
|
|
647
656
|
// Only controlled feature descriptions leave the device during unattended sync.
|
|
@@ -664,6 +673,13 @@ const WORK_CONTEXTS = [
|
|
|
664
673
|
];
|
|
665
674
|
|
|
666
675
|
const WORK_DETAILS = [
|
|
676
|
+
{ title: "target audience", pattern: /\btarget audience\b/i },
|
|
677
|
+
{ title: "customer needs", pattern: /\bcustomer needs\b/i },
|
|
678
|
+
{ title: "prioritization", pattern: /\b(?:prioriti[sz]ation|priorities)\b/i },
|
|
679
|
+
{ title: "tradeoffs", pattern: /\btrade.?offs?\b/i },
|
|
680
|
+
{ title: "goals", pattern: /\bgoals?\b/i },
|
|
681
|
+
{ title: "risks", pattern: /\brisks?\b/i },
|
|
682
|
+
{ title: "constraints", pattern: /\bconstraints?\b/i },
|
|
667
683
|
{ title: "timeouts", pattern: /\btimeouts?\b/i },
|
|
668
684
|
{ title: "duplicates", pattern: /\bduplicat(?:e|es|ed|ion)\b/i },
|
|
669
685
|
{ title: "stale data", pattern: /\bstale (?:data|results?|cache)\b/i },
|
|
@@ -766,7 +782,7 @@ function controlledDetails(text) {
|
|
|
766
782
|
|
|
767
783
|
const ORGANIZATION_WORK_WORDS = new Set([
|
|
768
784
|
"acceptance", "commitment", "commitments", "approval", "approves", "approved", "requirements", "support",
|
|
769
|
-
"research", "experience", "onboarding", "billing", "flow", "plan", "planning", "management",
|
|
785
|
+
"research", "needs", "experience", "onboarding", "billing", "flow", "plan", "planning", "management",
|
|
770
786
|
"implementation", "status", "owner", "ownership", "named",
|
|
771
787
|
]);
|
|
772
788
|
|
|
@@ -866,12 +882,21 @@ function safeActivityEvidence(notes) {
|
|
|
866
882
|
continue;
|
|
867
883
|
}
|
|
868
884
|
if (rawLine.trimEnd().endsWith("?")) continue;
|
|
869
|
-
|
|
885
|
+
if (/^\s*(?:>|["“'])/.test(rawLine)) continue;
|
|
886
|
+
const text = rawLine.replace(/\*\*|`/g, "");
|
|
887
|
+
const activities = activitySegments(text);
|
|
888
|
+
// A conversation is useful context without implying adoption or completion.
|
|
889
|
+
const discussion = activities.length === 0;
|
|
890
|
+
if (discussion && (text.trim().split(/\s+/).length < 5 ||
|
|
891
|
+
/^\s*(?:[-*]\s+)?(?:no\b|nothing\b|not\b|(?:I|we)\s+(?:cannot|can't|did not|didn't|have not|haven't)\b)/i.test(text) ||
|
|
892
|
+
/\b(?:will|can|could|would|should|might)\s+(?:discuss|explore|explain|analy[sz]e|outline|review|talk|research|plan|learn)\b/i.test(text))) continue;
|
|
893
|
+
for (const [segmentIndex, line] of (discussion ? [`Discussed ${text}`] : activities).entries()) {
|
|
870
894
|
const clauses = line.split(/\s+(?:and|but|while)\s+|[;—]\s*/i);
|
|
871
895
|
const nextAction = clauses.findIndex((clause, index) => index > 0 && WORK_ACTIONS.some((item) => item.pattern.test(clause)));
|
|
872
896
|
const workClause = withoutNamedLabels(nextAction > 0 ? clauses.slice(0, nextAction).join(" and ") : line);
|
|
873
897
|
let action = WORK_ACTIONS.find((item) => item.pattern.test(line));
|
|
874
898
|
if (action?.key === "decided" && /^(?:I\s+|We\s+)?decided\s+not\s+to\b/i.test(line)) action = WORK_ACTIONS.find((item) => item.key === "rejected");
|
|
899
|
+
const conversational = discussion || ["discussed", "explained", "outlined", "analyzed"].includes(action?.key);
|
|
875
900
|
const detailSource = workClause.split(/\b(?:about|titled|instead of|rather than)\b/i, 1)[0];
|
|
876
901
|
const contexts = controlledContexts(detailSource);
|
|
877
902
|
const featureContexts = contexts === null ? [] : contexts.length ? contexts : sectionContexts;
|
|
@@ -882,6 +907,7 @@ function safeActivityEvidence(notes) {
|
|
|
882
907
|
if (match && match.index < objectPosition) { object = item; objectPosition = match.index; }
|
|
883
908
|
}
|
|
884
909
|
object ||= featureContexts[0];
|
|
910
|
+
if (!object && conversational) object = TECHNICAL_DETAILS.find((item) => item.pattern.test(detailSource));
|
|
885
911
|
if (!action || !object) continue;
|
|
886
912
|
const context = ["interview_feedback", "professional_post"].includes(object.key) ? [] : featureContexts.filter((item) => item !== object);
|
|
887
913
|
if (["test", "docs"].includes(object.key) && !context.length) {
|
|
@@ -889,11 +915,12 @@ function safeActivityEvidence(notes) {
|
|
|
889
915
|
const distinct = subjects.filter((item, index) => subjects.findIndex((subject) => subject.key === item.key) === index);
|
|
890
916
|
if (distinct.length <= 2) context.push(...distinct.map((item) => ({ ...item, phrase: item.title })));
|
|
891
917
|
}
|
|
892
|
-
const details = controlledDetails(detailSource).filter((detail) => !object.title.includes(detail)
|
|
893
|
-
|
|
918
|
+
const details = controlledDetails(detailSource).filter((detail) => !object.title.includes(detail) &&
|
|
919
|
+
(!conversational || [...WORK_DETAILS, ...TECHNICAL_DETAILS].some((item) => item.title === detail && !["staging measurement", "production impact not measured"].includes(detail))));
|
|
920
|
+
if ((discussion || ["test", "docs", "research", "planning"].includes(object.key)) && !context.length && !details.length) continue;
|
|
894
921
|
const title = `${action.title} ${object.title}${context.length ? ` for ${context.map((item) => item.phrase).join(" and ")}` : ""}`;
|
|
895
922
|
let statement = `${title}${details.length ? ` (${details.join(", ")})` : ""}.`;
|
|
896
|
-
for (const detail of controlledPlanningContext(withoutNamedLabels(line), action.key)) {
|
|
923
|
+
for (const detail of conversational ? [] : controlledPlanningContext(withoutNamedLabels(line), action.key)) {
|
|
897
924
|
if (statement.length + detail.length + 2 <= MAX_WORK_DETAIL_LENGTH) statement += ` ${detail}.`;
|
|
898
925
|
}
|
|
899
926
|
const identity = `${turn}:${statement}`;
|
package/commands/shifu-sync.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
description: Inspect or sync redacted OpenCode activity using the saved Shifu policy.
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
+
Include non-coding work chats as well as implementation sessions. Read final answers semantically and retain useful research, planning, marketing, career, leadership, and learning context even without code changes or completed-action wording. Use neutral discussion evidence for explanations; proposals are not adopted decisions, and explanations do not prove completed work or demonstrated learning.
|
|
6
|
+
|
|
5
7
|
Before sync, the runner installs Shifu's exact `recommendedPackageVersion` only if its current version is older. Equal or newer versions are left alone. Update failures allow sync to continue; do not independently install npm latest.
|
|
6
8
|
|
|
7
9
|
Run `npx --yes @useshifu/coding-harness status --harness opencode` first.
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@ description: Consult Shifu when a choice depends on missing user or project hist
|
|
|
10
10
|
When asked to connect Shifu context, run:
|
|
11
11
|
|
|
12
12
|
```sh
|
|
13
|
-
npx --yes @useshifu/coding-harness@0.3.
|
|
13
|
+
npx --yes @useshifu/coding-harness@0.3.20 mcp-setup --harness codex
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
For a branch deployment, append `--mcp-url` with the user's supplied HTTPS endpoint ending in `/mcp`. Keep the existing sync API endpoint. The CLI reuses this harness's saved key, checks the authenticated tools, and preserves existing settings. Codex and Claude Code use local credential helpers; OpenCode uses its native `{file:...}` substitution pointing to a private credential file. The key is never placed literally in MCP configuration. If no connection exists, the CLI asks for this harness's key in the terminal. Never request or print the key in chat or place it in command arguments. When input is unavailable, have the user run the command in an interactive terminal. Do not substitute plaintext credentials for an unsupported credential mechanism.
|
|
@@ -7,7 +7,9 @@ description: Connect, configure, inspect, or sync coding-harness activity, AI Pr
|
|
|
7
7
|
|
|
8
8
|
Before manual or scheduled sync, the runner checks Shifu's `recommendedPackageVersion`. It automatically installs that exact release only when the installed version is older; equal or newer versions are left alone. Do not independently install npm latest. If the check or update fails, continue syncing with the current runner. Connection settings, pending work, checkpoints, and the schedule are preserved.
|
|
9
9
|
|
|
10
|
-
Shifu records useful work
|
|
10
|
+
Shifu records useful work and work discussions through the harness. Include non-coding chat sessions about research, planning, writing, marketing, career development, leadership, decisions, and learning; code changes and tool calls are not required. Do not force non-engineering work into engineering categories.
|
|
11
|
+
|
|
12
|
+
Read final answers semantically, including explanatory prose without completed-action wording. Retain supported discussion topics, constraints, alternatives, rationale, and conclusions as activity context. Use neutral wording such as "Discussed" or "Explained" when the notes support a conversation rather than completed work. Keep recommendations and proposals distinct from adopted decisions; do not assert that the user learned, implemented, or achieved something merely because the assistant described it. Skip casual chat without durable work context.
|
|
11
13
|
|
|
12
14
|
Never include user prompts, raw transcripts, tool output, source code, commands, credentials, URLs, file paths, company or person names, customer details, or proprietary identifiers in a coding-session payload. Synthesize descriptive project labels from their purpose rather than copying a raw name. The local coding runner reads final assistant notes for career activity and scans user turns locally for fixed AI Profile signals; it sends neither raw source. Files placed in the user's chosen Shifu input folder are a separate path: the runner sends supported files over TLS for server-side parsing and sanitization. Do not describe folder files as locally redacted.
|
|
13
15
|
|