ultimate-pi 0.20.0 → 0.22.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/.agents/skills/harness-decisions/SKILL.md +68 -2
- package/.agents/skills/harness-git-commit/SKILL.md +72 -0
- package/.agents/skills/harness-governor/SKILL.md +2 -2
- package/.agents/skills/harness-ls-lint-setup/SKILL.md +59 -0
- package/.agents/skills/harness-plan/SKILL.md +13 -11
- package/.agents/skills/harness-review/SKILL.md +1 -1
- package/.agents/skills/harness-sentrux-repair/SKILL.md +48 -0
- package/.agents/skills/sentrux/SKILL.md +4 -2
- package/.agents/skills/wiki-save/SKILL.md +1 -1
- package/.pi/PACKAGING.md +6 -0
- package/.pi/SYSTEM.md +21 -3
- package/.pi/agents/harness/ls-lint-steward.md +49 -0
- package/.pi/agents/harness/planning/decompose.md +4 -4
- package/.pi/agents/harness/reviewing/evaluator.md +1 -1
- package/.pi/agents/harness/running/executor.md +1 -1
- package/.pi/agents/harness/sentrux-repair-advisor.md +50 -0
- package/.pi/agents/pi-pi/prompt-expert.md +17 -2
- package/.pi/auto-commit.json +9 -2
- package/.pi/extensions/debate-orchestrator.ts +3 -0
- package/.pi/extensions/harness-anchored-edit.ts +7 -9
- package/.pi/extensions/harness-ask-user.ts +13 -34
- package/.pi/extensions/harness-debate-tools.ts +43 -4
- package/.pi/extensions/harness-live-widget.ts +28 -19
- package/.pi/extensions/harness-run-context.ts +278 -115
- package/.pi/extensions/harness-web-tools.ts +598 -471
- package/.pi/extensions/ls-lint-rules-sync.ts +103 -0
- package/.pi/extensions/observation-bus.ts +4 -0
- package/.pi/extensions/policy-gate.ts +270 -229
- package/.pi/extensions/sentrux-rules-sync.ts +2 -0
- package/.pi/extensions/soundboard.ts +48 -48
- package/.pi/harness/README.md +4 -0
- package/.pi/harness/agents.manifest.json +15 -7
- package/.pi/harness/agents.policy.yaml +49 -82
- package/.pi/harness/docs/adrs/0052-ls-lint-naming-lifecycle.md +45 -0
- package/.pi/harness/docs/adrs/0052-sentrux-structured-repair.md +38 -0
- package/.pi/harness/docs/adrs/0053-plan-task-clarification-gate.md +39 -0
- package/.pi/harness/docs/adrs/0054-harness-native-ask-user.md +40 -0
- package/.pi/harness/docs/adrs/0055-auto-commit-coauthor-lifecycle.md +40 -0
- package/.pi/harness/docs/adrs/README.md +5 -0
- package/.pi/harness/docs/practice-map.md +10 -5
- package/.pi/harness/evals/smoke/ls-lint-stub.json +10 -0
- package/.pi/harness/evolution/self-healing-rules.json +16 -0
- package/.pi/harness/ls-lint/naming.manifest.json +128 -0
- package/.pi/harness/sentrux/architecture.manifest.json +1 -1
- package/.pi/harness/specs/auto-commit.schema.json +63 -0
- package/.pi/harness/specs/ls-lint-manifest-proposal.schema.json +80 -0
- package/.pi/harness/specs/ls-lint-signal.schema.json +47 -0
- package/.pi/harness/specs/naming-manifest.schema.json +54 -0
- package/.pi/harness/specs/plan-task-clarification.schema.json +88 -0
- package/.pi/harness/specs/sentrux-diagnostics.schema.json +173 -0
- package/.pi/harness/specs/sentrux-repair-plan.schema.json +133 -0
- package/.pi/harness/specs/sentrux-report.schema.json +119 -0
- package/.pi/harness/specs/sentrux-signal.schema.json +34 -1
- package/.pi/lib/agents-policy.d.mts +26 -51
- package/.pi/lib/agents-policy.mjs +41 -28
- package/.pi/lib/agt/build-evaluation-context.ts +136 -64
- package/.pi/lib/ask-user/constants.mjs +3 -0
- package/.pi/lib/ask-user/constants.ts +4 -0
- package/.pi/lib/ask-user/contracts/glimpse-parse.ts +56 -0
- package/.pi/lib/ask-user/contracts/glimpse-payload-build.ts +58 -0
- package/.pi/lib/ask-user/contracts/glimpse-payload.ts +38 -0
- package/.pi/lib/ask-user/core/questionnaire.ts +74 -0
- package/.pi/lib/ask-user/dialog.ts +2 -314
- package/.pi/lib/ask-user/fallback.ts +2 -78
- package/.pi/lib/ask-user/format.ts +85 -0
- package/.pi/lib/ask-user/glimpseui.d.ts +10 -0
- package/.pi/lib/ask-user/index.ts +114 -0
- package/.pi/lib/ask-user/merge-task-clarification.ts +98 -0
- package/.pi/lib/ask-user/policy.mjs +43 -0
- package/.pi/lib/ask-user/policy.ts +104 -0
- package/.pi/lib/ask-user/presenters/glimpse.ts +130 -0
- package/.pi/lib/ask-user/presenters/headless.ts +131 -0
- package/.pi/lib/ask-user/presenters/select.ts +60 -0
- package/.pi/lib/ask-user/presenters/tui.ts +373 -0
- package/.pi/lib/ask-user/presenters/types.ts +13 -0
- package/.pi/lib/ask-user/render.ts +40 -9
- package/.pi/lib/ask-user/schema.ts +66 -13
- package/.pi/lib/ask-user/types.ts +60 -3
- package/.pi/lib/ask-user/validate-core.mjs +193 -7
- package/.pi/lib/ask-user/validate.ts +53 -34
- package/.pi/lib/harness-anchored-edit/package.json +3 -0
- package/.pi/lib/harness-artifact-gate.ts +75 -21
- package/.pi/lib/harness-auto-commit-config.mjs +321 -0
- package/.pi/lib/harness-lens/clients/lsp/client.ts +62 -39
- package/.pi/lib/harness-lens/clients/tool-policy.ts +73 -181
- package/.pi/lib/harness-lens/index.ts +241 -108
- package/.pi/lib/harness-lens/tools/lsp-navigation.ts +10 -8
- package/.pi/lib/harness-repair-brief.ts +84 -25
- package/.pi/lib/harness-run-context.ts +42 -52
- package/.pi/lib/harness-sentrux-parse.mjs +272 -0
- package/.pi/lib/harness-sentrux-root.mjs +78 -0
- package/.pi/lib/harness-slash-completions.ts +116 -0
- package/.pi/lib/harness-spawn-topology.ts +121 -87
- package/.pi/lib/harness-subagent-submit-registry.ts +10 -0
- package/.pi/lib/harness-subagents-bridge.ts +4 -1
- package/.pi/lib/harness-ui-state.ts +95 -48
- package/.pi/lib/plan-approval/dialog.ts +5 -0
- package/.pi/lib/plan-approval/validate.ts +1 -1
- package/.pi/lib/plan-approval-readiness.ts +32 -0
- package/.pi/lib/plan-debate-gate.ts +154 -114
- package/.pi/lib/plan-task-clarification.ts +158 -0
- package/.pi/prompts/harness-auto.md +2 -2
- package/.pi/prompts/harness-ls-lint-steward.md +43 -0
- package/.pi/prompts/harness-plan.md +58 -8
- package/.pi/prompts/harness-review.md +40 -6
- package/.pi/prompts/harness-run.md +33 -11
- package/.pi/prompts/harness-setup.md +72 -3
- package/.pi/prompts/harness-steer.md +2 -1
- package/.pi/prompts/wiki-save.md +5 -4
- package/.pi/scripts/README.md +8 -0
- package/.pi/scripts/generate-agents-policy-yaml.mjs +14 -2
- package/.pi/scripts/harness-auto-commit-bootstrap.mjs +96 -0
- package/.pi/scripts/harness-cli-verify.sh +47 -0
- package/.pi/scripts/harness-git-churn.mjs +77 -0
- package/.pi/scripts/harness-git-commit.mjs +173 -0
- package/.pi/scripts/harness-ls-lint-bootstrap.mjs +142 -0
- package/.pi/scripts/harness-ls-lint-cli.mjs +184 -0
- package/.pi/scripts/harness-seed-project-contracts.mjs +47 -0
- package/.pi/scripts/harness-sentrux-diagnostics.mjs +230 -0
- package/.pi/scripts/harness-sentrux-report.mjs +256 -0
- package/.pi/scripts/harness-verify.mjs +288 -125
- package/.pi/scripts/ls-lint-rules-sync.mjs +265 -0
- package/.pi/scripts/run-tests.mjs +1 -0
- package/.pi/settings.example.json +1 -0
- package/.sentrux/rules.toml +1 -1
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +25 -0
- package/README.md +13 -4
- package/package.json +5 -1
- package/vendor/pi-vcc/src/hooks/before-compact.ts +86 -60
|
@@ -1132,13 +1132,81 @@ export interface AutofixPolicyContext {
|
|
|
1132
1132
|
hasBiomeConfig?: boolean;
|
|
1133
1133
|
}
|
|
1134
1134
|
|
|
1135
|
+
const JS_TS_EXTENSIONS = new Set([
|
|
1136
|
+
".js",
|
|
1137
|
+
".jsx",
|
|
1138
|
+
".ts",
|
|
1139
|
+
".tsx",
|
|
1140
|
+
".mjs",
|
|
1141
|
+
".cjs",
|
|
1142
|
+
]);
|
|
1143
|
+
const PY_EXTENSIONS = new Set([".py", ".pyi"]);
|
|
1144
|
+
const KOTLIN_EXTENSIONS = new Set([".kt", ".kts"]);
|
|
1145
|
+
|
|
1146
|
+
function staticLinterPolicy(
|
|
1147
|
+
runner: LintRunnerName,
|
|
1148
|
+
gate: ToolGate = "smart-default",
|
|
1149
|
+
defaultWhenUnconfigured = true,
|
|
1150
|
+
): LinterPolicy {
|
|
1151
|
+
return {
|
|
1152
|
+
runnerNames: [runner],
|
|
1153
|
+
preferredRunners: [runner],
|
|
1154
|
+
defaultRunner: runner,
|
|
1155
|
+
defaultWhenUnconfigured,
|
|
1156
|
+
gate,
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
const STATIC_LINTER_POLICY_BY_EXTENSION = new Map<string, LinterPolicy>([
|
|
1161
|
+
[".css", staticLinterPolicy("stylelint")],
|
|
1162
|
+
[".scss", staticLinterPolicy("stylelint")],
|
|
1163
|
+
[".sass", staticLinterPolicy("stylelint")],
|
|
1164
|
+
[".less", staticLinterPolicy("stylelint")],
|
|
1165
|
+
[".sql", staticLinterPolicy("sqlfluff")],
|
|
1166
|
+
[".rb", staticLinterPolicy("rubocop")],
|
|
1167
|
+
[".rake", staticLinterPolicy("rubocop")],
|
|
1168
|
+
[".gemspec", staticLinterPolicy("rubocop")],
|
|
1169
|
+
[".ru", staticLinterPolicy("rubocop")],
|
|
1170
|
+
[".yaml", staticLinterPolicy("yamllint")],
|
|
1171
|
+
[".yml", staticLinterPolicy("yamllint")],
|
|
1172
|
+
[".md", staticLinterPolicy("markdownlint")],
|
|
1173
|
+
[".mdx", staticLinterPolicy("markdownlint")],
|
|
1174
|
+
[".html", staticLinterPolicy("htmlhint")],
|
|
1175
|
+
[".htm", staticLinterPolicy("htmlhint")],
|
|
1176
|
+
[".toml", staticLinterPolicy("taplo")],
|
|
1177
|
+
[".rs", staticLinterPolicy("rust-clippy")],
|
|
1178
|
+
[".sh", staticLinterPolicy("shellcheck")],
|
|
1179
|
+
[".bash", staticLinterPolicy("shellcheck")],
|
|
1180
|
+
[".fish", staticLinterPolicy("fish-indent")],
|
|
1181
|
+
[".tf", staticLinterPolicy("tflint")],
|
|
1182
|
+
[".tfvars", staticLinterPolicy("tflint")],
|
|
1183
|
+
[".ex", staticLinterPolicy("credo")],
|
|
1184
|
+
[".exs", staticLinterPolicy("credo")],
|
|
1185
|
+
[".eex", staticLinterPolicy("credo")],
|
|
1186
|
+
[".heex", staticLinterPolicy("credo")],
|
|
1187
|
+
[".leex", staticLinterPolicy("credo")],
|
|
1188
|
+
[".c", staticLinterPolicy("cpp-check")],
|
|
1189
|
+
[".cc", staticLinterPolicy("cpp-check")],
|
|
1190
|
+
[".cpp", staticLinterPolicy("cpp-check")],
|
|
1191
|
+
[".cxx", staticLinterPolicy("cpp-check")],
|
|
1192
|
+
[".h", staticLinterPolicy("cpp-check")],
|
|
1193
|
+
[".hpp", staticLinterPolicy("cpp-check")],
|
|
1194
|
+
[".ino", staticLinterPolicy("cpp-check")],
|
|
1195
|
+
[".dart", staticLinterPolicy("dart-analyze")],
|
|
1196
|
+
[".gleam", staticLinterPolicy("gleam-check")],
|
|
1197
|
+
[".ps1", staticLinterPolicy("psscriptanalyzer")],
|
|
1198
|
+
[".psm1", staticLinterPolicy("psscriptanalyzer")],
|
|
1199
|
+
[".psd1", staticLinterPolicy("psscriptanalyzer")],
|
|
1200
|
+
[".prisma", staticLinterPolicy("prisma-validate")],
|
|
1201
|
+
]);
|
|
1202
|
+
|
|
1135
1203
|
export function getLinterPolicyForFile(
|
|
1136
1204
|
filePath: string,
|
|
1137
1205
|
context: LinterPolicyContext = {},
|
|
1138
1206
|
): LinterPolicy | undefined {
|
|
1139
1207
|
const ext = path.extname(filePath).toLowerCase();
|
|
1140
1208
|
|
|
1141
|
-
if (
|
|
1209
|
+
if (JS_TS_EXTENSIONS.has(ext)) {
|
|
1142
1210
|
const policy = getJstsLintPolicy({
|
|
1143
1211
|
hasEslintConfig: context.hasEslintConfig,
|
|
1144
1212
|
hasOxlintConfig: context.hasOxlintConfig,
|
|
@@ -1154,7 +1222,7 @@ export function getLinterPolicyForFile(
|
|
|
1154
1222
|
};
|
|
1155
1223
|
}
|
|
1156
1224
|
|
|
1157
|
-
if (
|
|
1225
|
+
if (PY_EXTENSIONS.has(ext)) {
|
|
1158
1226
|
const preferredRunners: LintRunnerName[] = ["ruff-lint"];
|
|
1159
1227
|
if (context.hasMypyConfig) preferredRunners.push("mypy");
|
|
1160
1228
|
return {
|
|
@@ -1166,77 +1234,11 @@ export function getLinterPolicyForFile(
|
|
|
1166
1234
|
};
|
|
1167
1235
|
}
|
|
1168
1236
|
|
|
1169
|
-
if ([".css", ".scss", ".sass", ".less"].includes(ext)) {
|
|
1170
|
-
return {
|
|
1171
|
-
runnerNames: ["stylelint"],
|
|
1172
|
-
preferredRunners: ["stylelint"],
|
|
1173
|
-
defaultRunner: "stylelint",
|
|
1174
|
-
defaultWhenUnconfigured: true,
|
|
1175
|
-
gate: "smart-default",
|
|
1176
|
-
};
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
if (ext === ".sql") {
|
|
1180
|
-
return {
|
|
1181
|
-
runnerNames: ["sqlfluff"],
|
|
1182
|
-
preferredRunners: ["sqlfluff"],
|
|
1183
|
-
defaultRunner: "sqlfluff",
|
|
1184
|
-
defaultWhenUnconfigured: true,
|
|
1185
|
-
gate: "smart-default",
|
|
1186
|
-
};
|
|
1187
|
-
}
|
|
1188
|
-
|
|
1189
|
-
if ([".rb", ".rake", ".gemspec", ".ru"].includes(ext)) {
|
|
1190
|
-
return {
|
|
1191
|
-
runnerNames: ["rubocop"],
|
|
1192
|
-
preferredRunners: ["rubocop"],
|
|
1193
|
-
defaultRunner: "rubocop",
|
|
1194
|
-
defaultWhenUnconfigured: true,
|
|
1195
|
-
gate: "smart-default",
|
|
1196
|
-
};
|
|
1197
|
-
}
|
|
1198
|
-
|
|
1199
|
-
if ([".yaml", ".yml"].includes(ext)) {
|
|
1200
|
-
return {
|
|
1201
|
-
runnerNames: ["yamllint"],
|
|
1202
|
-
preferredRunners: ["yamllint"],
|
|
1203
|
-
defaultRunner: "yamllint",
|
|
1204
|
-
defaultWhenUnconfigured: true,
|
|
1205
|
-
gate: "smart-default",
|
|
1206
|
-
};
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
if ([".md", ".mdx"].includes(ext)) {
|
|
1210
|
-
return {
|
|
1211
|
-
runnerNames: ["markdownlint"],
|
|
1212
|
-
preferredRunners: ["markdownlint"],
|
|
1213
|
-
defaultRunner: "markdownlint",
|
|
1214
|
-
defaultWhenUnconfigured: true,
|
|
1215
|
-
gate: "smart-default",
|
|
1216
|
-
};
|
|
1217
|
-
}
|
|
1218
|
-
|
|
1219
|
-
if ([".html", ".htm"].includes(ext)) {
|
|
1220
|
-
return {
|
|
1221
|
-
runnerNames: ["htmlhint"],
|
|
1222
|
-
preferredRunners: ["htmlhint"],
|
|
1223
|
-
defaultRunner: "htmlhint",
|
|
1224
|
-
defaultWhenUnconfigured: true,
|
|
1225
|
-
gate: "smart-default",
|
|
1226
|
-
};
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
1237
|
if (path.basename(filePath).toLowerCase() === "dockerfile") {
|
|
1230
|
-
return
|
|
1231
|
-
runnerNames: ["hadolint"],
|
|
1232
|
-
preferredRunners: ["hadolint"],
|
|
1233
|
-
defaultRunner: "hadolint",
|
|
1234
|
-
defaultWhenUnconfigured: true,
|
|
1235
|
-
gate: "smart-default",
|
|
1236
|
-
};
|
|
1238
|
+
return staticLinterPolicy("hadolint");
|
|
1237
1239
|
}
|
|
1238
1240
|
|
|
1239
|
-
if (
|
|
1241
|
+
if (KOTLIN_EXTENSIONS.has(ext)) {
|
|
1240
1242
|
const preferredRunners: LintRunnerName[] = ["ktlint"];
|
|
1241
1243
|
if (context.hasDetektConfig) preferredRunners.push("detekt");
|
|
1242
1244
|
return {
|
|
@@ -1248,16 +1250,6 @@ export function getLinterPolicyForFile(
|
|
|
1248
1250
|
};
|
|
1249
1251
|
}
|
|
1250
1252
|
|
|
1251
|
-
if (ext === ".toml") {
|
|
1252
|
-
return {
|
|
1253
|
-
runnerNames: ["taplo"],
|
|
1254
|
-
preferredRunners: ["taplo"],
|
|
1255
|
-
defaultRunner: "taplo",
|
|
1256
|
-
defaultWhenUnconfigured: true,
|
|
1257
|
-
gate: "smart-default",
|
|
1258
|
-
};
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
1253
|
if (ext === ".go") {
|
|
1262
1254
|
return {
|
|
1263
1255
|
runnerNames: ["golangci-lint"],
|
|
@@ -1278,107 +1270,7 @@ export function getLinterPolicyForFile(
|
|
|
1278
1270
|
};
|
|
1279
1271
|
}
|
|
1280
1272
|
|
|
1281
|
-
|
|
1282
|
-
return {
|
|
1283
|
-
runnerNames: ["rust-clippy"],
|
|
1284
|
-
preferredRunners: ["rust-clippy"],
|
|
1285
|
-
defaultRunner: "rust-clippy",
|
|
1286
|
-
defaultWhenUnconfigured: true,
|
|
1287
|
-
gate: "smart-default",
|
|
1288
|
-
};
|
|
1289
|
-
}
|
|
1290
|
-
|
|
1291
|
-
if ([".sh", ".bash"].includes(ext)) {
|
|
1292
|
-
return {
|
|
1293
|
-
runnerNames: ["shellcheck"],
|
|
1294
|
-
preferredRunners: ["shellcheck"],
|
|
1295
|
-
defaultRunner: "shellcheck",
|
|
1296
|
-
defaultWhenUnconfigured: true,
|
|
1297
|
-
gate: "smart-default",
|
|
1298
|
-
};
|
|
1299
|
-
}
|
|
1300
|
-
|
|
1301
|
-
if (ext === ".fish") {
|
|
1302
|
-
return {
|
|
1303
|
-
runnerNames: ["fish-indent"],
|
|
1304
|
-
preferredRunners: ["fish-indent"],
|
|
1305
|
-
defaultRunner: "fish-indent",
|
|
1306
|
-
defaultWhenUnconfigured: true,
|
|
1307
|
-
gate: "smart-default",
|
|
1308
|
-
};
|
|
1309
|
-
}
|
|
1310
|
-
|
|
1311
|
-
if ([".tf", ".tfvars"].includes(ext)) {
|
|
1312
|
-
return {
|
|
1313
|
-
runnerNames: ["tflint"],
|
|
1314
|
-
preferredRunners: ["tflint"],
|
|
1315
|
-
defaultRunner: "tflint",
|
|
1316
|
-
defaultWhenUnconfigured: true,
|
|
1317
|
-
gate: "smart-default",
|
|
1318
|
-
};
|
|
1319
|
-
}
|
|
1320
|
-
|
|
1321
|
-
if ([".ex", ".exs", ".eex", ".heex", ".leex"].includes(ext)) {
|
|
1322
|
-
return {
|
|
1323
|
-
runnerNames: ["credo"],
|
|
1324
|
-
preferredRunners: ["credo"],
|
|
1325
|
-
defaultRunner: "credo",
|
|
1326
|
-
defaultWhenUnconfigured: true,
|
|
1327
|
-
gate: "smart-default",
|
|
1328
|
-
};
|
|
1329
|
-
}
|
|
1330
|
-
|
|
1331
|
-
if ([".c", ".cc", ".cpp", ".cxx", ".h", ".hpp", ".ino"].includes(ext)) {
|
|
1332
|
-
return {
|
|
1333
|
-
runnerNames: ["cpp-check"],
|
|
1334
|
-
preferredRunners: ["cpp-check"],
|
|
1335
|
-
defaultRunner: "cpp-check",
|
|
1336
|
-
defaultWhenUnconfigured: true,
|
|
1337
|
-
gate: "smart-default",
|
|
1338
|
-
};
|
|
1339
|
-
}
|
|
1340
|
-
|
|
1341
|
-
if (ext === ".dart") {
|
|
1342
|
-
return {
|
|
1343
|
-
runnerNames: ["dart-analyze"],
|
|
1344
|
-
preferredRunners: ["dart-analyze"],
|
|
1345
|
-
defaultRunner: "dart-analyze",
|
|
1346
|
-
defaultWhenUnconfigured: true,
|
|
1347
|
-
gate: "smart-default",
|
|
1348
|
-
};
|
|
1349
|
-
}
|
|
1350
|
-
|
|
1351
|
-
if (ext === ".gleam") {
|
|
1352
|
-
return {
|
|
1353
|
-
runnerNames: ["gleam-check"],
|
|
1354
|
-
preferredRunners: ["gleam-check"],
|
|
1355
|
-
defaultRunner: "gleam-check",
|
|
1356
|
-
defaultWhenUnconfigured: true,
|
|
1357
|
-
gate: "smart-default",
|
|
1358
|
-
};
|
|
1359
|
-
}
|
|
1360
|
-
|
|
1361
|
-
if ([".ps1", ".psm1", ".psd1"].includes(ext)) {
|
|
1362
|
-
return {
|
|
1363
|
-
runnerNames: ["psscriptanalyzer"],
|
|
1364
|
-
preferredRunners: ["psscriptanalyzer"],
|
|
1365
|
-
defaultRunner: "psscriptanalyzer",
|
|
1366
|
-
defaultWhenUnconfigured: true,
|
|
1367
|
-
gate: "smart-default",
|
|
1368
|
-
};
|
|
1369
|
-
}
|
|
1370
|
-
|
|
1371
|
-
if (ext === ".prisma") {
|
|
1372
|
-
return {
|
|
1373
|
-
runnerNames: ["prisma-validate"],
|
|
1374
|
-
preferredRunners: ["prisma-validate"],
|
|
1375
|
-
defaultRunner: "prisma-validate",
|
|
1376
|
-
defaultWhenUnconfigured: true,
|
|
1377
|
-
gate: "smart-default",
|
|
1378
|
-
};
|
|
1379
|
-
}
|
|
1380
|
-
|
|
1381
|
-
return undefined;
|
|
1273
|
+
return STATIC_LINTER_POLICY_BY_EXTENSION.get(ext);
|
|
1382
1274
|
}
|
|
1383
1275
|
|
|
1384
1276
|
export function getLinterPolicyForCwd(
|
|
@@ -336,57 +336,101 @@ function applyEditAutopatch(
|
|
|
336
336
|
return undefined;
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
getFlag?: (name: string) => boolean | undefined;
|
|
346
|
-
};
|
|
347
|
-
const piFlags = pi as PiWithFlags;
|
|
348
|
-
const readCliFlag = (name: string): boolean | undefined => {
|
|
349
|
-
if (typeof piFlags.getFlag === "function") return piFlags.getFlag(name);
|
|
350
|
-
return process.argv.includes(`--${name}`) ? true : undefined;
|
|
351
|
-
};
|
|
352
|
-
const getFlag = (name: string) =>
|
|
353
|
-
getLensFlag(name, readCliFlag, globalConfig);
|
|
354
|
-
|
|
339
|
+
function registerLensRuntimePart1(
|
|
340
|
+
pi: ExtensionAPI,
|
|
341
|
+
getFlag: (name: string) => boolean | string | undefined,
|
|
342
|
+
runtime: RuntimeCoordinator,
|
|
343
|
+
lensEnabledRef: { current: boolean },
|
|
344
|
+
) {
|
|
355
345
|
pi.registerFlag("no-lens", {
|
|
356
346
|
description: "Disable harness-lens for this session.",
|
|
357
347
|
type: "boolean",
|
|
358
348
|
default: false,
|
|
359
349
|
});
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function registerLensRuntimePart2(
|
|
353
|
+
pi: ExtensionAPI,
|
|
354
|
+
getFlag: (name: string) => boolean | string | undefined,
|
|
355
|
+
runtime: RuntimeCoordinator,
|
|
356
|
+
lensEnabledRef: { current: boolean },
|
|
357
|
+
) {
|
|
360
358
|
pi.registerFlag("no-lsp", {
|
|
361
359
|
description: "Disable LSP auto-touch and lsp_* tools backing servers.",
|
|
362
360
|
type: "boolean",
|
|
363
361
|
default: false,
|
|
364
362
|
});
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function registerLensRuntimePart3(
|
|
366
|
+
pi: ExtensionAPI,
|
|
367
|
+
getFlag: (name: string) => boolean | string | undefined,
|
|
368
|
+
runtime: RuntimeCoordinator,
|
|
369
|
+
lensEnabledRef: { current: boolean },
|
|
370
|
+
) {
|
|
365
371
|
pi.registerFlag("no-autoformat", {
|
|
366
372
|
description: "Disable auto-format on write/edit.",
|
|
367
373
|
type: "boolean",
|
|
368
374
|
default: false,
|
|
369
375
|
});
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function registerLensRuntimePart4(
|
|
379
|
+
pi: ExtensionAPI,
|
|
380
|
+
getFlag: (name: string) => boolean | string | undefined,
|
|
381
|
+
runtime: RuntimeCoordinator,
|
|
382
|
+
lensEnabledRef: { current: boolean },
|
|
383
|
+
) {
|
|
370
384
|
pi.registerFlag("immediate-format", {
|
|
371
385
|
description: "Format during tool_result instead of deferring to agent_end.",
|
|
372
386
|
type: "boolean",
|
|
373
387
|
default: false,
|
|
374
388
|
});
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function registerLensRuntimePart5(
|
|
392
|
+
pi: ExtensionAPI,
|
|
393
|
+
getFlag: (name: string) => boolean | string | undefined,
|
|
394
|
+
runtime: RuntimeCoordinator,
|
|
395
|
+
lensEnabledRef: { current: boolean },
|
|
396
|
+
) {
|
|
375
397
|
pi.registerFlag("lens-guard", {
|
|
376
398
|
description: "Block git commit/push while unresolved lens blockers exist.",
|
|
377
399
|
type: "boolean",
|
|
378
400
|
default: false,
|
|
379
401
|
});
|
|
402
|
+
}
|
|
380
403
|
|
|
404
|
+
function registerLensRuntimePart6(
|
|
405
|
+
pi: ExtensionAPI,
|
|
406
|
+
getFlag: (name: string) => boolean | string | undefined,
|
|
407
|
+
runtime: RuntimeCoordinator,
|
|
408
|
+
lensEnabledRef: { current: boolean },
|
|
409
|
+
) {
|
|
381
410
|
pi.registerTool(createLspDiagnosticsTool());
|
|
382
|
-
|
|
411
|
+
}
|
|
383
412
|
|
|
413
|
+
function registerLensRuntimePart7(
|
|
414
|
+
pi: ExtensionAPI,
|
|
415
|
+
getFlag: (name: string) => boolean | string | undefined,
|
|
416
|
+
runtime: RuntimeCoordinator,
|
|
417
|
+
lensEnabledRef: { current: boolean },
|
|
418
|
+
) {
|
|
419
|
+
pi.registerTool(createLspNavigationTool(getFlag));
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function registerLensRuntimePart8(
|
|
423
|
+
pi: ExtensionAPI,
|
|
424
|
+
getFlag: (name: string) => boolean | string | undefined,
|
|
425
|
+
runtime: RuntimeCoordinator,
|
|
426
|
+
lensEnabledRef: { current: boolean },
|
|
427
|
+
) {
|
|
384
428
|
pi.on("session_start", async (_event, ctx) => {
|
|
385
429
|
if (getFlag("no-lens")) {
|
|
386
|
-
|
|
430
|
+
lensEnabledRef.current = false;
|
|
387
431
|
return;
|
|
388
432
|
}
|
|
389
|
-
|
|
433
|
+
lensEnabledRef.current = true;
|
|
390
434
|
runtime.resetForSession();
|
|
391
435
|
clearWidgetState();
|
|
392
436
|
resetFormatService();
|
|
@@ -416,15 +460,126 @@ export default function harnessLensExtension(pi: ExtensionAPI): void {
|
|
|
416
460
|
});
|
|
417
461
|
}
|
|
418
462
|
});
|
|
463
|
+
}
|
|
419
464
|
|
|
465
|
+
function registerLensRuntimePart9(
|
|
466
|
+
pi: ExtensionAPI,
|
|
467
|
+
getFlag: (name: string) => boolean | string | undefined,
|
|
468
|
+
runtime: RuntimeCoordinator,
|
|
469
|
+
lensEnabledRef: { current: boolean },
|
|
470
|
+
) {
|
|
420
471
|
pi.on("turn_start", () => {
|
|
421
|
-
if (!
|
|
472
|
+
if (!lensEnabledRef.current) return;
|
|
422
473
|
runtime.beginTurn();
|
|
423
474
|
clearLastAnalyzedStateCache();
|
|
424
475
|
});
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
async function ensureToolCallLspConfig(args: {
|
|
479
|
+
getFlag: (name: string) => boolean | string | undefined;
|
|
480
|
+
filePath: string | undefined;
|
|
481
|
+
ctx: any;
|
|
482
|
+
runtime: RuntimeCoordinator;
|
|
483
|
+
}): Promise<void> {
|
|
484
|
+
if (args.getFlag("no-lsp")) return;
|
|
485
|
+
try {
|
|
486
|
+
await ensureLSPConfigInitialized(
|
|
487
|
+
args.filePath
|
|
488
|
+
? path.dirname(args.filePath)
|
|
489
|
+
: (args.ctx.cwd ?? args.runtime.projectRoot),
|
|
490
|
+
);
|
|
491
|
+
} catch (err) {
|
|
492
|
+
dbg(`tool_call lsp config init failed: ${err}`);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
function maybeAutoTouchLspOnToolCall(args: {
|
|
497
|
+
getFlag: (name: string) => boolean | string | undefined;
|
|
498
|
+
toolName: string;
|
|
499
|
+
filePath: string;
|
|
500
|
+
runtime: RuntimeCoordinator;
|
|
501
|
+
}): void {
|
|
502
|
+
if (
|
|
503
|
+
args.getFlag("no-lsp") ||
|
|
504
|
+
!isLspCapableFile(args.filePath) ||
|
|
505
|
+
shouldSkipLspAutoTouch(args.filePath, args.runtime.projectRoot)
|
|
506
|
+
) {
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
const shouldWarmRead =
|
|
510
|
+
args.toolName === "read" && args.runtime.shouldWarmLspOnRead(args.filePath);
|
|
511
|
+
const shouldTouch =
|
|
512
|
+
args.toolName === "write" ||
|
|
513
|
+
args.toolName === "edit" ||
|
|
514
|
+
args.toolName === "lsp_navigation" ||
|
|
515
|
+
shouldWarmRead;
|
|
516
|
+
if (!shouldTouch) return;
|
|
517
|
+
try {
|
|
518
|
+
const content = nodeFs.readFileSync(args.filePath, "utf-8");
|
|
519
|
+
if (args.toolName === "read")
|
|
520
|
+
args.runtime.markLspReadWarmStarted(args.filePath);
|
|
521
|
+
void getLSPService()
|
|
522
|
+
.touchFile(args.filePath, content, {
|
|
523
|
+
diagnostics: "none",
|
|
524
|
+
source: `tool_call:${args.toolName}`,
|
|
525
|
+
})
|
|
526
|
+
.then((result) => {
|
|
527
|
+
if (args.toolName !== "read") return;
|
|
528
|
+
if (result === undefined)
|
|
529
|
+
args.runtime.clearLspReadWarmState(args.filePath);
|
|
530
|
+
else args.runtime.markLspReadWarmCompleted(args.filePath);
|
|
531
|
+
})
|
|
532
|
+
.catch((err) => {
|
|
533
|
+
if (args.toolName === "read") {
|
|
534
|
+
args.runtime.clearLspReadWarmState(args.filePath);
|
|
535
|
+
}
|
|
536
|
+
dbg(`lsp auto-touch failed: ${err}`);
|
|
537
|
+
});
|
|
538
|
+
} catch {
|
|
539
|
+
if (args.toolName === "read")
|
|
540
|
+
args.runtime.clearLspReadWarmState(args.filePath);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
425
543
|
|
|
544
|
+
function applyEditAutopatchForToolCall(
|
|
545
|
+
filePath: string,
|
|
546
|
+
event: unknown,
|
|
547
|
+
ctx: unknown,
|
|
548
|
+
) {
|
|
549
|
+
if (
|
|
550
|
+
!isToolCallEventType(
|
|
551
|
+
"edit",
|
|
552
|
+
event as Parameters<typeof isToolCallEventType>[1],
|
|
553
|
+
)
|
|
554
|
+
) {
|
|
555
|
+
return undefined;
|
|
556
|
+
}
|
|
557
|
+
const editInput = (event as { input?: unknown }).input;
|
|
558
|
+
if (isAnchoredEditToolInput(editInput)) {
|
|
559
|
+
return applyAnchoredEditAutopatch(
|
|
560
|
+
filePath,
|
|
561
|
+
editInput,
|
|
562
|
+
anchoredEditTaskId({
|
|
563
|
+
sessionId: (ctx as { sessionId?: string }).sessionId,
|
|
564
|
+
}),
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
const legacyInput = editInput as {
|
|
568
|
+
oldText?: string;
|
|
569
|
+
newText?: string;
|
|
570
|
+
edits?: Array<{ oldText?: string; newText?: string }>;
|
|
571
|
+
};
|
|
572
|
+
return applyEditAutopatch(filePath, legacyInput);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
function registerLensRuntimePart10(
|
|
576
|
+
pi: ExtensionAPI,
|
|
577
|
+
getFlag: (name: string) => boolean | string | undefined,
|
|
578
|
+
runtime: RuntimeCoordinator,
|
|
579
|
+
lensEnabledRef: { current: boolean },
|
|
580
|
+
) {
|
|
426
581
|
pi.on("tool_call", async (event, ctx) => {
|
|
427
|
-
if (!
|
|
582
|
+
if (!lensEnabledRef.current) return;
|
|
428
583
|
|
|
429
584
|
const toolName = (event as { toolName?: string }).toolName ?? "";
|
|
430
585
|
if (
|
|
@@ -442,100 +597,33 @@ export default function harnessLensExtension(pi: ExtensionAPI): void {
|
|
|
442
597
|
runtime.projectRoot,
|
|
443
598
|
);
|
|
444
599
|
|
|
445
|
-
|
|
446
|
-
try {
|
|
447
|
-
await ensureLSPConfigInitialized(
|
|
448
|
-
filePath ? path.dirname(filePath) : (ctx.cwd ?? runtime.projectRoot),
|
|
449
|
-
);
|
|
450
|
-
} catch (err) {
|
|
451
|
-
dbg(`tool_call lsp config init failed: ${err}`);
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
|
|
600
|
+
await ensureToolCallLspConfig({ getFlag, filePath, ctx, runtime });
|
|
455
601
|
if (!filePath || !nodeFs.existsSync(filePath)) return;
|
|
456
602
|
if (isPathIgnoredByProject(filePath, runtime.projectRoot, false)) return;
|
|
457
603
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
!shouldSkipLspAutoTouch(filePath, runtime.projectRoot)
|
|
462
|
-
) {
|
|
463
|
-
const shouldWarmRead =
|
|
464
|
-
toolName === "read" && runtime.shouldWarmLspOnRead(filePath);
|
|
465
|
-
const shouldTouch =
|
|
466
|
-
toolName === "write" ||
|
|
467
|
-
toolName === "edit" ||
|
|
468
|
-
toolName === "lsp_navigation" ||
|
|
469
|
-
shouldWarmRead;
|
|
470
|
-
if (shouldTouch) {
|
|
471
|
-
try {
|
|
472
|
-
const content = nodeFs.readFileSync(filePath, "utf-8");
|
|
473
|
-
if (toolName === "read") runtime.markLspReadWarmStarted(filePath);
|
|
474
|
-
void getLSPService()
|
|
475
|
-
.touchFile(filePath, content, {
|
|
476
|
-
diagnostics: "none",
|
|
477
|
-
source: `tool_call:${toolName}`,
|
|
478
|
-
})
|
|
479
|
-
.then((result) => {
|
|
480
|
-
if (toolName === "read") {
|
|
481
|
-
if (result === undefined) {
|
|
482
|
-
runtime.clearLspReadWarmState(filePath);
|
|
483
|
-
} else {
|
|
484
|
-
runtime.markLspReadWarmCompleted(filePath);
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
})
|
|
488
|
-
.catch((err) => {
|
|
489
|
-
if (toolName === "read") runtime.clearLspReadWarmState(filePath);
|
|
490
|
-
dbg(`lsp auto-touch failed: ${err}`);
|
|
491
|
-
});
|
|
492
|
-
} catch {
|
|
493
|
-
if (toolName === "read") runtime.clearLspReadWarmState(filePath);
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
if (
|
|
499
|
-
isToolCallEventType(
|
|
500
|
-
"edit",
|
|
501
|
-
event as Parameters<typeof isToolCallEventType>[1],
|
|
502
|
-
)
|
|
503
|
-
) {
|
|
504
|
-
const editInput = (event as { input?: unknown }).input;
|
|
505
|
-
if (isAnchoredEditToolInput(editInput)) {
|
|
506
|
-
const block = applyAnchoredEditAutopatch(
|
|
507
|
-
filePath,
|
|
508
|
-
editInput,
|
|
509
|
-
anchoredEditTaskId({
|
|
510
|
-
sessionId: (ctx as { sessionId?: string }).sessionId,
|
|
511
|
-
}),
|
|
512
|
-
);
|
|
513
|
-
if (block) return block;
|
|
514
|
-
} else {
|
|
515
|
-
const legacyInput = editInput as {
|
|
516
|
-
oldText?: string;
|
|
517
|
-
newText?: string;
|
|
518
|
-
edits?: Array<{ oldText?: string; newText?: string }>;
|
|
519
|
-
};
|
|
520
|
-
const block = applyEditAutopatch(filePath, legacyInput);
|
|
521
|
-
if (block) return block;
|
|
522
|
-
}
|
|
523
|
-
}
|
|
604
|
+
maybeAutoTouchLspOnToolCall({ getFlag, toolName, filePath, runtime });
|
|
605
|
+
const block = applyEditAutopatchForToolCall(filePath, event, ctx);
|
|
606
|
+
if (block) return block;
|
|
524
607
|
});
|
|
608
|
+
}
|
|
525
609
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
});
|
|
535
|
-
});
|
|
610
|
+
function registerLensRuntimePart11(
|
|
611
|
+
pi: ExtensionAPI,
|
|
612
|
+
getFlag: (name: string) => boolean | string | undefined,
|
|
613
|
+
runtime: RuntimeCoordinator,
|
|
614
|
+
lensEnabledRef: { current: boolean },
|
|
615
|
+
) {
|
|
616
|
+
pi as any;
|
|
617
|
+
}
|
|
536
618
|
|
|
619
|
+
function registerLensRuntimePart12(
|
|
620
|
+
pi: ExtensionAPI,
|
|
621
|
+
getFlag: (name: string) => boolean | string | undefined,
|
|
622
|
+
runtime: RuntimeCoordinator,
|
|
623
|
+
lensEnabledRef: { current: boolean },
|
|
624
|
+
) {
|
|
537
625
|
pi.on("agent_end", async (_event, ctx) => {
|
|
538
|
-
if (!
|
|
626
|
+
if (!lensEnabledRef.current) return;
|
|
539
627
|
await handleAgentEnd({
|
|
540
628
|
ctxCwd: ctx.cwd,
|
|
541
629
|
getFlag,
|
|
@@ -547,3 +635,48 @@ export default function harnessLensExtension(pi: ExtensionAPI): void {
|
|
|
547
635
|
});
|
|
548
636
|
});
|
|
549
637
|
}
|
|
638
|
+
|
|
639
|
+
function registerHarnessLensRuntime(
|
|
640
|
+
pi: ExtensionAPI,
|
|
641
|
+
args: {
|
|
642
|
+
getFlag: (name: string) => boolean | string | undefined;
|
|
643
|
+
runtime: RuntimeCoordinator;
|
|
644
|
+
lensEnabledRef: { current: boolean };
|
|
645
|
+
},
|
|
646
|
+
) {
|
|
647
|
+
const { getFlag, runtime, lensEnabledRef } = args;
|
|
648
|
+
registerLensRuntimePart1(pi, getFlag, runtime, lensEnabledRef);
|
|
649
|
+
registerLensRuntimePart2(pi, getFlag, runtime, lensEnabledRef);
|
|
650
|
+
registerLensRuntimePart3(pi, getFlag, runtime, lensEnabledRef);
|
|
651
|
+
registerLensRuntimePart4(pi, getFlag, runtime, lensEnabledRef);
|
|
652
|
+
registerLensRuntimePart5(pi, getFlag, runtime, lensEnabledRef);
|
|
653
|
+
registerLensRuntimePart6(pi, getFlag, runtime, lensEnabledRef);
|
|
654
|
+
registerLensRuntimePart7(pi, getFlag, runtime, lensEnabledRef);
|
|
655
|
+
registerLensRuntimePart8(pi, getFlag, runtime, lensEnabledRef);
|
|
656
|
+
registerLensRuntimePart9(pi, getFlag, runtime, lensEnabledRef);
|
|
657
|
+
registerLensRuntimePart10(pi, getFlag, runtime, lensEnabledRef);
|
|
658
|
+
registerLensRuntimePart11(pi, getFlag, runtime, lensEnabledRef);
|
|
659
|
+
registerLensRuntimePart12(pi, getFlag, runtime, lensEnabledRef);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
export default function harnessLensExtension(pi: ExtensionAPI): void {
|
|
663
|
+
initLensEvents(pi);
|
|
664
|
+
const globalConfig = loadPiLensGlobalConfig();
|
|
665
|
+
const lensEnabledRef = { current: !globalConfig.noLens };
|
|
666
|
+
|
|
667
|
+
type PiWithFlags = ExtensionAPI & {
|
|
668
|
+
getFlag?: (name: string) => boolean | string | undefined;
|
|
669
|
+
};
|
|
670
|
+
const piFlags = pi as PiWithFlags;
|
|
671
|
+
const readCliFlag = (name: string): boolean | undefined => {
|
|
672
|
+
if (typeof piFlags.getFlag === "function") {
|
|
673
|
+
const flag = piFlags.getFlag(name);
|
|
674
|
+
return typeof flag === "boolean" ? flag : undefined;
|
|
675
|
+
}
|
|
676
|
+
return process.argv.includes(`--${name}`) ? true : undefined;
|
|
677
|
+
};
|
|
678
|
+
const getFlag = (name: string) =>
|
|
679
|
+
getLensFlag(name, readCliFlag, globalConfig);
|
|
680
|
+
|
|
681
|
+
registerHarnessLensRuntime(pi, { getFlag, runtime, lensEnabledRef });
|
|
682
|
+
}
|