hunter-harness 0.2.13 → 0.2.14
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/dist/bin.js +69 -10
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -4388,30 +4388,70 @@ function assertPreviewAllowed(preview, skip) {
|
|
|
4388
4388
|
}
|
|
4389
4389
|
}
|
|
4390
4390
|
var CREDENTIALS_HINT = "\u53EF\u5728\u4EA4\u4E92\u6A21\u5F0F\u4E0B\u5F55\u5165\uFF0C\u6216\u5199\u5165 .harness/credentials.local.yaml\uFF08\u52FF\u63D0\u4EA4 git\uFF09";
|
|
4391
|
-
var
|
|
4391
|
+
var CONFLICT_PREVIEW_LIMIT = 8;
|
|
4392
|
+
function conflictGroup(path) {
|
|
4393
|
+
const knowledgeMatch = path.match(/^\.harness\/knowledge\/entries\/([^/]+)\//);
|
|
4394
|
+
if (knowledgeMatch?.[1] !== void 0) {
|
|
4395
|
+
return `knowledge/${knowledgeMatch[1]}`;
|
|
4396
|
+
}
|
|
4397
|
+
if (path.startsWith(".harness/knowledge/"))
|
|
4398
|
+
return "knowledge/other";
|
|
4399
|
+
if (path === ".harness/context-index.json")
|
|
4400
|
+
return "context-index";
|
|
4401
|
+
return path.split("/", 1)[0] ?? "other";
|
|
4402
|
+
}
|
|
4403
|
+
function conflictGroups(conflicts) {
|
|
4404
|
+
const groups = {};
|
|
4405
|
+
for (const conflict2 of conflicts) {
|
|
4406
|
+
const group = conflictGroup(conflict2.path);
|
|
4407
|
+
groups[group] = (groups[group] ?? 0) + 1;
|
|
4408
|
+
}
|
|
4409
|
+
return groups;
|
|
4410
|
+
}
|
|
4411
|
+
function formatStaleBaselineMessage(conflicts = []) {
|
|
4412
|
+
const lines = [
|
|
4413
|
+
"\u670D\u52A1\u7AEF\u5B58\u5728\u672C\u5730\u5C1A\u672A\u786E\u8BA4\u7684\u66F4\u65B0\uFF0Cpush \u5DF2\u6682\u505C\u4EE5\u907F\u514D\u8986\u76D6\u5E76\u884C\u4FEE\u6539\u3002"
|
|
4414
|
+
];
|
|
4415
|
+
if (conflicts.length > 0) {
|
|
4416
|
+
lines.push(`\u68C0\u6D4B\u5230 ${conflicts.length} \u4E2A\u51B2\u7A81\uFF08\u4EC5\u5C55\u793A\u524D ${CONFLICT_PREVIEW_LIMIT} \u4E2A\uFF09\uFF1A`);
|
|
4417
|
+
for (const conflict2 of conflicts.slice(0, CONFLICT_PREVIEW_LIMIT)) {
|
|
4418
|
+
lines.push(` - ${conflict2.path}`);
|
|
4419
|
+
}
|
|
4420
|
+
if (conflicts.length > CONFLICT_PREVIEW_LIMIT) {
|
|
4421
|
+
lines.push(` - \u2026\u53E6 ${conflicts.length - CONFLICT_PREVIEW_LIMIT} \u4E2A`);
|
|
4422
|
+
}
|
|
4423
|
+
}
|
|
4424
|
+
lines.push("\u4FDD\u7559\u672C\u5730\u5E76\u7EE7\u7EED\uFF1Anpx hunter-harness update --conflict-strategy keep-local --yes", "\u63A5\u53D7\u670D\u52A1\u7AEF\u7248\u672C\uFF1Anpx hunter-harness update --conflict-strategy accept-remote --yes", "\u9010\u9879\u5904\u7406\uFF1Anpx hunter-harness update --resolve <path>=keep-local|accept-remote");
|
|
4425
|
+
return lines.join("\n");
|
|
4426
|
+
}
|
|
4392
4427
|
function staleBaselineError(code, conflicts) {
|
|
4393
|
-
const
|
|
4394
|
-
return new PushWorkflowError(
|
|
4428
|
+
const conflictList = [...conflicts ?? []];
|
|
4429
|
+
return new PushWorkflowError(formatStaleBaselineMessage(conflictList), 5, code, conflictList.length === 0 ? void 0 : {
|
|
4430
|
+
conflicts: conflictList,
|
|
4431
|
+
conflict_count: conflictList.length,
|
|
4432
|
+
conflict_groups: conflictGroups(conflictList)
|
|
4433
|
+
});
|
|
4395
4434
|
}
|
|
4396
|
-
async function syncToLatest(root, project, baseline, client) {
|
|
4435
|
+
async function syncToLatest(root, project, baseline, client, confirmConflictStrategy) {
|
|
4397
4436
|
const syncResult = await synchronizeArtifacts({
|
|
4398
4437
|
projectRoot: root,
|
|
4399
4438
|
project,
|
|
4400
4439
|
client,
|
|
4401
4440
|
requestId: uuidV7(),
|
|
4402
4441
|
dryRun: false,
|
|
4403
|
-
conflictStrategy: "manual"
|
|
4442
|
+
conflictStrategy: "manual",
|
|
4443
|
+
...confirmConflictStrategy === void 0 ? {} : { confirmConflictStrategy }
|
|
4404
4444
|
}, baseline);
|
|
4405
4445
|
if (syncResult.conflicts.length > 0) {
|
|
4406
4446
|
throw staleBaselineError("PROJECT_VERSION_CONFLICT", syncResult.conflicts);
|
|
4407
4447
|
}
|
|
4408
4448
|
return await readBaseline(root);
|
|
4409
4449
|
}
|
|
4410
|
-
async function autoRebaseIfServerAdvanced(root, project, baseline, client, remoteVersion) {
|
|
4450
|
+
async function autoRebaseIfServerAdvanced(root, project, baseline, client, remoteVersion, confirmConflictStrategy) {
|
|
4411
4451
|
if (remoteVersion === baseline.complete_project_version) {
|
|
4412
4452
|
return baseline;
|
|
4413
4453
|
}
|
|
4414
|
-
const updated = await syncToLatest(root, project, baseline, client);
|
|
4454
|
+
const updated = await syncToLatest(root, project, baseline, client, confirmConflictStrategy);
|
|
4415
4455
|
if (remoteVersion !== null && updated.complete_project_version !== remoteVersion) {
|
|
4416
4456
|
throw staleBaselineError("PROJECT_VERSION_CONFLICT");
|
|
4417
4457
|
}
|
|
@@ -4508,7 +4548,7 @@ async function pushProject(options) {
|
|
|
4508
4548
|
const boundAtStart = project.project.project_id;
|
|
4509
4549
|
if (boundAtStart !== null) {
|
|
4510
4550
|
const remote = await client.getProject(boundAtStart, uuidV7());
|
|
4511
|
-
baseline = await autoRebaseIfServerAdvanced(root, project, baseline, client, remote.latest_project_version);
|
|
4551
|
+
baseline = await autoRebaseIfServerAdvanced(root, project, baseline, client, remote.latest_project_version, options.confirmConflictStrategy);
|
|
4512
4552
|
preview = makePreview(baseline, await managedFiles(root, project), options.confirmedProjectLocal ?? [], installedPaths);
|
|
4513
4553
|
}
|
|
4514
4554
|
const initialSkip = await resolveSensitiveScanSkip(preview, options);
|
|
@@ -4628,7 +4668,7 @@ async function pushProject(options) {
|
|
|
4628
4668
|
} catch (error) {
|
|
4629
4669
|
if (error instanceof ApiError && (error.code === "STALE_PUSH" || error.code === "PROJECT_VERSION_CONFLICT") && !finalizeRetried) {
|
|
4630
4670
|
finalizeRetried = true;
|
|
4631
|
-
baseline = await syncToLatest(root, project, baseline, client);
|
|
4671
|
+
baseline = await syncToLatest(root, project, baseline, client, options.confirmConflictStrategy);
|
|
4632
4672
|
workflow = resetSession(workflow, proposalManifestHash);
|
|
4633
4673
|
await atomicWriteJson(workflowPath, workflow);
|
|
4634
4674
|
session = await client.createProposalSession(projectId, {
|
|
@@ -5799,6 +5839,24 @@ async function runCleanup(options, dependencies) {
|
|
|
5799
5839
|
}
|
|
5800
5840
|
|
|
5801
5841
|
// src/commands/push.ts
|
|
5842
|
+
var CONFLICT_PREVIEW_LIMIT2 = 8;
|
|
5843
|
+
async function promptStaleConflictStrategy(conflicts, dependencies) {
|
|
5844
|
+
const lines = [`\u68C0\u6D4B\u5230 ${conflicts.length} \u4E2A\u670D\u52A1\u7AEF\u5E76\u53D1\u51B2\u7A81\uFF1A`];
|
|
5845
|
+
for (const conflict2 of conflicts.slice(0, CONFLICT_PREVIEW_LIMIT2)) {
|
|
5846
|
+
lines.push(` - ${conflict2.path}`);
|
|
5847
|
+
}
|
|
5848
|
+
if (conflicts.length > CONFLICT_PREVIEW_LIMIT2) {
|
|
5849
|
+
lines.push(` - \u2026\u53E6 ${conflicts.length - CONFLICT_PREVIEW_LIMIT2} \u4E2A`);
|
|
5850
|
+
}
|
|
5851
|
+
dependencies.stderr(lines.join("\n") + "\n");
|
|
5852
|
+
const answer = await dependencies.prompt(
|
|
5853
|
+
"\u8BF7\u9009\u62E9\u5904\u7406\u65B9\u5F0F\uFF1A\n 1. \u4FDD\u7559\u672C\u5730\u5185\u5BB9\u5E76\u7EE7\u7EED\u63A8\u9001\uFF08\u63A8\u8350\uFF09\n 2. \u63A5\u53D7\u670D\u52A1\u7AEF\u5185\u5BB9\u5E76\u7EE7\u7EED\u63A8\u9001\n 3. \u9000\u51FA\uFF0C\u7A0D\u540E\u9010\u9879\u5904\u7406\n\u8BF7\u9009\u62E9 [1]\uFF1A"
|
|
5854
|
+
);
|
|
5855
|
+
const selected = answer.trim();
|
|
5856
|
+
if (selected === "" || selected === "1") return "keep-local";
|
|
5857
|
+
if (selected === "2") return "accept-remote";
|
|
5858
|
+
return false;
|
|
5859
|
+
}
|
|
5802
5860
|
function formatFindings(details) {
|
|
5803
5861
|
if (details?.findings === void 0 || details.findings.length === 0) {
|
|
5804
5862
|
return "";
|
|
@@ -5899,7 +5957,8 @@ async function runPush(options, dependencies) {
|
|
|
5899
5957
|
const reasonAnswer = await dependencies.prompt("\u8DF3\u8FC7\u539F\u56E0\uFF08\u53EF\u9009\uFF0C\u56DE\u8F66\u8DF3\u8FC7\uFF09: ");
|
|
5900
5958
|
const reason = reasonAnswer.trim();
|
|
5901
5959
|
return reason === "" ? { skip: true } : { skip: true, reason };
|
|
5902
|
-
} }
|
|
5960
|
+
} },
|
|
5961
|
+
...options.nonInteractive === true ? {} : { confirmConflictStrategy: async (conflicts) => promptStaleConflictStrategy(conflicts, dependencies) }
|
|
5903
5962
|
});
|
|
5904
5963
|
if ("cancelled" in result && result.cancelled === true) {
|
|
5905
5964
|
return 2;
|