@brainervirus/workit-opencode 8.4.0 → 8.5.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/assets/skills/workit-retro/SKILL.md +2 -2
- package/dist/plugin.js +382 -114
- package/package.json +2 -2
|
@@ -15,8 +15,8 @@ proposes and stops. Nothing changes until the user approves.
|
|
|
15
15
|
`retro:` row in `workit ledger list --type decision`), else the last ~10
|
|
16
16
|
sessions. State the window in one line.
|
|
17
17
|
2. **Read through workit, cheapest first.** Every finding cites these:
|
|
18
|
-
- `workit ledger list --last 200`: rulings
|
|
19
|
-
|
|
18
|
+
- `workit ledger list --last 200`: rulings, failed/self verdicts, handoffs,
|
|
19
|
+
check runs, CI reruns, `skill.loaded` rows (skipped skills: routing).
|
|
20
20
|
- `workit pr status --pr <n>` for each recent PR: threads, failing checks.
|
|
21
21
|
- `git log --oneline -50`, plus reverts and fixups after review.
|
|
22
22
|
- `workit knowledge lint`: today's AGENTS.md and need-based files.
|
package/dist/plugin.js
CHANGED
|
@@ -19157,6 +19157,7 @@ function entryCompactContext(store, entry, session, context) {
|
|
|
19157
19157
|
cache.delete(cache.keys().next().value);
|
|
19158
19158
|
return compact.data;
|
|
19159
19159
|
}
|
|
19160
|
+
var TURN_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
19160
19161
|
// packages/workit-core/src/hooks/policy.ts
|
|
19161
19162
|
var shellPolicy = (cwd, command) => {
|
|
19162
19163
|
const policy = shellBranchPolicyViolation(cwd, command);
|
|
@@ -19450,7 +19451,7 @@ function writeGate(cwd, paths) {
|
|
|
19450
19451
|
const gate = gateFor(cwd);
|
|
19451
19452
|
if (!gate || gate.blockers.length === 0)
|
|
19452
19453
|
return NONE2;
|
|
19453
|
-
if (paths && paths.every((file) => exempt(cwd, gate.root, file, gate.plans)))
|
|
19454
|
+
if (paths?.length && paths.every((file) => exempt(cwd, gate.root, file, gate.plans)))
|
|
19454
19455
|
return NONE2;
|
|
19455
19456
|
const reasons = gate.blockers.map((item) => `${item.ruleId}: ${item.reason}`).join("; ");
|
|
19456
19457
|
return {
|
|
@@ -19800,6 +19801,11 @@ var actionsIn = (cwd, command, dialect) => {
|
|
|
19800
19801
|
}
|
|
19801
19802
|
return out;
|
|
19802
19803
|
};
|
|
19804
|
+
var inWorkitWorkspace = (dir) => {
|
|
19805
|
+
const repo = repoAt(dir);
|
|
19806
|
+
return repo !== null && isWorkitWorkspace(repo);
|
|
19807
|
+
};
|
|
19808
|
+
var rawDelivery = (cwd, command, dialect) => mentionsRawTool(command) && actionsIn(cwd, command, dialect).some(({ action }) => action.kind !== "commit" && action.kind !== "pr-read");
|
|
19803
19809
|
var mentionsRawTool = (command) => /\b(?:git|gh|glab)\b/i.test(command);
|
|
19804
19810
|
var dialectOf = (input) => (input.event.kind === "shell.pre" || input.event.kind === "shell.post" ? input.event.dialect : undefined) ?? "posix";
|
|
19805
19811
|
function rawGitPre(input, command) {
|
|
@@ -19908,8 +19914,271 @@ function rawGitPost(input, command, key) {
|
|
|
19908
19914
|
settle2(input, repo, markerFile(repo, input.session.id, key));
|
|
19909
19915
|
} catch {}
|
|
19910
19916
|
}
|
|
19917
|
+
// packages/workit-core/src/hooks/skill-nudge.ts
|
|
19918
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
19919
|
+
import fs16 from "node:fs";
|
|
19920
|
+
import path23 from "node:path";
|
|
19921
|
+
|
|
19922
|
+
// packages/workit-core/src/core/skill-manifests.ts
|
|
19923
|
+
var WORKIT_METHOD_SKILLS = [
|
|
19924
|
+
"workit-shape",
|
|
19925
|
+
"workit-implement",
|
|
19926
|
+
"workit-review",
|
|
19927
|
+
"workit-debug",
|
|
19928
|
+
"workit-ship",
|
|
19929
|
+
"workit-continue",
|
|
19930
|
+
"workit-bdd",
|
|
19931
|
+
"workit-test-audit",
|
|
19932
|
+
"workit-deslop",
|
|
19933
|
+
"workit-fanout",
|
|
19934
|
+
"workit-verify-app",
|
|
19935
|
+
"workit-retro",
|
|
19936
|
+
"workit-architecture"
|
|
19937
|
+
];
|
|
19938
|
+
var WORKIT_SKILL_ALIASES = {
|
|
19939
|
+
"wk-shape": "workit-shape",
|
|
19940
|
+
"wk-implement": "workit-implement",
|
|
19941
|
+
"wk-review": "workit-review",
|
|
19942
|
+
"wk-debug": "workit-debug",
|
|
19943
|
+
"wk-ship": "workit-ship",
|
|
19944
|
+
"wk-continue": "workit-continue",
|
|
19945
|
+
"wk-bdd": "workit-bdd",
|
|
19946
|
+
"wk-test-audit": "workit-test-audit",
|
|
19947
|
+
"wk-deslop": "workit-deslop",
|
|
19948
|
+
"wk-fanout": "workit-fanout",
|
|
19949
|
+
"wk-verify-app": "workit-verify-app",
|
|
19950
|
+
"wk-retro": "workit-retro",
|
|
19951
|
+
"wk-architecture": "workit-architecture"
|
|
19952
|
+
};
|
|
19953
|
+
var skillLoadWording = (host, skill) => {
|
|
19954
|
+
switch (host) {
|
|
19955
|
+
case "claude-code":
|
|
19956
|
+
return `call the Skill tool with \`workit:${skill.replace(/^workit-/, "")}\``;
|
|
19957
|
+
case "opencode":
|
|
19958
|
+
return `call the skill tool with \`${skill}\``;
|
|
19959
|
+
default:
|
|
19960
|
+
return `read the \`${skill}\` skill's SKILL.md and follow it`;
|
|
19961
|
+
}
|
|
19962
|
+
};
|
|
19963
|
+
var SKILL_REFERENCE = /\((workit-[a-z-]+)\)/g;
|
|
19964
|
+
var renderSkillText = (text, host) => text.replace(SKILL_REFERENCE, (match, name) => WORKIT_METHOD_SKILLS.includes(name) ? `(${skillLoadWording(host, name)})` : match);
|
|
19965
|
+
if (false) {}
|
|
19966
|
+
|
|
19967
|
+
// packages/workit-core/src/hooks/skill-nudge.ts
|
|
19968
|
+
var USER_INVOKED = new Set(["workit-retro", "workit-architecture"]);
|
|
19969
|
+
var SKILL_HOST = {
|
|
19970
|
+
claude_code: "claude-code",
|
|
19971
|
+
opencode: "opencode",
|
|
19972
|
+
codex_cli: "codex",
|
|
19973
|
+
codex_desktop: "codex",
|
|
19974
|
+
cursor: "cursor",
|
|
19975
|
+
pi: "pi"
|
|
19976
|
+
};
|
|
19977
|
+
var PROMPT_INTENTS = [
|
|
19978
|
+
[
|
|
19979
|
+
"workit-debug",
|
|
19980
|
+
/\b(flaky|regression|(?:is|are|got|looks) broken|debug (?:this|it|the|why)|fix (?:the|this|a) bug)\b/i
|
|
19981
|
+
],
|
|
19982
|
+
[
|
|
19983
|
+
"workit-continue",
|
|
19984
|
+
/\b(pick up where|where (?:were|did) we|resume (?:the|this|my|our|work|where)|hand ?off)\b/i
|
|
19985
|
+
],
|
|
19986
|
+
[
|
|
19987
|
+
"workit-review",
|
|
19988
|
+
/\b(blast radius|code review|review (?:the|this|my|PR|pr|#\d+|branch|diff|changes))\b/i
|
|
19989
|
+
],
|
|
19990
|
+
[
|
|
19991
|
+
"workit-ship",
|
|
19992
|
+
/\b(ship (?:it|this|the)|babysit|open (?:a|the) (?:PR|pr|MR|mr)|merge (?:the|this|my) (?:PR|pr|MR|mr|branch)|(?:get|until|make) CI (?:is )?green)\b/i
|
|
19993
|
+
],
|
|
19994
|
+
["workit-bdd", /\b(BDD|TDD|acceptance criteria|Given\/When\/Then)(?![\w/])/],
|
|
19995
|
+
["workit-test-audit", /\b(test audit|audit the tests|tautolog\w*|weak tests)\b/i],
|
|
19996
|
+
["workit-deslop", /\b(deslop|slop|dead code)\b/i],
|
|
19997
|
+
["workit-fanout", /\b(fan(?: |-)?out|parallelize|parallel agents|swarm)\b/i],
|
|
19998
|
+
["workit-verify-app", /\b(verify the app|smoke test|prove it works)\b/i],
|
|
19999
|
+
["workit-retro", /\b(retro|retrospective)\b(?!\.\w)/i],
|
|
20000
|
+
["workit-architecture", /\b(deepen (?:the )?modules|architecture (?:review|pass|audit))\b/i],
|
|
20001
|
+
[
|
|
20002
|
+
"workit-shape",
|
|
20003
|
+
/\b(brainstorm\w*|grill me|should we|let'?s plan|plan (?:out|how|the|a|for)|(?:write|draft) (?:a|the) spec)\b/i
|
|
20004
|
+
],
|
|
20005
|
+
[
|
|
20006
|
+
"workit-implement",
|
|
20007
|
+
/\b(implement (?:the|this|a|it)|add (?:a|the) feature|build (?:a|an|the) (?:new )?(?:feature|command|verb|page|endpoint|component|cli|tool))\b/i
|
|
20008
|
+
]
|
|
20009
|
+
];
|
|
20010
|
+
var workitSkillOf = (name) => {
|
|
20011
|
+
const bare = name.trim().replace(/^\//, "").toLowerCase();
|
|
20012
|
+
const alias = WORKIT_SKILL_ALIASES[bare];
|
|
20013
|
+
if (alias)
|
|
20014
|
+
return alias;
|
|
20015
|
+
const skill = bare.replace(/^workit:/, "workit-");
|
|
20016
|
+
return WORKIT_METHOD_SKILLS.includes(skill) ? skill : null;
|
|
20017
|
+
};
|
|
20018
|
+
var promptTrigger = (prompt) => {
|
|
20019
|
+
const text = prompt.replace(/```[\s\S]*?```/g, " ").slice(0, 4000);
|
|
20020
|
+
for (const [skill, pattern] of PROMPT_INTENTS) {
|
|
20021
|
+
const match = pattern.exec(text);
|
|
20022
|
+
if (match)
|
|
20023
|
+
return { skill, trigger: match[1] ?? match[0] };
|
|
20024
|
+
}
|
|
20025
|
+
return null;
|
|
20026
|
+
};
|
|
20027
|
+
var markerFile2 = (input, session) => {
|
|
20028
|
+
const location = resolveStore(input.cwd);
|
|
20029
|
+
if (location instanceof Error || !location.shared)
|
|
20030
|
+
return null;
|
|
20031
|
+
const name = createHash12("sha256").update(`${input.host}\x00${session}`).digest("hex").slice(0, 32);
|
|
20032
|
+
return path23.join(location.dir, "hooks", `skills-${name}.json`);
|
|
20033
|
+
};
|
|
20034
|
+
var readMarker = (file) => {
|
|
20035
|
+
try {
|
|
20036
|
+
const value = JSON.parse(fs16.readFileSync(file, "utf8"));
|
|
20037
|
+
return { nudged: value.nudged ?? [], loaded: value.loaded ?? [] };
|
|
20038
|
+
} catch {
|
|
20039
|
+
return { nudged: [], loaded: [] };
|
|
20040
|
+
}
|
|
20041
|
+
};
|
|
20042
|
+
var writeMarker = (file, marker) => {
|
|
20043
|
+
try {
|
|
20044
|
+
fs16.mkdirSync(path23.dirname(file), { recursive: true });
|
|
20045
|
+
fs16.writeFileSync(file, JSON.stringify(marker));
|
|
20046
|
+
} catch {}
|
|
20047
|
+
};
|
|
20048
|
+
var loadedSkills = (cwd, session) => {
|
|
20049
|
+
const ledger = readLedger(cwd);
|
|
20050
|
+
const loaded = new Set;
|
|
20051
|
+
if (!ledger.ok)
|
|
20052
|
+
return loaded;
|
|
20053
|
+
for (const row of ledger.value.rows)
|
|
20054
|
+
if (row.type === "skill.loaded" && row.actor.session === session && typeof row.skill === "string")
|
|
20055
|
+
loaded.add(row.skill);
|
|
20056
|
+
return loaded;
|
|
20057
|
+
};
|
|
20058
|
+
var READERS = new Set([
|
|
20059
|
+
"cat",
|
|
20060
|
+
"sed",
|
|
20061
|
+
"head",
|
|
20062
|
+
"tail",
|
|
20063
|
+
"less",
|
|
20064
|
+
"more",
|
|
20065
|
+
"bat",
|
|
20066
|
+
"nl",
|
|
20067
|
+
"get-content",
|
|
20068
|
+
"gc",
|
|
20069
|
+
"type"
|
|
20070
|
+
]);
|
|
20071
|
+
function recordSkillLoad(input, name, via) {
|
|
20072
|
+
try {
|
|
20073
|
+
const skill = workitSkillOf(name);
|
|
20074
|
+
const session = input.session.id;
|
|
20075
|
+
if (!skill || !session)
|
|
20076
|
+
return;
|
|
20077
|
+
if (!inWorkitWorkspace(input.cwd))
|
|
20078
|
+
return;
|
|
20079
|
+
const file = markerFile2(input, session);
|
|
20080
|
+
if (!file)
|
|
20081
|
+
return;
|
|
20082
|
+
const marker = readMarker(file);
|
|
20083
|
+
if (marker.loaded.includes(skill))
|
|
20084
|
+
return;
|
|
20085
|
+
writeMarker(file, { ...marker, loaded: [...marker.loaded, skill] });
|
|
20086
|
+
if (loadedSkills(input.cwd, session).has(skill))
|
|
20087
|
+
return;
|
|
20088
|
+
appendHookObserved(input.cwd, {
|
|
20089
|
+
type: "skill.loaded",
|
|
20090
|
+
actor: { host: input.host, session, agentId: input.session.agentId },
|
|
20091
|
+
skill,
|
|
20092
|
+
via
|
|
20093
|
+
});
|
|
20094
|
+
} catch {}
|
|
20095
|
+
}
|
|
20096
|
+
var nudgeOnce = (input, session, skill, line) => {
|
|
20097
|
+
const file = markerFile2(input, session);
|
|
20098
|
+
if (!file)
|
|
20099
|
+
return null;
|
|
20100
|
+
const marker = readMarker(file);
|
|
20101
|
+
if (marker.nudged.includes(skill) || marker.loaded.includes(skill))
|
|
20102
|
+
return null;
|
|
20103
|
+
if (loadedSkills(input.cwd, session).has(skill))
|
|
20104
|
+
return null;
|
|
20105
|
+
writeMarker(file, { ...marker, nudged: [...marker.nudged, skill] });
|
|
20106
|
+
return line;
|
|
20107
|
+
};
|
|
20108
|
+
var nudgeText = (input, skill, why) => USER_INVOKED.has(skill) ? `Workit: ${why} looks like ${skill} work, which the user starts; offer it (/${skill.replace(/^workit-/, "wk-")}) rather than loading it.` : `Workit: ${why} looks like ${skill} work; if it is, ${skillLoadWording(SKILL_HOST[input.host], skill)} first.`;
|
|
20109
|
+
var promptLoads = (prompt) => /^\s*\/(?:skill:)?([\w:-]+)/.exec(prompt)?.[1] ?? /^\s*<skill name="([\w:-]+)"/.exec(prompt)?.[1] ?? /^\s*Load the (workit-[a-z-]+) skill with the skill tool\b/.exec(prompt)?.[1] ?? null;
|
|
20110
|
+
function promptNudge(input, prompt) {
|
|
20111
|
+
try {
|
|
20112
|
+
const session = input.session.id;
|
|
20113
|
+
if (!prompt || !session || input.session.agentId)
|
|
20114
|
+
return null;
|
|
20115
|
+
const loads = promptLoads(prompt);
|
|
20116
|
+
if (loads) {
|
|
20117
|
+
recordSkillLoad(input, loads, "slash");
|
|
20118
|
+
return null;
|
|
20119
|
+
}
|
|
20120
|
+
const hit = promptTrigger(prompt);
|
|
20121
|
+
if (!hit || !inWorkitWorkspace(input.cwd))
|
|
20122
|
+
return null;
|
|
20123
|
+
return nudgeOnce(input, session, hit.skill, nudgeText(input, hit.skill, `this request ("${hit.trigger}")`));
|
|
20124
|
+
} catch {
|
|
20125
|
+
return null;
|
|
20126
|
+
}
|
|
20127
|
+
}
|
|
20128
|
+
var WORKIT_DELIVERY = /^(?:pr (?:create|merge)|ci wait|git push)\b/;
|
|
20129
|
+
var SHELLS2 = new Set(["sh", "bash", "zsh", "dash", "ksh"]);
|
|
20130
|
+
var LAUNCHERS = new Set([
|
|
20131
|
+
"npx",
|
|
20132
|
+
"bunx",
|
|
20133
|
+
"pnpx",
|
|
20134
|
+
"-y",
|
|
20135
|
+
"--yes",
|
|
20136
|
+
"pnpm",
|
|
20137
|
+
"dlx",
|
|
20138
|
+
"exec",
|
|
20139
|
+
"env",
|
|
20140
|
+
"sudo",
|
|
20141
|
+
"command"
|
|
20142
|
+
]);
|
|
20143
|
+
var runsWorkitDelivery = (command, dialect, depth = 0) => segmentsOf(command, dialect).some(({ words }) => {
|
|
20144
|
+
const at = words.findIndex((word) => !/^\w+=/.test(word) && !LAUNCHERS.has(word));
|
|
20145
|
+
if (at >= 0 && /(?:^|[\\/])workit(?:\.exe)?$|^@brainervirus\/workit-cli$/.test(words[at])) {
|
|
20146
|
+
const args = words.slice(at + 1);
|
|
20147
|
+
if (args.some((arg) => arg === "--help" || arg === "-h" || arg === "--dry-run"))
|
|
20148
|
+
return false;
|
|
20149
|
+
return WORKIT_DELIVERY.test(args.join(" "));
|
|
20150
|
+
}
|
|
20151
|
+
const shell = SHELLS2.has(words[at]?.split(/[\\/]/).at(-1) ?? "");
|
|
20152
|
+
const script = shell && words[at + 1] === "-c" ? words[at + 2] : undefined;
|
|
20153
|
+
return depth < 3 && script !== undefined && runsWorkitDelivery(script, "posix", depth + 1);
|
|
20154
|
+
});
|
|
20155
|
+
var isDeliveryCommand = (cwd, command, dialect = "posix") => rawDelivery(cwd, command, dialect) || runsWorkitDelivery(command, dialect) && inWorkitWorkspace(cwd);
|
|
20156
|
+
function shipNudge(input, command) {
|
|
20157
|
+
try {
|
|
20158
|
+
const session = input.session.id;
|
|
20159
|
+
if (!session || input.session.agentId)
|
|
20160
|
+
return null;
|
|
20161
|
+
const dialect = input.event.kind === "shell.pre" ? input.event.dialect ?? "posix" : "posix";
|
|
20162
|
+
if (!isDeliveryCommand(input.cwd, command, dialect))
|
|
20163
|
+
return null;
|
|
20164
|
+
return nudgeOnce(input, session, "workit-ship", nudgeText(input, "workit-ship", "this delivery step"));
|
|
20165
|
+
} catch {
|
|
20166
|
+
return null;
|
|
20167
|
+
}
|
|
20168
|
+
}
|
|
20169
|
+
var withContextLine = (decision, line) => {
|
|
20170
|
+
if (!line)
|
|
20171
|
+
return decision;
|
|
20172
|
+
if (decision.kind === "none")
|
|
20173
|
+
return { kind: "context", text: line };
|
|
20174
|
+
if (decision.kind === "context")
|
|
20175
|
+
return { kind: "context", text: `${decision.text}
|
|
20176
|
+
${line}` };
|
|
20177
|
+
return decision;
|
|
20178
|
+
};
|
|
20179
|
+
var shellNudge = (input, command) => withContextLine(rawGitPre(input, command), shipNudge(input, command));
|
|
19911
20180
|
// packages/workit-core/src/hooks/hosts/fields.ts
|
|
19912
|
-
var
|
|
20181
|
+
var SHELLS3 = new Set(["sh", "bash", "zsh", "dash", "pwsh", "powershell", "cmd"]);
|
|
19913
20182
|
var WRITE_TOOLS = new Set([
|
|
19914
20183
|
"write",
|
|
19915
20184
|
"edit",
|
|
@@ -19931,7 +20200,6 @@ var WRITE_TOOLS = new Set([
|
|
|
19931
20200
|
]);
|
|
19932
20201
|
// packages/workit-core/src/hooks/handle.ts
|
|
19933
20202
|
var offered = new Set;
|
|
19934
|
-
var CLAUDE_JUDGES = new Set(["workit:verifier", "workit:reviewer"]);
|
|
19935
20203
|
// packages/workit-core/src/hooks/hosts/claude-code.ts
|
|
19936
20204
|
var SOURCES = new Set(["startup", "resume", "clear", "compact", "fork"]);
|
|
19937
20205
|
var SHELL_TOOLS = new Set(["Bash", "PowerShell"]);
|
|
@@ -19945,7 +20213,7 @@ var CONTEXT_EVENTS = new Set([
|
|
|
19945
20213
|
|
|
19946
20214
|
// packages/workit-core/src/hooks/hosts/codex.ts
|
|
19947
20215
|
var SHELL_TOOLS2 = new Set(["bash", "unified-exec"]);
|
|
19948
|
-
var SOURCES2 = new Set(["startup", "resume", "clear", "compact"]);
|
|
20216
|
+
var SOURCES2 = new Set(["startup", "resume", "clear", "compact", "fork"]);
|
|
19949
20217
|
|
|
19950
20218
|
// packages/workit-core/src/hooks/hosts/cursor.ts
|
|
19951
20219
|
var BLOCKING2 = new Set(["preToolUse", "beforeShellExecution", "subagentStart"]);
|
|
@@ -19970,21 +20238,23 @@ var OPENCODE_DESCRIPTOR = {
|
|
|
19970
20238
|
"subagent.stop": { support: "native", native: 'tool.hook("execute.after") subagent' },
|
|
19971
20239
|
"prompt.submit": { support: "undocumented", native: null },
|
|
19972
20240
|
"compact.pre": { support: "native", native: 'session.hook("compaction")' },
|
|
19973
|
-
stop: { support: "
|
|
20241
|
+
stop: { support: "none", native: null }
|
|
19974
20242
|
},
|
|
19975
20243
|
shellPolicy: { deny: "native", channel: "effect", failClosed: false },
|
|
19976
20244
|
context: {
|
|
19977
20245
|
sessionStart: "none",
|
|
19978
20246
|
perTurn: "native",
|
|
19979
20247
|
afterCompact: "native",
|
|
19980
|
-
task: "session-bound"
|
|
20248
|
+
task: "session-bound",
|
|
20249
|
+
turnResend: "every-turn"
|
|
19981
20250
|
},
|
|
19982
20251
|
subagents: {
|
|
19983
20252
|
identity: "native",
|
|
19984
20253
|
parentBinding: "native",
|
|
19985
20254
|
blockStart: "native",
|
|
19986
20255
|
worktreeIsolation: "undocumented",
|
|
19987
|
-
maxConcurrency: "undocumented"
|
|
20256
|
+
maxConcurrency: "undocumented",
|
|
20257
|
+
agentPrefix: "workit-"
|
|
19988
20258
|
},
|
|
19989
20259
|
provenance: { sessionId: "native", agentIdOnTool: "native", postToolObserve: "native" },
|
|
19990
20260
|
interaction: { questions: "native", writeBoundary: "partial" },
|
|
@@ -20019,11 +20289,11 @@ var OPENCODE_DESCRIPTOR = {
|
|
|
20019
20289
|
]
|
|
20020
20290
|
};
|
|
20021
20291
|
// packages/workit-opencode/src/shared/init-apply.ts
|
|
20022
|
-
import
|
|
20292
|
+
import path28 from "node:path";
|
|
20023
20293
|
|
|
20024
20294
|
// packages/workit-core/src/core/gitignore.ts
|
|
20025
20295
|
import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "node:fs";
|
|
20026
|
-
import
|
|
20296
|
+
import path24 from "node:path";
|
|
20027
20297
|
var GITIGNORE_ENTRIES = [
|
|
20028
20298
|
"# workit: SDD working state (never commit)",
|
|
20029
20299
|
"docs/*/sdd/",
|
|
@@ -20043,7 +20313,7 @@ var GITIGNORE_ENTRIES = [
|
|
|
20043
20313
|
var ensureProjectGitignore = (workspaceRoot, confirmed) => {
|
|
20044
20314
|
if (!confirmed)
|
|
20045
20315
|
return { ok: false, error: "confirmed: true required" };
|
|
20046
|
-
const file =
|
|
20316
|
+
const file = path24.join(workspaceRoot, ".gitignore");
|
|
20047
20317
|
const existing = existsSync8(file) ? readFileSync6(file, "utf8") : "";
|
|
20048
20318
|
const existingLines = new Set(existing.split(`
|
|
20049
20319
|
`).map((l) => l.trim()).filter(Boolean));
|
|
@@ -20071,25 +20341,25 @@ var ensureProjectGitignore = (workspaceRoot, confirmed) => {
|
|
|
20071
20341
|
|
|
20072
20342
|
// packages/workit-core/src/core/hygiene.ts
|
|
20073
20343
|
import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "node:fs";
|
|
20074
|
-
import
|
|
20344
|
+
import path25 from "node:path";
|
|
20075
20345
|
var repoRoot3 = assetRoot();
|
|
20076
|
-
var templatesDir = () =>
|
|
20346
|
+
var templatesDir = () => path25.join(repoRoot3, "templates", "hygiene");
|
|
20077
20347
|
var packageJson = (root) => {
|
|
20078
|
-
if (!existsSync9(
|
|
20348
|
+
if (!existsSync9(path25.join(root, "package.json")))
|
|
20079
20349
|
return null;
|
|
20080
20350
|
try {
|
|
20081
|
-
return JSON.parse(readFileSync7(
|
|
20351
|
+
return JSON.parse(readFileSync7(path25.join(root, "package.json"), "utf8"));
|
|
20082
20352
|
} catch {
|
|
20083
20353
|
return null;
|
|
20084
20354
|
}
|
|
20085
20355
|
};
|
|
20086
20356
|
var isOpenSource = (root) => {
|
|
20087
|
-
if (existsSync9(
|
|
20357
|
+
if (existsSync9(path25.join(root, "LICENSE")))
|
|
20088
20358
|
return true;
|
|
20089
20359
|
const pkg = packageJson(root);
|
|
20090
20360
|
if (pkg && !pkg.private)
|
|
20091
20361
|
return true;
|
|
20092
|
-
return
|
|
20362
|
+
return path25.basename(root) === "workflow-toolkit";
|
|
20093
20363
|
};
|
|
20094
20364
|
var licenseHolder = (root) => {
|
|
20095
20365
|
const pkg = packageJson(root);
|
|
@@ -20112,13 +20382,13 @@ var planHygieneFiles = (root, opts = {}) => {
|
|
|
20112
20382
|
files.push("LICENSE", "CONTRIBUTING.md");
|
|
20113
20383
|
const planned = [];
|
|
20114
20384
|
for (const file of files) {
|
|
20115
|
-
if (existsSync9(
|
|
20385
|
+
if (existsSync9(path25.join(root, file)))
|
|
20116
20386
|
continue;
|
|
20117
|
-
const tpl =
|
|
20387
|
+
const tpl = path25.join(templatesDir(), file);
|
|
20118
20388
|
if (!existsSync9(tpl))
|
|
20119
20389
|
continue;
|
|
20120
|
-
const content = readFileSync7(tpl, "utf8").replace(/<PROJECT>/g,
|
|
20121
|
-
planned.push({ path:
|
|
20390
|
+
const content = readFileSync7(tpl, "utf8").replace(/<PROJECT>/g, path25.basename(root)).replace(/<YEAR>/g, String(new Date().getFullYear())).replace(/<HOLDER>\s*/g, licenseHolder(root));
|
|
20391
|
+
planned.push({ path: path25.join(root, file), content });
|
|
20122
20392
|
}
|
|
20123
20393
|
return planned;
|
|
20124
20394
|
};
|
|
@@ -20128,19 +20398,19 @@ var ensureHygieneFiles = (root, opts) => {
|
|
|
20128
20398
|
const created = [];
|
|
20129
20399
|
for (const planned of planHygieneFiles(root, opts)) {
|
|
20130
20400
|
writeFileSync5(planned.path, planned.content, "utf8");
|
|
20131
|
-
created.push(
|
|
20401
|
+
created.push(path25.basename(planned.path));
|
|
20132
20402
|
}
|
|
20133
20403
|
return { ok: true, created };
|
|
20134
20404
|
};
|
|
20135
20405
|
|
|
20136
20406
|
// packages/workit-core/src/core/init.ts
|
|
20137
|
-
import
|
|
20138
|
-
import
|
|
20407
|
+
import fs17 from "node:fs";
|
|
20408
|
+
import path27 from "node:path";
|
|
20139
20409
|
import { spawnSync as spawnSync16 } from "node:child_process";
|
|
20140
20410
|
|
|
20141
20411
|
// packages/workit-core/src/core/workspace-branch-policy.ts
|
|
20142
20412
|
import { mkdirSync as mkdirSync4, readFileSync as readFileSync8, renameSync as renameSync3, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "node:fs";
|
|
20143
|
-
import
|
|
20413
|
+
import path26 from "node:path";
|
|
20144
20414
|
import { isDeepStrictEqual } from "node:util";
|
|
20145
20415
|
var readFileSafe = (p) => {
|
|
20146
20416
|
try {
|
|
@@ -20151,7 +20421,7 @@ var readFileSafe = (p) => {
|
|
|
20151
20421
|
};
|
|
20152
20422
|
function applyWorkspaceBranchPolicy(opts) {
|
|
20153
20423
|
const { workspace_root, env = process.env } = opts;
|
|
20154
|
-
const dir =
|
|
20424
|
+
const dir = path26.join(env.WORKFLOW_TOOLKIT_CONFIG ?? configDir());
|
|
20155
20425
|
const {
|
|
20156
20426
|
status,
|
|
20157
20427
|
path: wsPath,
|
|
@@ -20163,7 +20433,7 @@ function applyWorkspaceBranchPolicy(opts) {
|
|
|
20163
20433
|
if (status === "malformed" || status === "invalid")
|
|
20164
20434
|
return { ok: false, error: workspacesError ?? `invalid workspaces.json: ${wsPath}` };
|
|
20165
20435
|
const detection = detectBranchPolicy(workspace_root);
|
|
20166
|
-
const name = String(env.WORKFLOW_BP_NAME ??
|
|
20436
|
+
const name = String(env.WORKFLOW_BP_NAME ?? path26.basename(workspace_root));
|
|
20167
20437
|
const integration = env.WORKFLOW_BP_INTEGRATION ?? detection.integration;
|
|
20168
20438
|
const policy = {
|
|
20169
20439
|
preset: detection.preset,
|
|
@@ -20212,7 +20482,7 @@ function applyWorkspaceBranchPolicy(opts) {
|
|
|
20212
20482
|
ok: false,
|
|
20213
20483
|
error: `workspaces.json changed while applying the branch policy: ${wsPath}`
|
|
20214
20484
|
};
|
|
20215
|
-
mkdirSync4(
|
|
20485
|
+
mkdirSync4(path26.dirname(wsPath), { recursive: true });
|
|
20216
20486
|
const tmp = `${wsPath}.${process.pid}.tmp`;
|
|
20217
20487
|
try {
|
|
20218
20488
|
writeFileSync6(tmp, JSON.stringify({ ...document, workspaces: next }, null, 2) + `
|
|
@@ -20247,7 +20517,7 @@ function applyWorkspaceBranchPolicy(opts) {
|
|
|
20247
20517
|
var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE";
|
|
20248
20518
|
var readJson = (p) => {
|
|
20249
20519
|
try {
|
|
20250
|
-
const parsed = JSON.parse(
|
|
20520
|
+
const parsed = JSON.parse(fs17.readFileSync(p, "utf8"));
|
|
20251
20521
|
return isConfigObject(parsed) ? parsed : null;
|
|
20252
20522
|
} catch {
|
|
20253
20523
|
return null;
|
|
@@ -20277,7 +20547,7 @@ var youtrackJsonContent = (dir) => {
|
|
|
20277
20547
|
const meetingIssue = process.env.WORKFLOW_YT_MEETING_ISSUE;
|
|
20278
20548
|
return {
|
|
20279
20549
|
baseUrl: process.env.WORKFLOW_YT_BASE_URL ?? "https://youtrack.example.com",
|
|
20280
|
-
tokenFile: process.env.WORKFLOW_YT_TOKEN_FILE ??
|
|
20550
|
+
tokenFile: process.env.WORKFLOW_YT_TOKEN_FILE ?? path27.join(dir, "youtrack.token"),
|
|
20281
20551
|
...meetingIssue ? {
|
|
20282
20552
|
meetingIssue,
|
|
20283
20553
|
meetingIssues: { general: { issue: meetingIssue, label: "General meetings" } }
|
|
@@ -20307,19 +20577,19 @@ var vcsJsonContent = () => {
|
|
|
20307
20577
|
};
|
|
20308
20578
|
function initApplyData(action, env = process.env) {
|
|
20309
20579
|
const dir = String(env.WORKFLOW_TOOLKIT_CONFIG ?? configDir());
|
|
20310
|
-
|
|
20580
|
+
fs17.mkdirSync(dir, { recursive: true });
|
|
20311
20581
|
switch (action) {
|
|
20312
20582
|
case "youtrack_json": {
|
|
20313
|
-
const out =
|
|
20314
|
-
|
|
20583
|
+
const out = path27.join(dir, "youtrack.json");
|
|
20584
|
+
fs17.writeFileSync(out, JSON.stringify(youtrackJsonContent(dir), null, 2) + `
|
|
20315
20585
|
`, "utf8");
|
|
20316
20586
|
return { action, ok: true, path: out };
|
|
20317
20587
|
}
|
|
20318
20588
|
case "youtrack_token_placeholder": {
|
|
20319
|
-
const p =
|
|
20589
|
+
const p = path27.join(dir, "youtrack.token");
|
|
20320
20590
|
const preserved = writeFileExclusive(p, TOKEN_PLACEHOLDER2 + `
|
|
20321
20591
|
`, 384) === "preserved";
|
|
20322
|
-
const abs =
|
|
20592
|
+
const abs = path27.resolve(p);
|
|
20323
20593
|
return {
|
|
20324
20594
|
action,
|
|
20325
20595
|
ok: true,
|
|
@@ -20331,14 +20601,14 @@ function initApplyData(action, env = process.env) {
|
|
|
20331
20601
|
};
|
|
20332
20602
|
}
|
|
20333
20603
|
case "youtrack_scaffold": {
|
|
20334
|
-
const jsonOut =
|
|
20335
|
-
const tokenOut =
|
|
20336
|
-
|
|
20604
|
+
const jsonOut = path27.join(dir, "youtrack.json");
|
|
20605
|
+
const tokenOut = path27.join(dir, "youtrack.token");
|
|
20606
|
+
fs17.writeFileSync(jsonOut, JSON.stringify(youtrackJsonContent(dir), null, 2) + `
|
|
20337
20607
|
`, "utf8");
|
|
20338
20608
|
const preserved = writeFileExclusive(tokenOut, TOKEN_PLACEHOLDER2 + `
|
|
20339
20609
|
`, 384) === "preserved";
|
|
20340
|
-
const configPath =
|
|
20341
|
-
const tokenPath =
|
|
20610
|
+
const configPath = path27.resolve(jsonOut);
|
|
20611
|
+
const tokenPath = path27.resolve(tokenOut);
|
|
20342
20612
|
const prev = process.env.WORKFLOW_YOUTRACK_CONFIG;
|
|
20343
20613
|
process.env.WORKFLOW_YOUTRACK_CONFIG = configPath;
|
|
20344
20614
|
let tokenCreate = {};
|
|
@@ -20390,10 +20660,10 @@ function initApplyData(action, env = process.env) {
|
|
|
20390
20660
|
}
|
|
20391
20661
|
}
|
|
20392
20662
|
case "vcs_scaffold": {
|
|
20393
|
-
const jsonOut =
|
|
20394
|
-
|
|
20663
|
+
const jsonOut = path27.join(dir, "vcs.json");
|
|
20664
|
+
fs17.writeFileSync(jsonOut, JSON.stringify(vcsJsonContent(), null, 2) + `
|
|
20395
20665
|
`, "utf8");
|
|
20396
|
-
const configPath =
|
|
20666
|
+
const configPath = path27.resolve(jsonOut);
|
|
20397
20667
|
const prev = process.env.WORKFLOW_VCS_CONFIG;
|
|
20398
20668
|
process.env.WORKFLOW_VCS_CONFIG = configPath;
|
|
20399
20669
|
try {
|
|
@@ -20512,7 +20782,7 @@ var executeInitApply = (args, directory, runtime) => {
|
|
|
20512
20782
|
protectedNames: args.branch_policy_protected
|
|
20513
20783
|
}, current);
|
|
20514
20784
|
writeConfig(next);
|
|
20515
|
-
return output(ok({ action: "config", path:
|
|
20785
|
+
return output(ok({ action: "config", path: path28.join(configDir(), "config.json"), ...next }));
|
|
20516
20786
|
}
|
|
20517
20787
|
const env = Object.fromEntries(Object.entries({
|
|
20518
20788
|
WORKFLOW_YT_BASE_URL: args.base_url,
|
|
@@ -20529,14 +20799,14 @@ var executeInitApply = (args, directory, runtime) => {
|
|
|
20529
20799
|
|
|
20530
20800
|
// packages/workit-opencode/src/shared/session.ts
|
|
20531
20801
|
import { realpathSync as realpathSync7 } from "node:fs";
|
|
20532
|
-
import
|
|
20802
|
+
import path29 from "node:path";
|
|
20533
20803
|
var sameWorkspace = (expected, observed) => {
|
|
20534
20804
|
if (typeof observed !== "string" || !observed)
|
|
20535
20805
|
return false;
|
|
20536
20806
|
try {
|
|
20537
20807
|
return realpathSync7(expected) === realpathSync7(observed);
|
|
20538
20808
|
} catch {
|
|
20539
|
-
return
|
|
20809
|
+
return path29.resolve(expected) === path29.resolve(observed);
|
|
20540
20810
|
}
|
|
20541
20811
|
};
|
|
20542
20812
|
|
|
@@ -20608,7 +20878,7 @@ var workitFamilyOf = (toolName) => {
|
|
|
20608
20878
|
|
|
20609
20879
|
// packages/workit-opencode/src/tools/context.ts
|
|
20610
20880
|
import { realpathSync as realpathSync8 } from "node:fs";
|
|
20611
|
-
import
|
|
20881
|
+
import path30 from "node:path";
|
|
20612
20882
|
var createContextTool = () => ({
|
|
20613
20883
|
description: "Read Git, pull request, YouTrack, issue, changelog, release, or affected-file context.",
|
|
20614
20884
|
execute: async (args, context) => {
|
|
@@ -20618,7 +20888,7 @@ var createContextTool = () => ({
|
|
|
20618
20888
|
let root;
|
|
20619
20889
|
try {
|
|
20620
20890
|
const cwd = parsed.data.cwd;
|
|
20621
|
-
root = realpathSync8(cwd ?
|
|
20891
|
+
root = realpathSync8(cwd ? path30.resolve(context.directory, cwd) : context.directory);
|
|
20622
20892
|
} catch {
|
|
20623
20893
|
return JSON.stringify(failure2("invalid_input", "context target directory cannot be resolved"), null, 2);
|
|
20624
20894
|
}
|
|
@@ -21180,7 +21450,7 @@ var evaluateShellPermission = (root, event, workdirs = new Map) => {
|
|
|
21180
21450
|
};
|
|
21181
21451
|
|
|
21182
21452
|
// packages/workit-opencode/src/v2/shell.ts
|
|
21183
|
-
import
|
|
21453
|
+
import path31 from "node:path";
|
|
21184
21454
|
var commandOf = (input) => {
|
|
21185
21455
|
if (input === null || typeof input !== "object")
|
|
21186
21456
|
return null;
|
|
@@ -21189,7 +21459,7 @@ var commandOf = (input) => {
|
|
|
21189
21459
|
};
|
|
21190
21460
|
var hookInput = (root, sessionID, id, shell) => ({
|
|
21191
21461
|
host: "opencode",
|
|
21192
|
-
cwd: shell.workdir ?
|
|
21462
|
+
cwd: shell.workdir ? path31.resolve(root, shell.workdir) : root,
|
|
21193
21463
|
session: { id: sessionID, agentId: null, agentType: null, parentId: null },
|
|
21194
21464
|
permissionMode: null,
|
|
21195
21465
|
transcriptPath: null,
|
|
@@ -21219,7 +21489,7 @@ var observeShellResult = (root, event) => {
|
|
|
21219
21489
|
return;
|
|
21220
21490
|
const input = hookInput(root, String(event.sessionID), String(event.id), shell);
|
|
21221
21491
|
rawGitPost(input, shell.command, callKey(String(event.id), shell.command));
|
|
21222
|
-
const nudge =
|
|
21492
|
+
const nudge = shellNudge(input, shell.command);
|
|
21223
21493
|
const result = event.result;
|
|
21224
21494
|
if (nudge.kind !== "context" || !result)
|
|
21225
21495
|
return;
|
|
@@ -21235,84 +21505,78 @@ ${nudge.text}` };
|
|
|
21235
21505
|
} catch {}
|
|
21236
21506
|
};
|
|
21237
21507
|
|
|
21238
|
-
// packages/workit-opencode/src/v2/
|
|
21239
|
-
|
|
21240
|
-
|
|
21241
|
-
|
|
21242
|
-
|
|
21243
|
-
|
|
21244
|
-
|
|
21245
|
-
|
|
21246
|
-
|
|
21247
|
-
|
|
21248
|
-
|
|
21249
|
-
|
|
21250
|
-
"
|
|
21251
|
-
|
|
21252
|
-
|
|
21253
|
-
|
|
21254
|
-
"
|
|
21255
|
-
|
|
21256
|
-
|
|
21257
|
-
|
|
21258
|
-
|
|
21259
|
-
|
|
21260
|
-
|
|
21261
|
-
|
|
21262
|
-
|
|
21263
|
-
|
|
21264
|
-
|
|
21265
|
-
"
|
|
21266
|
-
|
|
21267
|
-
|
|
21268
|
-
"wk-fanout": "workit-fanout",
|
|
21269
|
-
"wk-verify-app": "workit-verify-app",
|
|
21270
|
-
"wk-retro": "workit-retro",
|
|
21271
|
-
"wk-architecture": "workit-architecture"
|
|
21508
|
+
// packages/workit-opencode/src/v2/skills.ts
|
|
21509
|
+
var hookInput2 = (root, sessionID, subagent) => ({
|
|
21510
|
+
host: "opencode",
|
|
21511
|
+
cwd: root,
|
|
21512
|
+
session: {
|
|
21513
|
+
id: sessionID,
|
|
21514
|
+
agentId: subagent ? sessionID : null,
|
|
21515
|
+
agentType: null,
|
|
21516
|
+
parentId: null
|
|
21517
|
+
},
|
|
21518
|
+
permissionMode: null,
|
|
21519
|
+
transcriptPath: null,
|
|
21520
|
+
event: { kind: "context.turn" }
|
|
21521
|
+
});
|
|
21522
|
+
var observeSkillLoad = (root, event) => {
|
|
21523
|
+
const input = event.input;
|
|
21524
|
+
if (typeof input?.name === "string")
|
|
21525
|
+
recordSkillLoad(hookInput2(root, String(event.sessionID), false), input.name, "tool");
|
|
21526
|
+
};
|
|
21527
|
+
var newUserPrompt = (messages) => {
|
|
21528
|
+
const last = messages.at(-1);
|
|
21529
|
+
if (last?.role !== "user")
|
|
21530
|
+
return null;
|
|
21531
|
+
if (typeof last.content === "string")
|
|
21532
|
+
return last.content;
|
|
21533
|
+
if (!Array.isArray(last.content))
|
|
21534
|
+
return null;
|
|
21535
|
+
const text = last.content.filter((part) => part.type === "text" && typeof part.text === "string").map((part) => part.text).join(`
|
|
21536
|
+
`);
|
|
21537
|
+
return text || null;
|
|
21272
21538
|
};
|
|
21273
|
-
var
|
|
21274
|
-
|
|
21275
|
-
|
|
21276
|
-
|
|
21277
|
-
|
|
21278
|
-
|
|
21279
|
-
default:
|
|
21280
|
-
return `read the \`${skill}\` skill's SKILL.md and follow it`;
|
|
21281
|
-
}
|
|
21539
|
+
var injectSkillNudge = (root, session, messages, system) => {
|
|
21540
|
+
try {
|
|
21541
|
+
const nudge = promptNudge(hookInput2(root, session.id, session.parentID !== undefined), newUserPrompt(messages));
|
|
21542
|
+
if (nudge)
|
|
21543
|
+
system.push({ type: "text", text: nudge });
|
|
21544
|
+
} catch {}
|
|
21282
21545
|
};
|
|
21283
|
-
|
|
21284
|
-
|
|
21285
|
-
|
|
21546
|
+
|
|
21547
|
+
// packages/workit-opencode/src/v2/registry.ts
|
|
21548
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9 } from "node:fs";
|
|
21549
|
+
import path33 from "node:path";
|
|
21286
21550
|
|
|
21287
21551
|
// packages/workit-opencode/src/shared/assets.ts
|
|
21288
21552
|
import { existsSync as existsSync10, realpathSync as realpathSync9 } from "node:fs";
|
|
21289
|
-
import
|
|
21553
|
+
import path32 from "node:path";
|
|
21290
21554
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
21291
21555
|
var moduleDir = () => {
|
|
21292
21556
|
try {
|
|
21293
|
-
return realpathSync9(
|
|
21557
|
+
return realpathSync9(path32.dirname(fileURLToPath2(import.meta.url)));
|
|
21294
21558
|
} catch {
|
|
21295
|
-
return
|
|
21559
|
+
return path32.dirname(fileURLToPath2(import.meta.url));
|
|
21296
21560
|
}
|
|
21297
21561
|
};
|
|
21298
21562
|
var packageRoot2 = () => {
|
|
21299
21563
|
const dir = moduleDir();
|
|
21300
21564
|
for (const candidate of [
|
|
21301
|
-
|
|
21302
|
-
|
|
21303
|
-
|
|
21565
|
+
path32.resolve(dir, ".."),
|
|
21566
|
+
path32.resolve(dir, "..", ".."),
|
|
21567
|
+
path32.resolve(dir, "..", "..", "..")
|
|
21304
21568
|
]) {
|
|
21305
|
-
if (existsSync10(
|
|
21569
|
+
if (existsSync10(path32.join(candidate, "package.json")))
|
|
21306
21570
|
return candidate;
|
|
21307
21571
|
}
|
|
21308
|
-
return
|
|
21572
|
+
return path32.resolve(dir, "..");
|
|
21309
21573
|
};
|
|
21310
21574
|
var skillsRoot = () => {
|
|
21311
21575
|
const root = packageRoot2();
|
|
21312
|
-
const canonical =
|
|
21313
|
-
if (existsSync10(
|
|
21576
|
+
const canonical = path32.resolve(root, "..", "workit-core", "skills");
|
|
21577
|
+
if (existsSync10(path32.join(root, "src")) && existsSync10(canonical))
|
|
21314
21578
|
return canonical;
|
|
21315
|
-
return
|
|
21579
|
+
return path32.join(root, "assets", "skills");
|
|
21316
21580
|
};
|
|
21317
21581
|
|
|
21318
21582
|
// packages/workit-opencode/src/v2/registry.ts
|
|
@@ -21339,11 +21603,11 @@ var registerSkills = async (ctx) => {
|
|
|
21339
21603
|
if (!existsSync11(skillsDir))
|
|
21340
21604
|
return new Set;
|
|
21341
21605
|
const listed = await ctx.skill.list().catch(() => ({ data: [] }));
|
|
21342
|
-
const own = (skill) => typeof skill.path === "string" &&
|
|
21606
|
+
const own = (skill) => typeof skill.path === "string" && path33.resolve(skill.path).startsWith(skillsDir + path33.sep);
|
|
21343
21607
|
const userSkills = new Set((listed?.data ?? []).filter((skill) => !own(skill)).map((skill) => skill.id));
|
|
21344
21608
|
const packaged = new Map;
|
|
21345
21609
|
for (const id of WORKIT_METHOD_SKILLS) {
|
|
21346
|
-
const file =
|
|
21610
|
+
const file = path33.join(skillsDir, id, "SKILL.md");
|
|
21347
21611
|
if (!userSkills.has(id) && existsSync11(file))
|
|
21348
21612
|
packaged.set(id, file);
|
|
21349
21613
|
}
|
|
@@ -21391,22 +21655,22 @@ var registerCommands = async (ctx, registeredSkills) => {
|
|
|
21391
21655
|
|
|
21392
21656
|
// packages/workit-opencode/src/stale-sources.ts
|
|
21393
21657
|
import { existsSync as existsSync12, readdirSync as readdirSync5 } from "node:fs";
|
|
21394
|
-
import
|
|
21658
|
+
import path34 from "node:path";
|
|
21395
21659
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
21396
21660
|
var typescriptFiles = (directory) => {
|
|
21397
21661
|
if (!existsSync12(directory))
|
|
21398
21662
|
return [];
|
|
21399
21663
|
return readdirSync5(directory, { withFileTypes: true }).flatMap((entry) => {
|
|
21400
|
-
const file =
|
|
21664
|
+
const file = path34.join(directory, entry.name);
|
|
21401
21665
|
return entry.isDirectory() ? typescriptFiles(file) : entry.isFile() && file.endsWith(".ts") ? [file] : [];
|
|
21402
21666
|
});
|
|
21403
21667
|
};
|
|
21404
21668
|
var pluginSourceFiles = [
|
|
21405
21669
|
...new Set([
|
|
21406
21670
|
fileURLToPath3(import.meta.url),
|
|
21407
|
-
...typescriptFiles(
|
|
21408
|
-
|
|
21409
|
-
...typescriptFiles(
|
|
21671
|
+
...typescriptFiles(path34.join(packageRoot2(), "src")),
|
|
21672
|
+
path34.join(packageRoot2(), "..", "workit-core", "src", "core.ts"),
|
|
21673
|
+
...typescriptFiles(path34.join(packageRoot2(), "..", "workit-core", "src", "core"))
|
|
21410
21674
|
])
|
|
21411
21675
|
].filter((file) => existsSync12(file)).toSorted();
|
|
21412
21676
|
|
|
@@ -21511,6 +21775,8 @@ var setup = async (ctx) => {
|
|
|
21511
21775
|
await ctx.tool.hook("execute.before", async (event) => {
|
|
21512
21776
|
if (event.tool === "shell")
|
|
21513
21777
|
return observeShellBefore(root, event, shellWorkdirs);
|
|
21778
|
+
if (event.tool === "skill")
|
|
21779
|
+
return observeSkillLoad(root, event);
|
|
21514
21780
|
if (event.tool !== "subagent")
|
|
21515
21781
|
return;
|
|
21516
21782
|
await lifecycle.executeBefore({
|
|
@@ -21540,6 +21806,8 @@ var setup = async (ctx) => {
|
|
|
21540
21806
|
const session = await sessionFacts(ctx, String(event.sessionID));
|
|
21541
21807
|
injectAgentContext(root, session, lifecycle.directChildren, event.system);
|
|
21542
21808
|
injectHistoryOffer(root, session, historyOfferSessions, event.system);
|
|
21809
|
+
if (session)
|
|
21810
|
+
injectSkillNudge(root, session, event.messages, event.system);
|
|
21543
21811
|
if (!staleSourcesWarned) {
|
|
21544
21812
|
const changed = changedSourcesSinceLoad(sourceMarker);
|
|
21545
21813
|
if (changed.length > 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-opencode",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.5.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit OpenCode plugin — native tools, adaptive policy, and sixteen method skills",
|
|
6
6
|
"keywords": [
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"typecheck": "tsc --noEmit"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@brainervirus/workit-core": "^8.
|
|
42
|
+
"@brainervirus/workit-core": "^8.5.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@opencode/plugin": "2.0.18"
|