@brainervirus/workit-cursor 1.3.0 → 1.3.2
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/.cursor-plugin/plugin.json +1 -1
- package/dist/cursor-session-start.js +41 -33
- package/dist/mcp-server.js +74 -37
- package/dist/workit-hook.js +43 -33
- package/package.json +3 -3
|
@@ -10270,6 +10270,26 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
10270
10270
|
return glob;
|
|
10271
10271
|
const real = realpathOf(prefix.replace(/\/+$/, "") || "/");
|
|
10272
10272
|
return real + (prefix.endsWith("/") ? "/" : "") + rest;
|
|
10273
|
+
}, globSpecificity = (glob) => glob.replaceAll("\\", "/").split("/").filter((segment) => segment.length > 0 && !/[*?[\]{]/.test(segment)).length, selectWorkspaceMatch = (matches, cwd, workspaceName) => {
|
|
10274
|
+
if (workspaceName !== undefined) {
|
|
10275
|
+
const named = matches.filter((entry) => entry.name === workspaceName);
|
|
10276
|
+
if (named.length === 1)
|
|
10277
|
+
return named[0];
|
|
10278
|
+
if (named.length > 1)
|
|
10279
|
+
throw new Error(`ambiguous workspace ${JSON.stringify(workspaceName)} for ${cwd}`);
|
|
10280
|
+
if (matches.length > 0) {
|
|
10281
|
+
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}; matching choices: ${matches.map((entry) => entry.name).join(", ")}`);
|
|
10282
|
+
}
|
|
10283
|
+
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}`);
|
|
10284
|
+
}
|
|
10285
|
+
if (matches.length < 2)
|
|
10286
|
+
return matches[0];
|
|
10287
|
+
const highestSpecificity = Math.max(...matches.map((entry) => globSpecificity(entry.glob)));
|
|
10288
|
+
const mostSpecific = matches.filter((entry) => globSpecificity(entry.glob) === highestSpecificity);
|
|
10289
|
+
if (mostSpecific.length > 1) {
|
|
10290
|
+
throw new Error(`ambiguous workspace for ${cwd}; choose one of: ${mostSpecific.map((entry) => entry.name).join(", ")}`);
|
|
10291
|
+
}
|
|
10292
|
+
return mostSpecific[0];
|
|
10273
10293
|
}, resolveWorkspaceFrom = (cwd, dir, workspaceName) => {
|
|
10274
10294
|
const result = readWorkspacesResult(dir);
|
|
10275
10295
|
if (result.status === "malformed" || result.status === "invalid")
|
|
@@ -10289,20 +10309,7 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
10289
10309
|
if (matched)
|
|
10290
10310
|
matches.push(ws);
|
|
10291
10311
|
}
|
|
10292
|
-
|
|
10293
|
-
const selected = matches.find((ws) => ws.name === workspaceName);
|
|
10294
|
-
if (!selected && matches.length > 0) {
|
|
10295
|
-
const matchingNames = matches.map((ws) => ws.name);
|
|
10296
|
-
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}; matching choices: ${matchingNames.join(", ")}`);
|
|
10297
|
-
}
|
|
10298
|
-
if (selected)
|
|
10299
|
-
return selected;
|
|
10300
|
-
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}`);
|
|
10301
|
-
}
|
|
10302
|
-
if (matches.length > 1) {
|
|
10303
|
-
throw new Error(`ambiguous workspace for ${cwd}; choose one of: ${matches.map((ws) => ws.name).join(", ")}`);
|
|
10304
|
-
}
|
|
10305
|
-
return matches[0] ?? null;
|
|
10312
|
+
return selectWorkspaceMatch(matches, cwd, workspaceName) ?? null;
|
|
10306
10313
|
}, runtimeWorkspacePolicySchema = (kind) => {
|
|
10307
10314
|
const key = kind === "branch" ? "branchPolicy" : kind === "commit" ? "commitPolicy" : "vcs";
|
|
10308
10315
|
const policySchema = kind === "branch" ? workspaceBranchPolicySchema : kind === "commit" ? workspaceCommitPolicySchema : object({
|
|
@@ -10353,21 +10360,7 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
10353
10360
|
return targets.some((target) => matchWorkspace(glob, target) || canonical !== glob && matchWorkspace(canonical, target));
|
|
10354
10361
|
});
|
|
10355
10362
|
const workspaceName = process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined;
|
|
10356
|
-
|
|
10357
|
-
if (workspaceName) {
|
|
10358
|
-
const named = matches.filter((entry) => entry.name === workspaceName);
|
|
10359
|
-
if (named.length === 1)
|
|
10360
|
-
selected = named[0];
|
|
10361
|
-
else if (named.length > 1)
|
|
10362
|
-
throw new Error(`ambiguous workspace ${JSON.stringify(workspaceName)} for ${cwd}`);
|
|
10363
|
-
else if (matches.length)
|
|
10364
|
-
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}; matching choices: ${matches.map((entry) => entry.name).join(", ")}`);
|
|
10365
|
-
else
|
|
10366
|
-
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}`);
|
|
10367
|
-
} else if (matches.length > 1)
|
|
10368
|
-
throw new Error(`ambiguous workspace for ${cwd}; choose one of: ${matches.map((entry) => entry.name).join(", ")}`);
|
|
10369
|
-
else
|
|
10370
|
-
selected = matches[0];
|
|
10363
|
+
const selected = selectWorkspaceMatch(matches, cwd, workspaceName);
|
|
10371
10364
|
if (!selected)
|
|
10372
10365
|
return null;
|
|
10373
10366
|
const policy = runtimeWorkspacePolicySchema(kind).safeParse(selected);
|
|
@@ -11905,6 +11898,15 @@ need zero Workit task, assessment, or writer calls. Use one compact tracked
|
|
|
11905
11898
|
record only when handoff, dependent steps, concurrent actors, or meaningful
|
|
11906
11899
|
decisions make continuity useful; similar titles alone never merge tasks.
|
|
11907
11900
|
|
|
11901
|
+
For a routine user-authorized branch or commit, prefer native host Git/shell
|
|
11902
|
+
tools from the outset when managed coordination or outcome reconciliation is
|
|
11903
|
+
not needed. Inspect the actual target checkout and its configured conventions;
|
|
11904
|
+
use Workit's read-only context/policy tools when needed. Do not start a task,
|
|
11905
|
+
acquire a writer, or mint a decision receipt solely for a native Git action.
|
|
11906
|
+
Native permissions still apply. Never switch execution paths to evade a denial
|
|
11907
|
+
or repeat an uncertain managed effect. A local-commit endpoint does not imply
|
|
11908
|
+
PR readiness, a fresh review, or post-commit assessment/closure paperwork.
|
|
11909
|
+
|
|
11908
11910
|
For tracked work, inspect its current state and use the shared operations for
|
|
11909
11911
|
task, policy, evidence, finding, decision, worker, writer, and state changes.
|
|
11910
11912
|
Start a record once for an explicit tracked objective; assess or reassess only
|
|
@@ -11926,6 +11928,11 @@ Preserve uncertain external outcomes and reconcile repository/provider state
|
|
|
11926
11928
|
before retrying. Internal reservations prevent duplicate or ambiguous effects;
|
|
11927
11929
|
they are not permission tickets for every edit.
|
|
11928
11930
|
|
|
11931
|
+
On OpenCode V1 and V2, use native host tools for external mutations. Workit
|
|
11932
|
+
provides read-only workit_context; it has no managed external-action executor.
|
|
11933
|
+
Do not create proposals or request Workit approvals merely to invoke native
|
|
11934
|
+
tools. Old uncertain managed effects still require evidence before any retry.
|
|
11935
|
+
|
|
11929
11936
|
Use host-native authorization through the host's supported path. A native
|
|
11930
11937
|
question receipt records an actual question interaction; it is not automatic
|
|
11931
11938
|
host permission. Record a meaningful user choice once with provenance when
|
|
@@ -12266,6 +12273,7 @@ function resolveRequirements(input) {
|
|
|
12266
12273
|
dependentAction: null,
|
|
12267
12274
|
acceptanceAllowed: false
|
|
12268
12275
|
}));
|
|
12276
|
+
const independentBehaviorReview = input.preferences?.thorough === true || input.assessment.consequences.some((consequence) => ["security", "data", "public_contract", "operations"].includes(consequence.area));
|
|
12269
12277
|
if (signals.behaviorChange.value === true)
|
|
12270
12278
|
requirements.push(requirement({
|
|
12271
12279
|
ruleId: "behavioral-verification",
|
|
@@ -12277,14 +12285,14 @@ function resolveRequirements(input) {
|
|
|
12277
12285
|
dependentAction: null,
|
|
12278
12286
|
acceptanceAllowed: false
|
|
12279
12287
|
}), requirement({
|
|
12280
|
-
ruleId: "fresh-context-review",
|
|
12288
|
+
ruleId: independentBehaviorReview ? "fresh-context-review" : "self-review",
|
|
12281
12289
|
dimension: "review",
|
|
12282
12290
|
scope,
|
|
12283
|
-
reason: "
|
|
12284
|
-
satisfaction: "A separate review context examines the current candidate and records its result.",
|
|
12291
|
+
reason: independentBehaviorReview ? "Consequential behavior or the thorough preference requires fresh-context review." : "Bounded behavior changes use self-review unless consequential risks or trusted rules require more.",
|
|
12292
|
+
satisfaction: independentBehaviorReview ? "A separate review context examines the current candidate and records its result." : "The lead reviews the resulting diff and records the relevant scope and checks.",
|
|
12285
12293
|
before: "close",
|
|
12286
12294
|
dependentAction: null,
|
|
12287
|
-
acceptanceAllowed:
|
|
12295
|
+
acceptanceAllowed: !independentBehaviorReview
|
|
12288
12296
|
}));
|
|
12289
12297
|
else if (signals.mechanicalLowRisk.value === true)
|
|
12290
12298
|
requirements.push(requirement({
|
package/dist/mcp-server.js
CHANGED
|
@@ -20757,7 +20757,47 @@ function operationJsonSchema(family) {
|
|
|
20757
20757
|
return toJSONSchema(operationSchemas[family], { target: "draft-2020-12" });
|
|
20758
20758
|
}
|
|
20759
20759
|
var OPERATION_SCHEMA_DEPTH = 1;
|
|
20760
|
-
var
|
|
20760
|
+
var schemaShapeDescription = (value, depth = 0) => {
|
|
20761
|
+
if (!value || typeof value !== "object")
|
|
20762
|
+
return "value";
|
|
20763
|
+
const schema = value;
|
|
20764
|
+
if (Array.isArray(schema.oneOf) || Array.isArray(schema.anyOf)) {
|
|
20765
|
+
const options = Array.isArray(schema.oneOf) ? schema.oneOf : schema.anyOf;
|
|
20766
|
+
return `(${options.map((option) => schemaShapeDescription(option, depth)).join("|")})`;
|
|
20767
|
+
}
|
|
20768
|
+
if (schema.const !== undefined)
|
|
20769
|
+
return `=${JSON.stringify(schema.const)}`;
|
|
20770
|
+
if (Array.isArray(schema.enum))
|
|
20771
|
+
return `[${schema.enum.map(String).join("|")}]`;
|
|
20772
|
+
const type = Array.isArray(schema.type) ? schema.type.join("/") : schema.type;
|
|
20773
|
+
if (type === "array")
|
|
20774
|
+
return `arr<${schemaShapeDescription(schema.items, depth)}>`;
|
|
20775
|
+
if (type === "object" && schema.properties && typeof schema.properties === "object") {
|
|
20776
|
+
if (depth >= 2)
|
|
20777
|
+
return "obj";
|
|
20778
|
+
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
20779
|
+
const properties = schema.properties;
|
|
20780
|
+
const fields = Object.entries(properties).map(([name, child]) => `${name}${required.has(name) ? "!" : ""}:${schemaShapeDescription(child, depth + 1)}`);
|
|
20781
|
+
return `obj{${fields.join(",")}}`;
|
|
20782
|
+
}
|
|
20783
|
+
if (typeof type !== "string")
|
|
20784
|
+
return "?";
|
|
20785
|
+
return type.split("/").map((part) => ({ string: "str", boolean: "bool", number: "num", null: "null" })[part] ?? part).join("|");
|
|
20786
|
+
};
|
|
20787
|
+
var canonicalFieldsDescription = (value) => {
|
|
20788
|
+
if (Array.isArray(value))
|
|
20789
|
+
return `Canonical object fields: ${value.join(", ")}. Workit validates the complete nested value.`;
|
|
20790
|
+
const isZodType = (schema) => ("_zod" in schema) && typeof schema._zod === "object";
|
|
20791
|
+
const schema = isZodType(value) ? toJSONSchema(value, { target: "draft-2020-12" }) : value;
|
|
20792
|
+
if (!schema.properties || typeof schema.properties !== "object") {
|
|
20793
|
+
const variants = Array.isArray(schema.oneOf) ? schema.oneOf : Array.isArray(schema.anyOf) ? schema.anyOf : null;
|
|
20794
|
+
return variants ? `Canonical shapes: ${variants.map((variant) => schemaShapeDescription(variant)).join(" | ")}. Full nested value is validated.` : "Canonical nested value; Workit validates the complete value.";
|
|
20795
|
+
}
|
|
20796
|
+
const properties = schema.properties;
|
|
20797
|
+
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
20798
|
+
const fields = Object.entries(properties).map(([name, child]) => `${name}${required.has(name) ? "!" : ""}:${schemaShapeDescription(child)}`);
|
|
20799
|
+
return `Fields (! required): ${fields.join(", ")}. Full nested value is validated.`;
|
|
20800
|
+
};
|
|
20761
20801
|
function boundedOperationJsonSchema(family, maxDepth = OPERATION_SCHEMA_DEPTH, stringifiedObjects = false) {
|
|
20762
20802
|
const tolerate = (projected) => {
|
|
20763
20803
|
if (!stringifiedObjects)
|
|
@@ -20781,9 +20821,10 @@ function boundedOperationJsonSchema(family, maxDepth = OPERATION_SCHEMA_DEPTH, s
|
|
|
20781
20821
|
return node;
|
|
20782
20822
|
const record = node;
|
|
20783
20823
|
if (record.properties && typeof record.properties === "object") {
|
|
20784
|
-
const
|
|
20824
|
+
const properties = record.properties;
|
|
20825
|
+
const fields = Object.keys(properties);
|
|
20785
20826
|
if (currentDepth >= maxDepth || fields.length === 0) {
|
|
20786
|
-
const description = stringifiedObjects ? `${canonicalFieldsDescription(
|
|
20827
|
+
const description = stringifiedObjects ? `${canonicalFieldsDescription(record)} A JSON-encoded string is also accepted.` : canonicalFieldsDescription(record);
|
|
20787
20828
|
return tolerate({ type: "object", description });
|
|
20788
20829
|
}
|
|
20789
20830
|
return tolerate({
|
|
@@ -23075,6 +23116,28 @@ var canonicalGlob = (glob) => {
|
|
|
23075
23116
|
const real = realpathOf(prefix.replace(/\/+$/, "") || "/");
|
|
23076
23117
|
return real + (prefix.endsWith("/") ? "/" : "") + rest;
|
|
23077
23118
|
};
|
|
23119
|
+
var globSpecificity = (glob) => glob.replaceAll("\\", "/").split("/").filter((segment) => segment.length > 0 && !/[*?[\]{]/.test(segment)).length;
|
|
23120
|
+
var selectWorkspaceMatch = (matches, cwd, workspaceName) => {
|
|
23121
|
+
if (workspaceName !== undefined) {
|
|
23122
|
+
const named = matches.filter((entry) => entry.name === workspaceName);
|
|
23123
|
+
if (named.length === 1)
|
|
23124
|
+
return named[0];
|
|
23125
|
+
if (named.length > 1)
|
|
23126
|
+
throw new Error(`ambiguous workspace ${JSON.stringify(workspaceName)} for ${cwd}`);
|
|
23127
|
+
if (matches.length > 0) {
|
|
23128
|
+
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}; matching choices: ${matches.map((entry) => entry.name).join(", ")}`);
|
|
23129
|
+
}
|
|
23130
|
+
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}`);
|
|
23131
|
+
}
|
|
23132
|
+
if (matches.length < 2)
|
|
23133
|
+
return matches[0];
|
|
23134
|
+
const highestSpecificity = Math.max(...matches.map((entry) => globSpecificity(entry.glob)));
|
|
23135
|
+
const mostSpecific = matches.filter((entry) => globSpecificity(entry.glob) === highestSpecificity);
|
|
23136
|
+
if (mostSpecific.length > 1) {
|
|
23137
|
+
throw new Error(`ambiguous workspace for ${cwd}; choose one of: ${mostSpecific.map((entry) => entry.name).join(", ")}`);
|
|
23138
|
+
}
|
|
23139
|
+
return mostSpecific[0];
|
|
23140
|
+
};
|
|
23078
23141
|
var resolveWorkspaceFrom = (cwd, dir, workspaceName) => {
|
|
23079
23142
|
const result = readWorkspacesResult(dir);
|
|
23080
23143
|
if (result.status === "malformed" || result.status === "invalid")
|
|
@@ -23094,20 +23157,7 @@ var resolveWorkspaceFrom = (cwd, dir, workspaceName) => {
|
|
|
23094
23157
|
if (matched)
|
|
23095
23158
|
matches.push(ws);
|
|
23096
23159
|
}
|
|
23097
|
-
|
|
23098
|
-
const selected = matches.find((ws) => ws.name === workspaceName);
|
|
23099
|
-
if (!selected && matches.length > 0) {
|
|
23100
|
-
const matchingNames = matches.map((ws) => ws.name);
|
|
23101
|
-
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}; matching choices: ${matchingNames.join(", ")}`);
|
|
23102
|
-
}
|
|
23103
|
-
if (selected)
|
|
23104
|
-
return selected;
|
|
23105
|
-
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}`);
|
|
23106
|
-
}
|
|
23107
|
-
if (matches.length > 1) {
|
|
23108
|
-
throw new Error(`ambiguous workspace for ${cwd}; choose one of: ${matches.map((ws) => ws.name).join(", ")}`);
|
|
23109
|
-
}
|
|
23110
|
-
return matches[0] ?? null;
|
|
23160
|
+
return selectWorkspaceMatch(matches, cwd, workspaceName) ?? null;
|
|
23111
23161
|
};
|
|
23112
23162
|
var runtimeWorkspacePolicySchema = (kind) => {
|
|
23113
23163
|
const key = kind === "branch" ? "branchPolicy" : kind === "commit" ? "commitPolicy" : "vcs";
|
|
@@ -23164,21 +23214,7 @@ var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
|
|
|
23164
23214
|
return targets.some((target) => matchWorkspace(glob, target) || canonical !== glob && matchWorkspace(canonical, target));
|
|
23165
23215
|
});
|
|
23166
23216
|
const workspaceName = process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined;
|
|
23167
|
-
|
|
23168
|
-
if (workspaceName) {
|
|
23169
|
-
const named = matches.filter((entry) => entry.name === workspaceName);
|
|
23170
|
-
if (named.length === 1)
|
|
23171
|
-
selected = named[0];
|
|
23172
|
-
else if (named.length > 1)
|
|
23173
|
-
throw new Error(`ambiguous workspace ${JSON.stringify(workspaceName)} for ${cwd}`);
|
|
23174
|
-
else if (matches.length)
|
|
23175
|
-
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}; matching choices: ${matches.map((entry) => entry.name).join(", ")}`);
|
|
23176
|
-
else
|
|
23177
|
-
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}`);
|
|
23178
|
-
} else if (matches.length > 1)
|
|
23179
|
-
throw new Error(`ambiguous workspace for ${cwd}; choose one of: ${matches.map((entry) => entry.name).join(", ")}`);
|
|
23180
|
-
else
|
|
23181
|
-
selected = matches[0];
|
|
23217
|
+
const selected = selectWorkspaceMatch(matches, cwd, workspaceName);
|
|
23182
23218
|
if (!selected)
|
|
23183
23219
|
return null;
|
|
23184
23220
|
const policy = runtimeWorkspacePolicySchema(kind).safeParse(selected);
|
|
@@ -25107,6 +25143,7 @@ function resolveRequirements(input) {
|
|
|
25107
25143
|
dependentAction: null,
|
|
25108
25144
|
acceptanceAllowed: false
|
|
25109
25145
|
}));
|
|
25146
|
+
const independentBehaviorReview = input.preferences?.thorough === true || input.assessment.consequences.some((consequence) => ["security", "data", "public_contract", "operations"].includes(consequence.area));
|
|
25110
25147
|
if (signals.behaviorChange.value === true)
|
|
25111
25148
|
requirements.push(requirement({
|
|
25112
25149
|
ruleId: "behavioral-verification",
|
|
@@ -25118,14 +25155,14 @@ function resolveRequirements(input) {
|
|
|
25118
25155
|
dependentAction: null,
|
|
25119
25156
|
acceptanceAllowed: false
|
|
25120
25157
|
}), requirement({
|
|
25121
|
-
ruleId: "fresh-context-review",
|
|
25158
|
+
ruleId: independentBehaviorReview ? "fresh-context-review" : "self-review",
|
|
25122
25159
|
dimension: "review",
|
|
25123
25160
|
scope,
|
|
25124
|
-
reason: "
|
|
25125
|
-
satisfaction: "A separate review context examines the current candidate and records its result.",
|
|
25161
|
+
reason: independentBehaviorReview ? "Consequential behavior or the thorough preference requires fresh-context review." : "Bounded behavior changes use self-review unless consequential risks or trusted rules require more.",
|
|
25162
|
+
satisfaction: independentBehaviorReview ? "A separate review context examines the current candidate and records its result." : "The lead reviews the resulting diff and records the relevant scope and checks.",
|
|
25126
25163
|
before: "close",
|
|
25127
25164
|
dependentAction: null,
|
|
25128
|
-
acceptanceAllowed:
|
|
25165
|
+
acceptanceAllowed: !independentBehaviorReview
|
|
25129
25166
|
}));
|
|
25130
25167
|
else if (signals.mechanicalLowRisk.value === true)
|
|
25131
25168
|
requirements.push(requirement({
|
|
@@ -27694,7 +27731,7 @@ var CHANGELOG_RULES = `- Use an [Unreleased] section.
|
|
|
27694
27731
|
- Entries should be human-readable and user-facing.
|
|
27695
27732
|
- Do not use raw commit messages as changelog bullets.
|
|
27696
27733
|
- MERGE into existing ### Category under [Unreleased] — never append a second ### Added / ### Fixed block.
|
|
27697
|
-
- Apply with the native
|
|
27734
|
+
- Apply with the host-native editor, preserving the repository changelog conventions.
|
|
27698
27735
|
- If Unreleased already has duplicate category headings, normalize_only first.`;
|
|
27699
27736
|
function changelogContext(root, range) {
|
|
27700
27737
|
const cwd = path13.resolve(repoRoot(root));
|
package/dist/workit-hook.js
CHANGED
|
@@ -10300,6 +10300,28 @@ var canonicalGlob = (glob) => {
|
|
|
10300
10300
|
const real = realpathOf(prefix.replace(/\/+$/, "") || "/");
|
|
10301
10301
|
return real + (prefix.endsWith("/") ? "/" : "") + rest;
|
|
10302
10302
|
};
|
|
10303
|
+
var globSpecificity = (glob) => glob.replaceAll("\\", "/").split("/").filter((segment) => segment.length > 0 && !/[*?[\]{]/.test(segment)).length;
|
|
10304
|
+
var selectWorkspaceMatch = (matches, cwd, workspaceName) => {
|
|
10305
|
+
if (workspaceName !== undefined) {
|
|
10306
|
+
const named = matches.filter((entry) => entry.name === workspaceName);
|
|
10307
|
+
if (named.length === 1)
|
|
10308
|
+
return named[0];
|
|
10309
|
+
if (named.length > 1)
|
|
10310
|
+
throw new Error(`ambiguous workspace ${JSON.stringify(workspaceName)} for ${cwd}`);
|
|
10311
|
+
if (matches.length > 0) {
|
|
10312
|
+
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}; matching choices: ${matches.map((entry) => entry.name).join(", ")}`);
|
|
10313
|
+
}
|
|
10314
|
+
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}`);
|
|
10315
|
+
}
|
|
10316
|
+
if (matches.length < 2)
|
|
10317
|
+
return matches[0];
|
|
10318
|
+
const highestSpecificity = Math.max(...matches.map((entry) => globSpecificity(entry.glob)));
|
|
10319
|
+
const mostSpecific = matches.filter((entry) => globSpecificity(entry.glob) === highestSpecificity);
|
|
10320
|
+
if (mostSpecific.length > 1) {
|
|
10321
|
+
throw new Error(`ambiguous workspace for ${cwd}; choose one of: ${mostSpecific.map((entry) => entry.name).join(", ")}`);
|
|
10322
|
+
}
|
|
10323
|
+
return mostSpecific[0];
|
|
10324
|
+
};
|
|
10303
10325
|
var resolveWorkspaceFrom = (cwd, dir, workspaceName) => {
|
|
10304
10326
|
const result = readWorkspacesResult(dir);
|
|
10305
10327
|
if (result.status === "malformed" || result.status === "invalid")
|
|
@@ -10319,20 +10341,7 @@ var resolveWorkspaceFrom = (cwd, dir, workspaceName) => {
|
|
|
10319
10341
|
if (matched)
|
|
10320
10342
|
matches.push(ws);
|
|
10321
10343
|
}
|
|
10322
|
-
|
|
10323
|
-
const selected = matches.find((ws) => ws.name === workspaceName);
|
|
10324
|
-
if (!selected && matches.length > 0) {
|
|
10325
|
-
const matchingNames = matches.map((ws) => ws.name);
|
|
10326
|
-
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}; matching choices: ${matchingNames.join(", ")}`);
|
|
10327
|
-
}
|
|
10328
|
-
if (selected)
|
|
10329
|
-
return selected;
|
|
10330
|
-
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}`);
|
|
10331
|
-
}
|
|
10332
|
-
if (matches.length > 1) {
|
|
10333
|
-
throw new Error(`ambiguous workspace for ${cwd}; choose one of: ${matches.map((ws) => ws.name).join(", ")}`);
|
|
10334
|
-
}
|
|
10335
|
-
return matches[0] ?? null;
|
|
10344
|
+
return selectWorkspaceMatch(matches, cwd, workspaceName) ?? null;
|
|
10336
10345
|
};
|
|
10337
10346
|
var runtimeWorkspacePolicySchema = (kind) => {
|
|
10338
10347
|
const key = kind === "branch" ? "branchPolicy" : kind === "commit" ? "commitPolicy" : "vcs";
|
|
@@ -10389,21 +10398,7 @@ var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
|
|
|
10389
10398
|
return targets.some((target) => matchWorkspace(glob, target) || canonical !== glob && matchWorkspace(canonical, target));
|
|
10390
10399
|
});
|
|
10391
10400
|
const workspaceName = process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined;
|
|
10392
|
-
|
|
10393
|
-
if (workspaceName) {
|
|
10394
|
-
const named = matches.filter((entry) => entry.name === workspaceName);
|
|
10395
|
-
if (named.length === 1)
|
|
10396
|
-
selected = named[0];
|
|
10397
|
-
else if (named.length > 1)
|
|
10398
|
-
throw new Error(`ambiguous workspace ${JSON.stringify(workspaceName)} for ${cwd}`);
|
|
10399
|
-
else if (matches.length)
|
|
10400
|
-
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}; matching choices: ${matches.map((entry) => entry.name).join(", ")}`);
|
|
10401
|
-
else
|
|
10402
|
-
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}`);
|
|
10403
|
-
} else if (matches.length > 1)
|
|
10404
|
-
throw new Error(`ambiguous workspace for ${cwd}; choose one of: ${matches.map((entry) => entry.name).join(", ")}`);
|
|
10405
|
-
else
|
|
10406
|
-
selected = matches[0];
|
|
10401
|
+
const selected = selectWorkspaceMatch(matches, cwd, workspaceName);
|
|
10407
10402
|
if (!selected)
|
|
10408
10403
|
return null;
|
|
10409
10404
|
const policy = runtimeWorkspacePolicySchema(kind).safeParse(selected);
|
|
@@ -11844,6 +11839,15 @@ need zero Workit task, assessment, or writer calls. Use one compact tracked
|
|
|
11844
11839
|
record only when handoff, dependent steps, concurrent actors, or meaningful
|
|
11845
11840
|
decisions make continuity useful; similar titles alone never merge tasks.
|
|
11846
11841
|
|
|
11842
|
+
For a routine user-authorized branch or commit, prefer native host Git/shell
|
|
11843
|
+
tools from the outset when managed coordination or outcome reconciliation is
|
|
11844
|
+
not needed. Inspect the actual target checkout and its configured conventions;
|
|
11845
|
+
use Workit's read-only context/policy tools when needed. Do not start a task,
|
|
11846
|
+
acquire a writer, or mint a decision receipt solely for a native Git action.
|
|
11847
|
+
Native permissions still apply. Never switch execution paths to evade a denial
|
|
11848
|
+
or repeat an uncertain managed effect. A local-commit endpoint does not imply
|
|
11849
|
+
PR readiness, a fresh review, or post-commit assessment/closure paperwork.
|
|
11850
|
+
|
|
11847
11851
|
For tracked work, inspect its current state and use the shared operations for
|
|
11848
11852
|
task, policy, evidence, finding, decision, worker, writer, and state changes.
|
|
11849
11853
|
Start a record once for an explicit tracked objective; assess or reassess only
|
|
@@ -11865,6 +11869,11 @@ Preserve uncertain external outcomes and reconcile repository/provider state
|
|
|
11865
11869
|
before retrying. Internal reservations prevent duplicate or ambiguous effects;
|
|
11866
11870
|
they are not permission tickets for every edit.
|
|
11867
11871
|
|
|
11872
|
+
On OpenCode V1 and V2, use native host tools for external mutations. Workit
|
|
11873
|
+
provides read-only workit_context; it has no managed external-action executor.
|
|
11874
|
+
Do not create proposals or request Workit approvals merely to invoke native
|
|
11875
|
+
tools. Old uncertain managed effects still require evidence before any retry.
|
|
11876
|
+
|
|
11868
11877
|
Use host-native authorization through the host's supported path. A native
|
|
11869
11878
|
question receipt records an actual question interaction; it is not automatic
|
|
11870
11879
|
host permission. Record a meaningful user choice once with provenance when
|
|
@@ -12281,6 +12290,7 @@ function resolveRequirements(input) {
|
|
|
12281
12290
|
dependentAction: null,
|
|
12282
12291
|
acceptanceAllowed: false
|
|
12283
12292
|
}));
|
|
12293
|
+
const independentBehaviorReview = input.preferences?.thorough === true || input.assessment.consequences.some((consequence) => ["security", "data", "public_contract", "operations"].includes(consequence.area));
|
|
12284
12294
|
if (signals.behaviorChange.value === true)
|
|
12285
12295
|
requirements.push(requirement({
|
|
12286
12296
|
ruleId: "behavioral-verification",
|
|
@@ -12292,14 +12302,14 @@ function resolveRequirements(input) {
|
|
|
12292
12302
|
dependentAction: null,
|
|
12293
12303
|
acceptanceAllowed: false
|
|
12294
12304
|
}), requirement({
|
|
12295
|
-
ruleId: "fresh-context-review",
|
|
12305
|
+
ruleId: independentBehaviorReview ? "fresh-context-review" : "self-review",
|
|
12296
12306
|
dimension: "review",
|
|
12297
12307
|
scope,
|
|
12298
|
-
reason: "
|
|
12299
|
-
satisfaction: "A separate review context examines the current candidate and records its result.",
|
|
12308
|
+
reason: independentBehaviorReview ? "Consequential behavior or the thorough preference requires fresh-context review." : "Bounded behavior changes use self-review unless consequential risks or trusted rules require more.",
|
|
12309
|
+
satisfaction: independentBehaviorReview ? "A separate review context examines the current candidate and records its result." : "The lead reviews the resulting diff and records the relevant scope and checks.",
|
|
12300
12310
|
before: "close",
|
|
12301
12311
|
dependentAction: null,
|
|
12302
|
-
acceptanceAllowed:
|
|
12312
|
+
acceptanceAllowed: !independentBehaviorReview
|
|
12303
12313
|
}));
|
|
12304
12314
|
else if (signals.mechanicalLowRisk.value === true)
|
|
12305
12315
|
requirements.push(requirement({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-cursor",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit Cursor plugin — shared MCP transport, native hooks, and fourteen method skills",
|
|
6
6
|
"keywords": [
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"build": "bun scripts/build.ts"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@brainervirus/workit-core": "^1.3.
|
|
48
|
-
"@brainervirus/workit-mcp": "^1.3.
|
|
47
|
+
"@brainervirus/workit-core": "^1.3.2",
|
|
48
|
+
"@brainervirus/workit-mcp": "^1.3.2"
|
|
49
49
|
},
|
|
50
50
|
"engines": {
|
|
51
51
|
"node": ">=24"
|