@parabolic-technologies/banzai 2.6.5 → 2.6.6
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/banzai.mjs +118 -52
- package/dist/banzai.mjs.map +4 -4
- package/package.json +1 -1
package/dist/banzai.mjs
CHANGED
|
@@ -5897,6 +5897,13 @@ function consultationString(value, label, maximum) {
|
|
|
5897
5897
|
}
|
|
5898
5898
|
return value;
|
|
5899
5899
|
}
|
|
5900
|
+
function consultationProse(value, label, maximum) {
|
|
5901
|
+
return consultationString(
|
|
5902
|
+
typeof value === "string" ? value.replace(/[ \t\n\r]*[\t\n\r][ \t\n\r]*/gu, " ").replace(/^ +| +$/gu, "") : value,
|
|
5903
|
+
label,
|
|
5904
|
+
maximum
|
|
5905
|
+
);
|
|
5906
|
+
}
|
|
5900
5907
|
function consultationIdentifier(value, label) {
|
|
5901
5908
|
const identifier22 = consultationString(value, label, 128);
|
|
5902
5909
|
if (identifier22 === "." || identifier22 === ".." || !CONSULTATION_ID_PATTERN.test(identifier22)) {
|
|
@@ -5904,12 +5911,12 @@ function consultationIdentifier(value, label) {
|
|
|
5904
5911
|
}
|
|
5905
5912
|
return identifier22;
|
|
5906
5913
|
}
|
|
5907
|
-
function consultationStrings(value, label, maximumItems, maximumLength) {
|
|
5914
|
+
function consultationStrings(value, label, maximumItems, maximumLength, decodeItem) {
|
|
5908
5915
|
if (!Array.isArray(value) || value.length > maximumItems) {
|
|
5909
5916
|
return consultationError(`${label} must be a bounded string array.`);
|
|
5910
5917
|
}
|
|
5911
5918
|
const strings = value.map(
|
|
5912
|
-
(item, index) =>
|
|
5919
|
+
(item, index) => decodeItem(item, `${label}[${index}]`, maximumLength)
|
|
5913
5920
|
);
|
|
5914
5921
|
if (new Set(strings).size !== strings.length) {
|
|
5915
5922
|
return consultationError(`${label} must not contain duplicates.`);
|
|
@@ -5939,15 +5946,34 @@ function parseConsultationOption(value, label) {
|
|
|
5939
5946
|
]);
|
|
5940
5947
|
return {
|
|
5941
5948
|
optionId: consultationIdentifier(record7.optionId, `${label}.optionId`),
|
|
5942
|
-
title:
|
|
5943
|
-
benefits: consultationStrings(
|
|
5944
|
-
|
|
5945
|
-
|
|
5949
|
+
title: consultationProse(record7.title, `${label}.title`, 160),
|
|
5950
|
+
benefits: consultationStrings(
|
|
5951
|
+
record7.benefits,
|
|
5952
|
+
`${label}.benefits`,
|
|
5953
|
+
8,
|
|
5954
|
+
500,
|
|
5955
|
+
consultationProse
|
|
5956
|
+
),
|
|
5957
|
+
costs: consultationStrings(
|
|
5958
|
+
record7.costs,
|
|
5959
|
+
`${label}.costs`,
|
|
5960
|
+
8,
|
|
5961
|
+
500,
|
|
5962
|
+
consultationProse
|
|
5963
|
+
),
|
|
5964
|
+
risks: consultationStrings(
|
|
5965
|
+
record7.risks,
|
|
5966
|
+
`${label}.risks`,
|
|
5967
|
+
8,
|
|
5968
|
+
500,
|
|
5969
|
+
consultationProse
|
|
5970
|
+
),
|
|
5946
5971
|
consequences: consultationStrings(
|
|
5947
5972
|
record7.consequences,
|
|
5948
5973
|
`${label}.consequences`,
|
|
5949
5974
|
8,
|
|
5950
|
-
500
|
|
5975
|
+
500,
|
|
5976
|
+
consultationProse
|
|
5951
5977
|
)
|
|
5952
5978
|
};
|
|
5953
5979
|
}
|
|
@@ -5991,7 +6017,7 @@ function parseConsultationCard(value, index) {
|
|
|
5991
6017
|
return {
|
|
5992
6018
|
path: consultationPath(evidenceRecord.path, `${evidenceLabel}.path`),
|
|
5993
6019
|
line,
|
|
5994
|
-
detail:
|
|
6020
|
+
detail: consultationProse(
|
|
5995
6021
|
evidenceRecord.detail,
|
|
5996
6022
|
`${evidenceLabel}.detail`,
|
|
5997
6023
|
500
|
|
@@ -6035,7 +6061,7 @@ function parseConsultationCard(value, index) {
|
|
|
6035
6061
|
}
|
|
6036
6062
|
recommendation = {
|
|
6037
6063
|
optionId,
|
|
6038
|
-
rationale:
|
|
6064
|
+
rationale: consultationProse(
|
|
6039
6065
|
recommendationRecord.rationale,
|
|
6040
6066
|
`${label}.recommendation.rationale`,
|
|
6041
6067
|
1e3
|
|
@@ -6051,7 +6077,8 @@ function parseConsultationCard(value, index) {
|
|
|
6051
6077
|
record7.affectedRequirements,
|
|
6052
6078
|
`${label}.affectedRequirements`,
|
|
6053
6079
|
16,
|
|
6054
|
-
120
|
|
6080
|
+
120,
|
|
6081
|
+
consultationString
|
|
6055
6082
|
);
|
|
6056
6083
|
if (affectedRequirements.length === 0) {
|
|
6057
6084
|
return consultationError(
|
|
@@ -6063,9 +6090,9 @@ function parseConsultationCard(value, index) {
|
|
|
6063
6090
|
record7.decisionId,
|
|
6064
6091
|
`${label}.decisionId`
|
|
6065
6092
|
),
|
|
6066
|
-
title:
|
|
6067
|
-
question:
|
|
6068
|
-
why:
|
|
6093
|
+
title: consultationProse(record7.title, `${label}.title`, 160),
|
|
6094
|
+
question: consultationProse(record7.question, `${label}.question`, 1e3),
|
|
6095
|
+
why: consultationProse(record7.why, `${label}.why`, 1200),
|
|
6069
6096
|
affectedRequirements,
|
|
6070
6097
|
evidence: evidence2,
|
|
6071
6098
|
decisionOwner: "human",
|
|
@@ -6296,7 +6323,7 @@ function parsePhaseResultFields(record7) {
|
|
|
6296
6323
|
const decisionConsultation = parseDecisionConsultation(
|
|
6297
6324
|
record7.decisionConsultation
|
|
6298
6325
|
);
|
|
6299
|
-
const summary2 = gate === "decision_consultation" ?
|
|
6326
|
+
const summary2 = gate === "decision_consultation" ? consultationProse(record7.summary, "summary", 1e3) : requireString(record7.summary, "summary");
|
|
6300
6327
|
if (gate === "decision_consultation" ? phase !== "plan" || outcome !== "needs_human_decision" || decisionConsultation === null || questions.length !== 0 : decisionConsultation !== null) {
|
|
6301
6328
|
throw new BanzaiError2(
|
|
6302
6329
|
"INVALID_RESULT",
|
|
@@ -12887,6 +12914,13 @@ function consultationString2(value, label, maximum) {
|
|
|
12887
12914
|
}
|
|
12888
12915
|
return value;
|
|
12889
12916
|
}
|
|
12917
|
+
function consultationProse2(value, label, maximum) {
|
|
12918
|
+
return consultationString2(
|
|
12919
|
+
typeof value === "string" ? value.replace(/[ \t\n\r]*[\t\n\r][ \t\n\r]*/gu, " ").replace(/^ +| +$/gu, "") : value,
|
|
12920
|
+
label,
|
|
12921
|
+
maximum
|
|
12922
|
+
);
|
|
12923
|
+
}
|
|
12890
12924
|
function consultationIdentifier2(value, label) {
|
|
12891
12925
|
const identifier4 = consultationString2(value, label, 128);
|
|
12892
12926
|
if (identifier4 === "." || identifier4 === ".." || !CONSULTATION_ID_PATTERN2.test(identifier4)) {
|
|
@@ -12894,12 +12928,12 @@ function consultationIdentifier2(value, label) {
|
|
|
12894
12928
|
}
|
|
12895
12929
|
return identifier4;
|
|
12896
12930
|
}
|
|
12897
|
-
function consultationStrings2(value, label, maximumItems, maximumLength) {
|
|
12931
|
+
function consultationStrings2(value, label, maximumItems, maximumLength, decodeItem) {
|
|
12898
12932
|
if (!Array.isArray(value) || value.length > maximumItems) {
|
|
12899
12933
|
return consultationError2(`${label} must be a bounded string array.`);
|
|
12900
12934
|
}
|
|
12901
12935
|
const strings = value.map(
|
|
12902
|
-
(item, index) =>
|
|
12936
|
+
(item, index) => decodeItem(item, `${label}[${index}]`, maximumLength)
|
|
12903
12937
|
);
|
|
12904
12938
|
if (new Set(strings).size !== strings.length) {
|
|
12905
12939
|
return consultationError2(`${label} must not contain duplicates.`);
|
|
@@ -12929,15 +12963,34 @@ function parseConsultationOption2(value, label) {
|
|
|
12929
12963
|
]);
|
|
12930
12964
|
return {
|
|
12931
12965
|
optionId: consultationIdentifier2(record7.optionId, `${label}.optionId`),
|
|
12932
|
-
title:
|
|
12933
|
-
benefits: consultationStrings2(
|
|
12934
|
-
|
|
12935
|
-
|
|
12966
|
+
title: consultationProse2(record7.title, `${label}.title`, 160),
|
|
12967
|
+
benefits: consultationStrings2(
|
|
12968
|
+
record7.benefits,
|
|
12969
|
+
`${label}.benefits`,
|
|
12970
|
+
8,
|
|
12971
|
+
500,
|
|
12972
|
+
consultationProse2
|
|
12973
|
+
),
|
|
12974
|
+
costs: consultationStrings2(
|
|
12975
|
+
record7.costs,
|
|
12976
|
+
`${label}.costs`,
|
|
12977
|
+
8,
|
|
12978
|
+
500,
|
|
12979
|
+
consultationProse2
|
|
12980
|
+
),
|
|
12981
|
+
risks: consultationStrings2(
|
|
12982
|
+
record7.risks,
|
|
12983
|
+
`${label}.risks`,
|
|
12984
|
+
8,
|
|
12985
|
+
500,
|
|
12986
|
+
consultationProse2
|
|
12987
|
+
),
|
|
12936
12988
|
consequences: consultationStrings2(
|
|
12937
12989
|
record7.consequences,
|
|
12938
12990
|
`${label}.consequences`,
|
|
12939
12991
|
8,
|
|
12940
|
-
500
|
|
12992
|
+
500,
|
|
12993
|
+
consultationProse2
|
|
12941
12994
|
)
|
|
12942
12995
|
};
|
|
12943
12996
|
}
|
|
@@ -12981,7 +13034,7 @@ function parseConsultationCard2(value, index) {
|
|
|
12981
13034
|
return {
|
|
12982
13035
|
path: consultationPath2(evidenceRecord.path, `${evidenceLabel}.path`),
|
|
12983
13036
|
line,
|
|
12984
|
-
detail:
|
|
13037
|
+
detail: consultationProse2(
|
|
12985
13038
|
evidenceRecord.detail,
|
|
12986
13039
|
`${evidenceLabel}.detail`,
|
|
12987
13040
|
500
|
|
@@ -13025,7 +13078,7 @@ function parseConsultationCard2(value, index) {
|
|
|
13025
13078
|
}
|
|
13026
13079
|
recommendation = {
|
|
13027
13080
|
optionId,
|
|
13028
|
-
rationale:
|
|
13081
|
+
rationale: consultationProse2(
|
|
13029
13082
|
recommendationRecord.rationale,
|
|
13030
13083
|
`${label}.recommendation.rationale`,
|
|
13031
13084
|
1e3
|
|
@@ -13041,7 +13094,8 @@ function parseConsultationCard2(value, index) {
|
|
|
13041
13094
|
record7.affectedRequirements,
|
|
13042
13095
|
`${label}.affectedRequirements`,
|
|
13043
13096
|
16,
|
|
13044
|
-
120
|
|
13097
|
+
120,
|
|
13098
|
+
consultationString2
|
|
13045
13099
|
);
|
|
13046
13100
|
if (affectedRequirements.length === 0) {
|
|
13047
13101
|
return consultationError2(
|
|
@@ -13053,9 +13107,9 @@ function parseConsultationCard2(value, index) {
|
|
|
13053
13107
|
record7.decisionId,
|
|
13054
13108
|
`${label}.decisionId`
|
|
13055
13109
|
),
|
|
13056
|
-
title:
|
|
13057
|
-
question:
|
|
13058
|
-
why:
|
|
13110
|
+
title: consultationProse2(record7.title, `${label}.title`, 160),
|
|
13111
|
+
question: consultationProse2(record7.question, `${label}.question`, 1e3),
|
|
13112
|
+
why: consultationProse2(record7.why, `${label}.why`, 1200),
|
|
13059
13113
|
affectedRequirements,
|
|
13060
13114
|
evidence: evidence2,
|
|
13061
13115
|
decisionOwner: "human",
|
|
@@ -13372,7 +13426,7 @@ function parsePhaseResultFields2(record7) {
|
|
|
13372
13426
|
const decisionConsultation = parseDecisionConsultation2(
|
|
13373
13427
|
record7.decisionConsultation
|
|
13374
13428
|
);
|
|
13375
|
-
const summary2 = gate === "decision_consultation" ?
|
|
13429
|
+
const summary2 = gate === "decision_consultation" ? consultationProse2(record7.summary, "summary", 1e3) : requireString2(record7.summary, "summary");
|
|
13376
13430
|
if (gate === "decision_consultation" ? phase !== "plan" || outcome !== "needs_human_decision" || decisionConsultation === null || questions.length !== 0 : decisionConsultation !== null) {
|
|
13377
13431
|
throw new BanzaiError(
|
|
13378
13432
|
"INVALID_RESULT",
|
|
@@ -24395,7 +24449,7 @@ import process7 from "node:process";
|
|
|
24395
24449
|
// package.json
|
|
24396
24450
|
var package_default = {
|
|
24397
24451
|
name: "@parabolic-technologies/banzai",
|
|
24398
|
-
version: "2.6.
|
|
24452
|
+
version: "2.6.6",
|
|
24399
24453
|
private: false,
|
|
24400
24454
|
description: "Spec-driven AI development CLI for Codex and Claude Code, with human approvals and independent review for complex changes.",
|
|
24401
24455
|
keywords: [
|
|
@@ -24530,6 +24584,7 @@ var phase_result_schema_default = {
|
|
|
24530
24584
|
},
|
|
24531
24585
|
summary: {
|
|
24532
24586
|
type: "string",
|
|
24587
|
+
description: "With gate decision_consultation, one plain line of at most 1000 characters without control characters; the decision cards carry the detail.",
|
|
24533
24588
|
minLength: 1
|
|
24534
24589
|
},
|
|
24535
24590
|
artifacts: {
|
|
@@ -24687,6 +24742,7 @@ var phase_result_schema_default = {
|
|
|
24687
24742
|
},
|
|
24688
24743
|
{
|
|
24689
24744
|
type: "object",
|
|
24745
|
+
description: "Every string in this request is one plain line without control characters within its maxLength; use separate array entries instead of line breaks.",
|
|
24690
24746
|
additionalProperties: false,
|
|
24691
24747
|
properties: {
|
|
24692
24748
|
schema: {
|
|
@@ -31570,18 +31626,6 @@ async function establishPlanRemainderDigest(context, state, attempt, planPath, m
|
|
|
31570
31626
|
}
|
|
31571
31627
|
await recordResultDigestEvidence(context, state, attempt, [comparison]);
|
|
31572
31628
|
}
|
|
31573
|
-
function completionInvalidCheckpoint(context, sourceAttemptId, error, sourceAttemptKind = "implementation") {
|
|
31574
|
-
return {
|
|
31575
|
-
schemaVersion: 1,
|
|
31576
|
-
status: "invalid",
|
|
31577
|
-
sourceAttemptId,
|
|
31578
|
-
sourceAttemptKind,
|
|
31579
|
-
errorCode: "PLAN_TASK_COMPLETION_INVALID",
|
|
31580
|
-
violation: error.violation,
|
|
31581
|
-
taskId: error.taskId,
|
|
31582
|
-
recordedAt: timestamp(context)
|
|
31583
|
-
};
|
|
31584
|
-
}
|
|
31585
31629
|
|
|
31586
31630
|
// src/workflow/verification/required-checks.ts
|
|
31587
31631
|
import { readFile as readFile13 } from "node:fs/promises";
|
|
@@ -32323,6 +32367,22 @@ function artifactWritePaths(state, phase) {
|
|
|
32323
32367
|
|
|
32324
32368
|
// src/workflow/attempts/lifecycle.ts
|
|
32325
32369
|
import path29 from "node:path";
|
|
32370
|
+
|
|
32371
|
+
// src/workflow/domain/completion-checkpoint.ts
|
|
32372
|
+
function completionInvalidCheckpoint(facts) {
|
|
32373
|
+
return {
|
|
32374
|
+
schemaVersion: 1,
|
|
32375
|
+
status: "invalid",
|
|
32376
|
+
sourceAttemptId: facts.sourceAttemptId,
|
|
32377
|
+
sourceAttemptKind: facts.sourceAttemptKind,
|
|
32378
|
+
errorCode: "PLAN_TASK_COMPLETION_INVALID",
|
|
32379
|
+
violation: facts.violation,
|
|
32380
|
+
taskId: facts.taskId,
|
|
32381
|
+
recordedAt: facts.recordedAt
|
|
32382
|
+
};
|
|
32383
|
+
}
|
|
32384
|
+
|
|
32385
|
+
// src/workflow/attempts/lifecycle.ts
|
|
32326
32386
|
function newAttempt(context, state, kind, mutable) {
|
|
32327
32387
|
return {
|
|
32328
32388
|
id: `${kind}-${state.reviewIteration + 1}-${context.ids().slice(0, 8)}`,
|
|
@@ -32590,12 +32650,13 @@ async function failAttempt(context, state, record7, error) {
|
|
|
32590
32650
|
}
|
|
32591
32651
|
}
|
|
32592
32652
|
if (completionError3 !== null) {
|
|
32593
|
-
state.planTaskCompletion = completionInvalidCheckpoint(
|
|
32594
|
-
|
|
32595
|
-
record7.attempt.
|
|
32596
|
-
completionError3,
|
|
32597
|
-
|
|
32598
|
-
|
|
32653
|
+
state.planTaskCompletion = completionInvalidCheckpoint({
|
|
32654
|
+
sourceAttemptId: record7.attempt.id,
|
|
32655
|
+
sourceAttemptKind: record7.attempt.kind === "fix" ? "fix" : "implementation",
|
|
32656
|
+
violation: completionError3.violation,
|
|
32657
|
+
taskId: completionError3.taskId,
|
|
32658
|
+
recordedAt: timestamp(context)
|
|
32659
|
+
});
|
|
32599
32660
|
}
|
|
32600
32661
|
blockState(
|
|
32601
32662
|
state,
|
|
@@ -34235,12 +34296,13 @@ async function blockForCompletionFailure(context, state, sourceAttemptId, error)
|
|
|
34235
34296
|
"source_attempt_invalid",
|
|
34236
34297
|
errorMessage(error)
|
|
34237
34298
|
);
|
|
34238
|
-
state.planTaskCompletion = completionInvalidCheckpoint(
|
|
34239
|
-
context,
|
|
34299
|
+
state.planTaskCompletion = completionInvalidCheckpoint({
|
|
34240
34300
|
sourceAttemptId,
|
|
34241
|
-
|
|
34242
|
-
|
|
34243
|
-
|
|
34301
|
+
sourceAttemptKind: state.planTaskCompletion?.sourceAttemptId === sourceAttemptId ? state.planTaskCompletion.sourceAttemptKind ?? "implementation" : "implementation",
|
|
34302
|
+
violation: completionError3.violation,
|
|
34303
|
+
taskId: completionError3.taskId,
|
|
34304
|
+
recordedAt: timestamp(context)
|
|
34305
|
+
});
|
|
34244
34306
|
state.activeProcess = null;
|
|
34245
34307
|
blockState(
|
|
34246
34308
|
state,
|
|
@@ -35483,6 +35545,10 @@ still genuinely unresolved and blocks sound requirements, an ADR, or the plan,
|
|
|
35483
35545
|
stop before authoring a Proposed ADR or plan that selects an option. Return
|
|
35484
35546
|
outcome=needs_human_decision, gate=decision_consultation, questions=[], and one
|
|
35485
35547
|
closed decisionConsultation request containing 1-3 sequential decision cards.
|
|
35548
|
+
Its summary is one plain line of at most 1000 characters naming the pending
|
|
35549
|
+
decisions; the cards carry the detail. Every card string is also one plain line
|
|
35550
|
+
within its schema maxLength: put separate points in separate benefits, costs,
|
|
35551
|
+
risks, consequences, or evidence entries instead of line breaks or lists.
|
|
35486
35552
|
Each card must have a fresh stable decisionId, a precise question and why,
|
|
35487
35553
|
affected requirement IDs, repository-relative evidence, an accountable owner,
|
|
35488
35554
|
the supported responseMode, explicit options with consequences when the mode is
|