@bongos/core 1.19.690 → 1.19.691
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/.bongos-core.json +13 -13
- package/docs/module-api-changelog.md +2 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/ship-flow.js +59 -1
- package/scripts/gds/ship-resume.js +22 -0
- package/scripts/gds/ship.js +5 -1
- package/src/module-api.js +1 -1
- package/tests/ship_resume.mjs +54 -1
package/.bongos-core.json
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
"artifact": "bongos-core",
|
|
3
3
|
"manifest_schema": 1,
|
|
4
4
|
"generator": "scripts/gds/package-core.js",
|
|
5
|
-
"core_version": "1.19.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.19.691",
|
|
6
|
+
"core_contract": "1.19.691",
|
|
7
|
+
"source_commit": "d6f9d26e0e431f817085c4f3e93cba48e534c2e7",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-09-13T00:
|
|
9
|
+
"built_at": "2026-09-13T00:51:33.922Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 477,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
19
|
"file_count": 2627,
|
|
20
|
-
"tree_sha256": "
|
|
20
|
+
"tree_sha256": "c8d122583fff727fc928395a6e21c2ec230528b5163e89020d1b5506c39376be",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/ask-for-help/SKILL.md",
|
|
@@ -2802,7 +2802,7 @@
|
|
|
2802
2802
|
{
|
|
2803
2803
|
"path": "docs/module-api-changelog.md",
|
|
2804
2804
|
"mode": "0000644",
|
|
2805
|
-
"sha256": "
|
|
2805
|
+
"sha256": "d15899aa7ccc7cf1c4746843d0bc37487fcfaf1dabcbb6c9cac6ea8ccac49865"
|
|
2806
2806
|
},
|
|
2807
2807
|
{
|
|
2808
2808
|
"path": "docs/modules-contract.md",
|
|
@@ -7782,12 +7782,12 @@
|
|
|
7782
7782
|
{
|
|
7783
7783
|
"path": "package-lock.json",
|
|
7784
7784
|
"mode": "0000644",
|
|
7785
|
-
"sha256": "
|
|
7785
|
+
"sha256": "8ef95c8bad02f83fa9d831818ab483bc1fbf18fbaf3392f5d03ab82dea4a3a7b"
|
|
7786
7786
|
},
|
|
7787
7787
|
{
|
|
7788
7788
|
"path": "package.json",
|
|
7789
7789
|
"mode": "0000644",
|
|
7790
|
-
"sha256": "
|
|
7790
|
+
"sha256": "88f4f66604d980452d57d66d581170a45fd7e07464cf3699e390b34773105504"
|
|
7791
7791
|
},
|
|
7792
7792
|
{
|
|
7793
7793
|
"path": "public-docs/index.html",
|
|
@@ -8922,7 +8922,7 @@
|
|
|
8922
8922
|
{
|
|
8923
8923
|
"path": "scripts/gds/ship-flow.js",
|
|
8924
8924
|
"mode": "0000644",
|
|
8925
|
-
"sha256": "
|
|
8925
|
+
"sha256": "7f6c46f56fcd54c01b5dd0bd6fecd712962c87ed693a44bea1746cf4c6aacebb"
|
|
8926
8926
|
},
|
|
8927
8927
|
{
|
|
8928
8928
|
"path": "scripts/gds/ship-git.js",
|
|
@@ -8977,7 +8977,7 @@
|
|
|
8977
8977
|
{
|
|
8978
8978
|
"path": "scripts/gds/ship-resume.js",
|
|
8979
8979
|
"mode": "0000644",
|
|
8980
|
-
"sha256": "
|
|
8980
|
+
"sha256": "20b91c52c75fae6355165941d1467081424614d46063f87137870ef291d442b9"
|
|
8981
8981
|
},
|
|
8982
8982
|
{
|
|
8983
8983
|
"path": "scripts/gds/ship-session-upload.js",
|
|
@@ -9002,7 +9002,7 @@
|
|
|
9002
9002
|
{
|
|
9003
9003
|
"path": "scripts/gds/ship.js",
|
|
9004
9004
|
"mode": "0000644",
|
|
9005
|
-
"sha256": "
|
|
9005
|
+
"sha256": "a64455fdf9771e4ccb04b49d42b9bb0cb0fe45bc6cb36d4e5f3abe0c31fe99ff"
|
|
9006
9006
|
},
|
|
9007
9007
|
{
|
|
9008
9008
|
"path": "scripts/gds/skill-lint.js",
|
|
@@ -9552,7 +9552,7 @@
|
|
|
9552
9552
|
{
|
|
9553
9553
|
"path": "src/module-api.js",
|
|
9554
9554
|
"mode": "0000644",
|
|
9555
|
-
"sha256": "
|
|
9555
|
+
"sha256": "97d34718e5b331dc33b78b070ed6760c8113f383faf0a90cd8076f1ac5047fbb"
|
|
9556
9556
|
},
|
|
9557
9557
|
{
|
|
9558
9558
|
"path": "src/module-loader/catalog.js",
|
|
@@ -12677,7 +12677,7 @@
|
|
|
12677
12677
|
{
|
|
12678
12678
|
"path": "tests/ship_resume.mjs",
|
|
12679
12679
|
"mode": "0000644",
|
|
12680
|
-
"sha256": "
|
|
12680
|
+
"sha256": "e5305fa140de31d7e646e328b4a3956f845f62b335bf14285a91cc38a20f8e0f"
|
|
12681
12681
|
},
|
|
12682
12682
|
{
|
|
12683
12683
|
"path": "tests/ship_smoke_gate.mjs",
|
|
@@ -1839,5 +1839,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
1839
1839
|
landed since 1.19.688 with no explicit bump. run 34726470555. (task 1002620)
|
|
1840
1840
|
1.19.690 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1841
1841
|
landed since 1.19.689 with no explicit bump. run 34727464797. (task 1002620)
|
|
1842
|
+
1.19.691 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1843
|
+
landed since 1.19.690 with no explicit bump. run 34729018766. (task 1002620)
|
|
1842
1844
|
---------------------------------------------------------------------------
|
|
1843
1845
|
```
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.691",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.19.
|
|
9
|
+
"version": "1.19.691",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.691",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|
package/scripts/gds/ship-flow.js
CHANGED
|
@@ -27,7 +27,7 @@ const { apiErrorLine, normalizeApiError, isUnknownFieldRejection } = require('./
|
|
|
27
27
|
const { pushVia } = require('./ship-deploy-target.js');
|
|
28
28
|
|
|
29
29
|
const { diffstatFor, finishShip } = require('./ship-finish.js');
|
|
30
|
-
const { evaluateRegradeEligibility, evaluateResumeAction, resumeMerge } = require('./ship-resume.js');
|
|
30
|
+
const { evaluateRegradeEligibility, evaluateResumeAction, resumeMerge, shouldConfirmWithoutGrade } = require('./ship-resume.js');
|
|
31
31
|
const { noteServerReward } = require('./ship-state.js');
|
|
32
32
|
|
|
33
33
|
// ---------- Main flow ----------
|
|
@@ -850,8 +850,66 @@ async function regradeMain() {
|
|
|
850
850
|
const graderBaseline = computeGraderBaseline(claimLike);
|
|
851
851
|
const committedFiles = computeChangedFiles(graderBaseline);
|
|
852
852
|
if (committedFiles.length === 0) {
|
|
853
|
+
// task 1003147: a DELIBERATELY artifact-free task used to dead-end here.
|
|
854
|
+
// shipMain routes every 'completed' task to this re-grade BEFORE reading any
|
|
855
|
+
// flag (evaluateResumeAction takes none), so --allow-empty / --skip-grade never
|
|
856
|
+
// reached the manual-confirm path that a no-artifact task actually needs — and
|
|
857
|
+
// that path is unreachable from 'completed' any other way. Hit for real on task
|
|
858
|
+
// 1003146: a kind=verify task landed at 'completed' with no grade row, and
|
|
859
|
+
// --allow-empty, --skip-grade and --verified all bailed on this same line.
|
|
860
|
+
//
|
|
861
|
+
// BOTH conditions are required, and the diff emptiness is MEASURED, not taken
|
|
862
|
+
// on the builder's word. A flag alone must not reach confirm: a task with a
|
|
863
|
+
// real diff whose grade failed would then bypass the grader by passing
|
|
864
|
+
// --allow-empty, which is a quality hole, not a fix. Here the grader has
|
|
865
|
+
// nothing to read, so there is no verdict to dodge. Confirming is additionally
|
|
866
|
+
// permission-gated server-side on task.confirm.grade_bypass, so this widens
|
|
867
|
+
// no authority — it only stops the ONE shape that had no exit at all.
|
|
868
|
+
if (shouldConfirmWithoutGrade({ committedFileCount: committedFiles.length, args })) {
|
|
869
|
+
console.log('');
|
|
870
|
+
console.log(`Nothing to grade (the committed diff vs ${graderBaseline || 'baseline'} is empty) and this ship`);
|
|
871
|
+
console.log('declares itself artifact-free — manual-confirming via POST /tasks/:id/confirm.');
|
|
872
|
+
// A kind='verify' task cannot reach here without --verified: the gate above
|
|
873
|
+
// exits first, so the server's verify_attestation_required can't fire below.
|
|
874
|
+
const confirm = await (await cliClient()).tasks.postTasksIdConfirm({ id: taskId, body: { verified } });
|
|
875
|
+
if (!confirm.ok) {
|
|
876
|
+
const errObj = confirm.data && confirm.data.error;
|
|
877
|
+
const errCode = typeof errObj === 'string' ? errObj : (errObj && errObj.code);
|
|
878
|
+
if (confirm.status === 403 && errCode === 'permission_forbidden') {
|
|
879
|
+
const details = (errObj && typeof errObj === 'object' && errObj.details) || {};
|
|
880
|
+
const floor = details.floors && details.floors['task.confirm.grade_bypass'];
|
|
881
|
+
console.error('');
|
|
882
|
+
console.error(`✖ Confirming without a passing grade is permission-gated: task.confirm.grade_bypass${floor ? ` (floor: ${floor})` : ''}.`);
|
|
883
|
+
console.error(' This is an authorization wall, not a verdict on your work.');
|
|
884
|
+
console.error(` Ask a builder whose role holds it to POST /api/gds/tasks/${taskId}/confirm.`);
|
|
885
|
+
process.exit(1);
|
|
886
|
+
}
|
|
887
|
+
console.error(`manual-confirm failed: ${apiErrorLine(confirm.data, confirm.status)}`);
|
|
888
|
+
process.exit(1);
|
|
889
|
+
}
|
|
890
|
+
const confirmedStatus = confirm.data.taskStatus;
|
|
891
|
+
printCreditsAndAchievements({
|
|
892
|
+
postGradeStatus: confirmedStatus,
|
|
893
|
+
credits: confirm.data.creditsAwarded ?? 0,
|
|
894
|
+
creditsRaw: null,
|
|
895
|
+
creditsMultiplier: null,
|
|
896
|
+
ideaBonusInfo: confirm.data.ideaBonus ?? null,
|
|
897
|
+
justUnlocked: confirm.data.just_unlocked || [],
|
|
898
|
+
});
|
|
899
|
+
// The same confirmed→shipped tail a normal ship runs, so a no-artifact resume
|
|
900
|
+
// lands identically instead of stopping one step short.
|
|
901
|
+
await finishShip({
|
|
902
|
+
taskId, summary, advanceToMerge: confirmedStatus === 'confirmed', skipMerge, dbOnly: true,
|
|
903
|
+
postGradeStatus: confirmedStatus,
|
|
904
|
+
doneLine: 'Done — confirmed with no artifact (grader had nothing to read).',
|
|
905
|
+
card: { title: task.title, valueSummary: summary, notes: '' },
|
|
906
|
+
});
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
853
909
|
console.error(`Nothing to grade: the committed diff vs ${graderBaseline || 'baseline'} is empty.`);
|
|
854
910
|
console.error('The grader reads committed history, not the working tree — commit your fixes on this branch, then re-run --regrade.');
|
|
911
|
+
console.error('If this task is DELIBERATELY artifact-free (a DB-only close, an ops verification), say so:');
|
|
912
|
+
console.error(` node scripts/gds/ship.js ${taskId} --allow-empty`);
|
|
855
913
|
process.exit(1);
|
|
856
914
|
}
|
|
857
915
|
|
|
@@ -106,6 +106,27 @@ function evaluateResumeAction({ task, lastClaim, builder }) {
|
|
|
106
106
|
return { action: 'error', reason: `Task #${task.id} is '${status}'. Nothing to resume.` };
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
// task 1003147: may a re-grade that has NOTHING to grade manual-confirm instead of
|
|
110
|
+
// dead-ending? Pure + exported so the truth table is unit-tested with no git or
|
|
111
|
+
// network, the same contract evaluateResumeAction above carries.
|
|
112
|
+
//
|
|
113
|
+
// Both halves are required, and they are different KINDS of evidence. The empty
|
|
114
|
+
// diff is MEASURED (the caller passes what `git diff --name-only` actually
|
|
115
|
+
// returned); the flag is the builder's DECLARATION that artifact-free is intended.
|
|
116
|
+
// A declaration alone must never be enough — a task with a real diff whose grade
|
|
117
|
+
// failed would otherwise bypass the grader by passing --allow-empty, turning a
|
|
118
|
+
// deadlock fix into a quality hole. When the diff is genuinely empty the grader has
|
|
119
|
+
// nothing to read, so there is no verdict being dodged.
|
|
120
|
+
//
|
|
121
|
+
// A bare re-run (neither flag) keeps dead-ending, deliberately: the overwhelmingly
|
|
122
|
+
// common cause of an empty diff is uncommitted work, and silently confirming that
|
|
123
|
+
// would ship nothing while reporting success.
|
|
124
|
+
function shouldConfirmWithoutGrade({ committedFileCount, args = [] }) {
|
|
125
|
+
const emptyDiff = Number(committedFileCount) === 0;
|
|
126
|
+
const declaredNoArtifact = args.includes('--allow-empty') || args.includes('--skip-grade');
|
|
127
|
+
return emptyDiff && declaredNoArtifact;
|
|
128
|
+
}
|
|
129
|
+
|
|
109
130
|
// task 941: resume a `confirmed`-but-unshipped task — the merge/deploy leg only
|
|
110
131
|
// (it already passed the grade + earned credits; this is the leg that stalls when
|
|
111
132
|
// a box can't reach the server publish, a poll window expires, etc.). Mirrors the
|
|
@@ -148,4 +169,5 @@ module.exports = {
|
|
|
148
169
|
evaluateRegradeEligibility,
|
|
149
170
|
evaluateResumeAction,
|
|
150
171
|
resumeMerge,
|
|
172
|
+
shouldConfirmWithoutGrade,
|
|
151
173
|
};
|
package/scripts/gds/ship.js
CHANGED
|
@@ -152,7 +152,7 @@ const {
|
|
|
152
152
|
formatGradeOutcome,
|
|
153
153
|
gradeAndRecord,
|
|
154
154
|
} = require('./ship-grade-steps.js');
|
|
155
|
-
const { evaluateRegradeEligibility, evaluateResumeAction } = require('./ship-resume.js');
|
|
155
|
+
const { evaluateRegradeEligibility, evaluateResumeAction, shouldConfirmWithoutGrade } = require('./ship-resume.js');
|
|
156
156
|
const { regradeMain, shipMain } = require('./ship-flow.js');
|
|
157
157
|
const { fatalRecoveryLines, smokeGateMessages } = require('./ship-honesty.js');
|
|
158
158
|
const { chooseBroadcastTargets } = require('../../modules/discord/ship-broadcast');
|
|
@@ -213,6 +213,10 @@ module.exports = {
|
|
|
213
213
|
// re-run — exported so the truth table (completed→grade, confirmed→merge,
|
|
214
214
|
// ownership, terminal states) is unit-tested with no git/network.
|
|
215
215
|
evaluateResumeAction,
|
|
216
|
+
// task 1003147: whether a re-grade with NOTHING to grade may manual-confirm
|
|
217
|
+
// instead of dead-ending — exported so the truth table (empty diff + declared
|
|
218
|
+
// no-artifact → confirm; a real diff, or no declaration → never) is unit-tested.
|
|
219
|
+
shouldConfirmWithoutGrade,
|
|
216
220
|
// #747: pre-ship auto-linkify of the ship's own changed docs. The path
|
|
217
221
|
// predicate is pure + exported so the regression test can assert which
|
|
218
222
|
// changed files fall in the linkifier's domain without git/fs/API.
|
package/src/module-api.js
CHANGED
|
@@ -71,7 +71,7 @@ const { responsibilityFor, ROLE_RESPONSIBILITIES } = require('./role-responsibil
|
|
|
71
71
|
// there. scripts/gds/bump-version.js still rewrites the literal below; it appends
|
|
72
72
|
// the entry to that file. Look for a version's history there, not here.
|
|
73
73
|
// ---------------------------------------------------------------------------
|
|
74
|
-
const CORE_VERSION = '1.19.
|
|
74
|
+
const CORE_VERSION = '1.19.691'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
|
|
75
75
|
|
|
76
76
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
77
77
|
// Usage: const log = api.logger('dev-box'); log.info('mounted');
|
package/tests/ship_resume.mjs
CHANGED
|
@@ -17,9 +17,11 @@
|
|
|
17
17
|
import { strict as assert } from 'node:assert';
|
|
18
18
|
import { createRequire } from 'node:module';
|
|
19
19
|
|
|
20
|
+
import { shipCliSource } from './helpers.mjs';
|
|
21
|
+
|
|
20
22
|
const require = createRequire(import.meta.url);
|
|
21
23
|
const ship = require('../scripts/gds/ship.js');
|
|
22
|
-
const { evaluateResumeAction } = ship;
|
|
24
|
+
const { evaluateResumeAction, shouldConfirmWithoutGrade } = ship;
|
|
23
25
|
|
|
24
26
|
let passed = 0;
|
|
25
27
|
let failed = 0;
|
|
@@ -124,6 +126,57 @@ test('completed + owner with low rank still resumes (ownership, not rank)', () =
|
|
|
124
126
|
assert.equal(a.via, 'owner');
|
|
125
127
|
});
|
|
126
128
|
|
|
129
|
+
// ---- task 1003147: the artifact-free resume that used to deadlock ----------
|
|
130
|
+
// HIT FOR REAL on task 1003146. A kind=verify task landed at 'completed' with no
|
|
131
|
+
// grade row; every documented escape (--allow-empty, --skip-grade, --verified) was
|
|
132
|
+
// swallowed by the same "Nothing to grade" bail, because shipMain routes ANY
|
|
133
|
+
// 'completed' task into the re-grade before reading a flag. The manual-confirm
|
|
134
|
+
// path a no-artifact task needs is unreachable from 'completed' any other way.
|
|
135
|
+
|
|
136
|
+
test('empty diff + --allow-empty → confirm instead of bailing (the 1003146 shape)', () => {
|
|
137
|
+
assert.equal(shouldConfirmWithoutGrade({ committedFileCount: 0, args: ['1003146', '--allow-empty'] }), true);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test('empty diff + --skip-grade → confirm (the other documented no-artifact flag)', () => {
|
|
141
|
+
assert.equal(shouldConfirmWithoutGrade({ committedFileCount: 0, args: ['1003146', '--skip-grade'] }), true);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test('a REAL diff + --allow-empty still grades — the flag is not a grader bypass', () => {
|
|
145
|
+
// The hole this guard exists to avoid: if a declaration alone were enough, a task
|
|
146
|
+
// whose grade FAILED could dodge the verdict by re-running with --allow-empty.
|
|
147
|
+
assert.equal(shouldConfirmWithoutGrade({ committedFileCount: 3, args: ['1003146', '--allow-empty'] }), false);
|
|
148
|
+
assert.equal(shouldConfirmWithoutGrade({ committedFileCount: 1, args: ['1003146', '--skip-grade'] }), false);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test('empty diff with NO flag keeps dead-ending — uncommitted work must not "ship"', () => {
|
|
152
|
+
// The overwhelmingly common cause of an empty diff is forgetting to commit.
|
|
153
|
+
// Confirming that silently would report success having shipped nothing.
|
|
154
|
+
assert.equal(shouldConfirmWithoutGrade({ committedFileCount: 0, args: ['1003146'] }), false);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test('the empty-diff guard is actually WIRED to the decision, not just exporting it', () => {
|
|
158
|
+
// A pure truth table proves the decision, not that anything calls it. Without
|
|
159
|
+
// this, the guard could revert to its unconditional `process.exit(1)` and every
|
|
160
|
+
// case above would still pass — the deadlock back, the tests still green.
|
|
161
|
+
const src = shipCliSource();
|
|
162
|
+
// Match the CALL, not the declaration. shipCliSource() spans the whole ship
|
|
163
|
+
// family including ship-resume.js, where the function is DEFINED as
|
|
164
|
+
// `shouldConfirmWithoutGrade({ committedFileCount, args })` — a looser pattern
|
|
165
|
+
// matches that signature and passes even with the call site deleted. Verified:
|
|
166
|
+
// with the guard stubbed to `if (false)`, the loose form stayed green.
|
|
167
|
+
// `committedFiles.length` exists only at the call site.
|
|
168
|
+
assert.match(src, /shouldConfirmWithoutGrade\(\{\s*committedFileCount:\s*committedFiles\.length/,
|
|
169
|
+
'the re-grade empty-diff guard must CALL shouldConfirmWithoutGrade, not merely export it');
|
|
170
|
+
assert.match(src, /postTasksIdConfirm\(\{ id: taskId, body: \{ verified \} \}\)/,
|
|
171
|
+
'and reaching it must land on the manual-confirm route a no-artifact task needs');
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test('shouldConfirmWithoutGrade: defaults and odd inputs never throw', () => {
|
|
175
|
+
assert.equal(shouldConfirmWithoutGrade({ committedFileCount: 0 }), false, 'no args → no declaration');
|
|
176
|
+
assert.equal(shouldConfirmWithoutGrade({ committedFileCount: '0', args: ['--allow-empty'] }), true, 'a numeric string still counts as empty');
|
|
177
|
+
assert.equal(shouldConfirmWithoutGrade({ committedFileCount: undefined, args: ['--allow-empty'] }), false, 'an unknown count is not an empty one');
|
|
178
|
+
});
|
|
179
|
+
|
|
127
180
|
console.log('');
|
|
128
181
|
console.log(`ship_resume: ${passed} passed, ${failed} failed`);
|
|
129
182
|
process.exit(failed === 0 ? 0 : 1);
|