@pmelab/gtd 55.0.0 → 56.0.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/.claude-plugin/plugin.json +1 -1
- package/README.md +60 -61
- package/dist/chunks/{reserved-DHafcW7t.mjs → reserved-B8EC-WE8.mjs} +77 -203
- package/dist/chunks/{review-BJGKwlYv.mjs → review-HdrX0FJ7.mjs} +30 -125
- package/dist/chunks/{steering-CLhu8C7q.mjs → steering-CCNvngSH.mjs} +256 -65
- package/dist/chunks/{tail-B9Hw2AFB.mjs → tail-BSLah2mA.mjs} +144 -56
- package/dist/gtd.bundle.mjs +259 -22
- package/dist/steering.mjs +2 -2
- package/dist/testkit.mjs +6 -6
- package/dist/web/main.css +1 -1
- package/dist/web/main.js +551 -66
- package/dist/workflow-kit.mjs +1 -1
- package/dist/workflows/cleanup.mjs +2 -2
- package/dist/workflows/feature.mjs +14 -16
- package/dist/workflows/fix.mjs +3 -3
- package/dist/workflows/review.mjs +3 -3
- package/dist/workflows/rollout.mjs +1 -1
- package/dist/workflows.mjs +522 -453
- package/package.json +1 -1
- package/skills/authoring/SKILL.md +3 -3
- package/src/cli/Cli.ts +5 -5
- package/src/edge/Edge.test.ts +1 -1
- package/src/steering/FORMATS.md +5 -1
- package/src/steering/SteeringFormats.test.ts +2 -2
- package/src/steering/contract.test.ts +1 -0
- package/src/steering/findings.test.ts +47 -0
- package/src/steering/findings.ts +350 -0
- package/src/steering/fixtures/findings/gate.md +34 -0
- package/src/steering/fixtures/findings/gate.read.json +87 -0
- package/src/steering/index.test.ts +2 -2
- package/src/steering/index.ts +4 -3
- package/src/steering/review.test.ts +1 -75
- package/src/steering/review.ts +1 -74
- package/src/workflow/compile.test.ts +1 -0
- package/src/workflows/feature/criteria-coverage.feature +1 -6
- package/src/workflows/feature/feature.test.ts +1 -1
- package/src/workflows/feature/feature.ts +12 -20
- package/src/workflows/feature/lens-review.feature +323 -171
- package/src/workflows/feature/refactor-absorbs.feature +1 -7
- package/src/workflows/feature/refactor-first.feature +2 -10
- package/src/workflows/feature/refactor-rebuild.feature +4 -24
- package/src/workflows/feature/refactor-review.feature +33 -117
- package/src/workflows/feature/refactor.test.ts +0 -2
- package/src/workflows/feature/refactor.ts +0 -1
- package/src/workflows/feature/review-gate.feature +6 -22
- package/src/workflows/feature/reviewer-walkthrough.feature +16 -103
- package/src/workflows/feature/standards.feature +75 -34
- package/src/workflows/fix/fix-lens-origin.feature +20 -7
- package/src/workflows/fix/fix-quality.feature +102 -23
- package/src/workflows/review/review-door.feature +62 -59
- package/src/workflows/shared/learn.test.ts +0 -14
- package/src/workflows/shared/learn.ts +1 -6
- package/src/workflows/shared/lenses.ts +149 -43
- package/src/workflows/shared/review.test.ts +27 -26
- package/src/workflows/shared/review.ts +29 -196
- package/src/workflows/shared/tail.ts +18 -9
- package/src/workflows/shared/text.test.ts +103 -288
- package/src/workflows/shared/text.ts +131 -329
- package/src/workflows/feature/review-answers.feature +0 -324
- package/src/workflows/feature/severity-budget.feature +0 -116
- package/src/workflows/feature/severity-sorted-review.feature +0 -198
|
@@ -33,14 +33,16 @@ import {
|
|
|
33
33
|
seamSteerMessage,
|
|
34
34
|
summaryPrompt,
|
|
35
35
|
withSkills,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
withWalkthrough,
|
|
40
|
-
rankedReview,
|
|
41
|
-
unranked,
|
|
36
|
+
findingGateFile,
|
|
37
|
+
nitFixBlock,
|
|
38
|
+
withSummary,
|
|
42
39
|
} from "./text.js"
|
|
43
|
-
import {
|
|
40
|
+
import {
|
|
41
|
+
findingEntries,
|
|
42
|
+
reviewDecisions,
|
|
43
|
+
steeringFormatFor,
|
|
44
|
+
unansweredNotes,
|
|
45
|
+
} from "../../steering/index.js"
|
|
44
46
|
import { captureStep, renderText } from "./text.fixture.js"
|
|
45
47
|
|
|
46
48
|
describe("withSkills", () => {
|
|
@@ -1272,138 +1274,8 @@ describe("buildReviewCollectingPrompt answer boxes", () => {
|
|
|
1272
1274
|
})
|
|
1273
1275
|
})
|
|
1274
1276
|
|
|
1275
|
-
describe("
|
|
1276
|
-
const
|
|
1277
|
-
|
|
1278
|
-
describe("standards", () => {
|
|
1279
|
-
const conflict = { text: "Calculators are functions.", olds: ["Calculators are classes."] }
|
|
1280
|
-
const withConflict = composedReview(BASE, {
|
|
1281
|
-
notes: [],
|
|
1282
|
-
fixed: [],
|
|
1283
|
-
noise: [],
|
|
1284
|
-
standards: { added: [], undecided: [conflict] },
|
|
1285
|
-
})
|
|
1286
|
-
|
|
1287
|
-
it("asks about each undecided standard in a note that blocks sign-off", () => {
|
|
1288
|
-
expect(withConflict).toMatch(/^## Findings\n\n### Standard conflict [0-9a-f]{8}$/m)
|
|
1289
|
-
expect(withConflict).toContain("- [ ] keep the new one (drop the old)")
|
|
1290
|
-
expect(unansweredNotes(withConflict)).toHaveLength(1)
|
|
1291
|
-
})
|
|
1292
|
-
|
|
1293
|
-
it("reads its boxes by position, like a note's", () => {
|
|
1294
|
-
const ticked = withConflict.replace("- [ ] keep the old one", "- [x] keep the old one")
|
|
1295
|
-
expect(unansweredNotes(ticked)).toEqual([])
|
|
1296
|
-
expect(reviewDecisions(withConflict, ticked)).toEqual([
|
|
1297
|
-
expect.objectContaining({ choice: "wontfix" }),
|
|
1298
|
-
])
|
|
1299
|
-
})
|
|
1300
|
-
|
|
1301
|
-
it("lists the standards added", () => {
|
|
1302
|
-
const doc = composedReview(BASE, {
|
|
1303
|
-
notes: [],
|
|
1304
|
-
fixed: [],
|
|
1305
|
-
noise: [],
|
|
1306
|
-
standards: { added: ["Prefer early returns."], undecided: [] },
|
|
1307
|
-
})
|
|
1308
|
-
expect(doc).toContain("## Standards added")
|
|
1309
|
-
expect(doc).toContain("- Prefer early returns.")
|
|
1310
|
-
})
|
|
1311
|
-
})
|
|
1312
|
-
|
|
1313
|
-
it("is a valid review with unique chunk titles, so every note matches its own chunk", () => {
|
|
1314
|
-
const doc = composedReview(BASE, {
|
|
1315
|
-
notes: [
|
|
1316
|
-
{ title: "same", body: "one" },
|
|
1317
|
-
{ title: "same", body: "two", unresolved: true },
|
|
1318
|
-
],
|
|
1319
|
-
fixed: [{ title: "f", commit: "fedcba9876543210" }],
|
|
1320
|
-
noise: [{ title: "n", p: 0.8 }],
|
|
1321
|
-
})
|
|
1322
|
-
expect(steeringFormatFor("review")!.validate(doc)).toEqual([])
|
|
1323
|
-
expect(doc).toContain("# Review: 0123456\n\n<!-- base: " + BASE + " -->")
|
|
1324
|
-
expect(doc).toContain("## Findings\n\n### same\n\none")
|
|
1325
|
-
expect(doc).toContain("### same (2)\n\n_The fixer left this unresolved._\n\ntwo")
|
|
1326
|
-
expect(doc).toContain("## Fixed automatically\n\n- f (fedcba9)")
|
|
1327
|
-
expect(doc).toContain("## Dropped as noise\n\n- n (p=0.8)")
|
|
1328
|
-
})
|
|
1329
|
-
|
|
1330
|
-
it("holds one chunk when the lap left nothing", () => {
|
|
1331
|
-
const doc = composedReview(BASE, { notes: [], fixed: [], noise: [] })
|
|
1332
|
-
expect(steeringFormatFor("review")!.validate(doc)).toEqual([])
|
|
1333
|
-
expect(doc).toContain("## Nothing to note")
|
|
1334
|
-
})
|
|
1335
|
-
|
|
1336
|
-
it("never reuses a title, a summary's included", () => {
|
|
1337
|
-
const doc = composedReview(BASE, {
|
|
1338
|
-
notes: [
|
|
1339
|
-
{ title: "a", body: "1" },
|
|
1340
|
-
{ title: "a (2)", body: "2" },
|
|
1341
|
-
{ title: "a", body: "3" },
|
|
1342
|
-
{ title: "Fixed automatically", body: "4" },
|
|
1343
|
-
],
|
|
1344
|
-
fixed: [{ title: "f", commit: "fedcba9876543210" }],
|
|
1345
|
-
noise: [],
|
|
1346
|
-
})
|
|
1347
|
-
const titles = doc.split("\n").filter((l) => /^#{2,3} /.test(l))
|
|
1348
|
-
expect(titles).toEqual([
|
|
1349
|
-
"## Findings",
|
|
1350
|
-
"### a",
|
|
1351
|
-
"### a (2)",
|
|
1352
|
-
"### a (3)",
|
|
1353
|
-
"### Fixed automatically (2)",
|
|
1354
|
-
"## Fixed automatically",
|
|
1355
|
-
])
|
|
1356
|
-
})
|
|
1357
|
-
|
|
1358
|
-
it("turns a lens's task boxes into plain bullets, so no pointer or risk is read", () => {
|
|
1359
|
-
const doc = composedReview(BASE, {
|
|
1360
|
-
notes: [
|
|
1361
|
-
{ title: "a", body: "- [ ] ./src/a.ts#1-1 Risk: x\n- [x] done\n1. [ ] one\n> - [ ] q" },
|
|
1362
|
-
],
|
|
1363
|
-
fixed: [],
|
|
1364
|
-
noise: [],
|
|
1365
|
-
})
|
|
1366
|
-
expect(steeringFormatFor("review")!.validate(doc)).toEqual([])
|
|
1367
|
-
expect(doc).toContain("- ./src/a.ts#1-1 Risk: x\n- done\n1. one\n> - q")
|
|
1368
|
-
})
|
|
1369
|
-
|
|
1370
|
-
it("names the nit fix on the review after it", () => {
|
|
1371
|
-
const doc = composedReview(BASE, { notes: [], fixed: [], noise: [], nitFix: "abcdef0123" })
|
|
1372
|
-
expect(doc).toContain(
|
|
1373
|
-
"## Fixed from your notes\n\nYour nits and fix-as-suggested notes were worked on in abcdef0;",
|
|
1374
|
-
)
|
|
1375
|
-
})
|
|
1376
|
-
|
|
1377
|
-
it("ends every note, and only a note, in its three answer boxes", () => {
|
|
1378
|
-
const doc = composedReview(BASE, {
|
|
1379
|
-
notes: [{ title: "a", body: "- ends in a list" }],
|
|
1380
|
-
fixed: [{ title: "f", commit: "fedcba9876543210" }],
|
|
1381
|
-
noise: [],
|
|
1382
|
-
})
|
|
1383
|
-
expect(doc).toContain(
|
|
1384
|
-
"### a\n\n- ends in a list\n\nTick exactly one:\n\n- [ ] fix as suggested\n- [ ] won't fix\n- [ ] _your answer_\n\n## Fixed automatically",
|
|
1385
|
-
)
|
|
1386
|
-
expect(doc.match(/fix as suggested/g)).toHaveLength(1)
|
|
1387
|
-
expect(unansweredNotes(doc)).toEqual([{ title: "a", line: 7, reason: "tick exactly one box" }])
|
|
1388
|
-
})
|
|
1389
|
-
|
|
1390
|
-
it("leaves out the notes already answered", () => {
|
|
1391
|
-
const doc = composedReview(BASE, {
|
|
1392
|
-
notes: [
|
|
1393
|
-
{ title: "a", body: "1" },
|
|
1394
|
-
{ title: "a", body: "2" },
|
|
1395
|
-
],
|
|
1396
|
-
fixed: [],
|
|
1397
|
-
noise: [],
|
|
1398
|
-
answered: new Set(["a"]),
|
|
1399
|
-
})
|
|
1400
|
-
expect(doc).not.toContain("# a\n")
|
|
1401
|
-
expect(doc).toContain("## a (2)\n\n2")
|
|
1402
|
-
})
|
|
1403
|
-
})
|
|
1404
|
-
|
|
1405
|
-
describe("walkthrough", () => {
|
|
1406
|
-
const empty = { notes: [], fixed: [], noise: [] }
|
|
1277
|
+
describe("withSummary", () => {
|
|
1278
|
+
const empty = { fixed: [], gateFixed: [], dropped: [], noise: [], unresolved: [] }
|
|
1407
1279
|
const review = [
|
|
1408
1280
|
"# Review: abc1234",
|
|
1409
1281
|
"",
|
|
@@ -1413,201 +1285,144 @@ describe("walkthrough", () => {
|
|
|
1413
1285
|
"",
|
|
1414
1286
|
"- [ ] ./src/calc.ts#2-2 — subtract(a, b)",
|
|
1415
1287
|
"",
|
|
1416
|
-
"##
|
|
1288
|
+
"## Quality lap",
|
|
1417
1289
|
"",
|
|
1418
1290
|
"- [ ] ./src/calc.ts#2-2 — the reviewer's own chunk",
|
|
1419
1291
|
"",
|
|
1420
1292
|
].join("\n")
|
|
1421
1293
|
|
|
1422
|
-
it("
|
|
1423
|
-
const
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
"x (2)",
|
|
1432
|
-
])
|
|
1433
|
-
expect(titledNotes({ ...empty, notes, answered: new Set(["x"]) }).map((n) => n.title)).toEqual([
|
|
1434
|
-
"Fixed automatically (2)",
|
|
1435
|
-
"x (2)",
|
|
1436
|
-
])
|
|
1437
|
-
})
|
|
1438
|
-
|
|
1439
|
-
it("lists each note with its exact heading and quoted body", () => {
|
|
1440
|
-
const block = walkthroughBlock([
|
|
1441
|
-
{ title: "No test", body: "Add one.\n\n- [ ] a box", lens: "tests" },
|
|
1442
|
-
])
|
|
1443
|
-
expect(block).toContain("- `## No test`:\n\n > Add one.\n >\n > - a box")
|
|
1444
|
-
expect(block).toContain("its heading exactly as given")
|
|
1445
|
-
})
|
|
1446
|
-
|
|
1447
|
-
it("names the nit fix's commit, and says nothing with nothing to tell", () => {
|
|
1448
|
-
expect(walkthroughBlock([], "0123456789")).toContain(
|
|
1449
|
-
"Commit `0123456` worked on the human's nits",
|
|
1450
|
-
)
|
|
1451
|
-
expect(walkthroughBlock([])).toBe("")
|
|
1452
|
-
})
|
|
1453
|
-
|
|
1454
|
-
it("puts a note's text under its heading and its boxes after the reviewer's pointers", () => {
|
|
1455
|
-
const out = withWalkthrough(review, {
|
|
1456
|
-
...empty,
|
|
1457
|
-
notes: [{ title: "Subtract", body: "It may overflow.", unresolved: true }],
|
|
1294
|
+
it("lists what the lap did in one chunk, numbered past a title the reviewer took", () => {
|
|
1295
|
+
const out = withSummary(review, {
|
|
1296
|
+
report: {
|
|
1297
|
+
fixed: [{ title: "f", commit: "fedcba9876543210", lens: "tests" }],
|
|
1298
|
+
gateFixed: [{ title: "g", commit: "0123456789abcdef" }],
|
|
1299
|
+
dropped: [{ title: "d" }],
|
|
1300
|
+
noise: [{ title: "n", p: 0.8 }],
|
|
1301
|
+
unresolved: [{ title: "u" }, { title: "v", unclear: true }],
|
|
1302
|
+
},
|
|
1458
1303
|
})
|
|
1304
|
+
expect(steeringFormatFor("review")!.validate(out)).toEqual([])
|
|
1459
1305
|
expect(out).toContain(
|
|
1460
1306
|
[
|
|
1461
|
-
"##
|
|
1307
|
+
"## Quality lap (2)",
|
|
1308
|
+
"",
|
|
1309
|
+
"What the quality lenses found, and what became of it. Write a note under",
|
|
1310
|
+
"a line to reopen it.",
|
|
1462
1311
|
"",
|
|
1463
|
-
"
|
|
1312
|
+
"Fixed automatically:",
|
|
1464
1313
|
"",
|
|
1465
|
-
"
|
|
1314
|
+
"- f (fedcba9, lens tests)",
|
|
1466
1315
|
"",
|
|
1467
|
-
"
|
|
1316
|
+
"Fixed at the finding gate:",
|
|
1468
1317
|
"",
|
|
1469
|
-
"-
|
|
1318
|
+
"- g (0123456)",
|
|
1470
1319
|
"",
|
|
1471
|
-
"
|
|
1320
|
+
"Dropped at the finding gate:",
|
|
1472
1321
|
"",
|
|
1473
|
-
"-
|
|
1474
|
-
"
|
|
1475
|
-
"
|
|
1322
|
+
"- d",
|
|
1323
|
+
"",
|
|
1324
|
+
"Dropped as noise:",
|
|
1325
|
+
"",
|
|
1326
|
+
"- n (p=0.8)",
|
|
1327
|
+
"",
|
|
1328
|
+
"Unresolved after the finding gate:",
|
|
1329
|
+
"",
|
|
1330
|
+
"- u",
|
|
1331
|
+
"- v (removed while renaming another)",
|
|
1476
1332
|
"",
|
|
1477
|
-
"## Fixed automatically",
|
|
1478
1333
|
].join("\n"),
|
|
1479
1334
|
)
|
|
1480
1335
|
})
|
|
1481
1336
|
|
|
1482
|
-
it("
|
|
1483
|
-
const
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1337
|
+
it("asks about each undecided standard in a note that blocks sign-off, read by position", () => {
|
|
1338
|
+
const conflict = { text: "Calculators are functions.", olds: ["Calculators are classes."] }
|
|
1339
|
+
const out = withSummary(review, {
|
|
1340
|
+
report: empty,
|
|
1341
|
+
standards: { added: [], undecided: [conflict] },
|
|
1487
1342
|
})
|
|
1488
|
-
expect(
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
).
|
|
1493
|
-
})
|
|
1494
|
-
|
|
1495
|
-
it("leaves a review with nothing to add byte for byte, trailing newlines and all", () => {
|
|
1496
|
-
expect(withWalkthrough(review, empty)).toBe(review)
|
|
1497
|
-
expect(withWalkthrough(review.trimEnd(), empty)).toBe(review.trimEnd())
|
|
1498
|
-
expect(withWalkthrough(review, { ...empty, notes: [{ title: "absent", body: "x" }] })).toBe(
|
|
1499
|
-
review,
|
|
1500
|
-
)
|
|
1343
|
+
expect(out).toMatch(/^## Standard conflict [0-9a-f]{8}$/m)
|
|
1344
|
+
expect(unansweredNotes(out)).toHaveLength(1)
|
|
1345
|
+
const ticked = out.replace("- [ ] keep the old one", "- [x] keep the old one")
|
|
1346
|
+
expect(unansweredNotes(ticked)).toEqual([])
|
|
1347
|
+
expect(reviewDecisions(out, ticked)).toEqual([expect.objectContaining({ choice: "wontfix" })])
|
|
1501
1348
|
})
|
|
1502
1349
|
|
|
1503
|
-
it("
|
|
1504
|
-
const out =
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
})
|
|
1508
|
-
|
|
1509
|
-
expect(
|
|
1510
|
-
expect(decision?.body).not.toContain("./src/calc.ts")
|
|
1511
|
-
})
|
|
1512
|
-
|
|
1513
|
-
it("shows a title holding backticks as one unbroken code span", () => {
|
|
1514
|
-
expect(walkthroughBlock([{ title: "`sub` drifts", body: "x" }])).toContain(
|
|
1515
|
-
"- `` ## `sub` drifts ``:",
|
|
1516
|
-
)
|
|
1350
|
+
it("lists the standards added", () => {
|
|
1351
|
+
const out = withSummary(review, {
|
|
1352
|
+
report: empty,
|
|
1353
|
+
standards: { added: ["Prefer early returns."], undecided: [] },
|
|
1354
|
+
})
|
|
1355
|
+
expect(out).toContain("## Standards added")
|
|
1356
|
+
expect(out).toContain("- Prefer early returns.")
|
|
1517
1357
|
})
|
|
1518
1358
|
|
|
1519
|
-
it("
|
|
1520
|
-
expect(
|
|
1521
|
-
"never open a note in a finding's chunk with `Risk:`",
|
|
1522
|
-
)
|
|
1359
|
+
it("leaves a review with nothing to add byte for byte, trailing newlines and all", () => {
|
|
1360
|
+
expect(withSummary(`${review}\n\n`, { report: empty })).toBe(`${review}\n\n`)
|
|
1523
1361
|
})
|
|
1524
1362
|
})
|
|
1525
1363
|
|
|
1526
|
-
describe("
|
|
1527
|
-
const
|
|
1528
|
-
"# Review: abc1234",
|
|
1529
|
-
"",
|
|
1530
|
-
"<!-- base: abc1234 -->",
|
|
1531
|
-
"",
|
|
1532
|
-
"## Rename",
|
|
1533
|
-
"",
|
|
1534
|
-
"- [ ] ./a.ts#1-1",
|
|
1535
|
-
"",
|
|
1536
|
-
"## Token",
|
|
1537
|
-
"",
|
|
1538
|
-
"_could_",
|
|
1539
|
-
"",
|
|
1540
|
-
"Reads the token.",
|
|
1541
|
-
"",
|
|
1542
|
-
"- [ ] ./a.ts#2-2",
|
|
1543
|
-
"",
|
|
1544
|
-
"## Fixed automatically",
|
|
1545
|
-
"",
|
|
1546
|
-
"- x (abc1234)",
|
|
1547
|
-
"",
|
|
1548
|
-
].join("\n")
|
|
1364
|
+
describe("findingGateFile", () => {
|
|
1365
|
+
const gate = steeringFormatFor("findings")!
|
|
1549
1366
|
|
|
1550
|
-
it("
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
{ title: "
|
|
1554
|
-
{ title: "
|
|
1555
|
-
]
|
|
1556
|
-
|
|
1367
|
+
it("lists the open notes, then the noise, each with an unticked box, and reads back clean", () => {
|
|
1368
|
+
const file = findingGateFile(
|
|
1369
|
+
[
|
|
1370
|
+
{ title: "a", body: "Design.", lens: "tests" },
|
|
1371
|
+
{ title: "b", body: "Left over.", unresolved: true },
|
|
1372
|
+
],
|
|
1373
|
+
[{ title: "n", body: "Meh.", p: 0.8 }],
|
|
1374
|
+
)
|
|
1375
|
+
expect(file).toBe(
|
|
1557
1376
|
[
|
|
1558
|
-
"#
|
|
1377
|
+
"# Quality",
|
|
1378
|
+
"",
|
|
1379
|
+
"## a",
|
|
1559
1380
|
"",
|
|
1560
|
-
"
|
|
1381
|
+
"_From lens tests._",
|
|
1561
1382
|
"",
|
|
1562
|
-
"
|
|
1383
|
+
"Design.",
|
|
1563
1384
|
"",
|
|
1564
|
-
"
|
|
1385
|
+
"- [ ] fix",
|
|
1565
1386
|
"",
|
|
1566
|
-
"
|
|
1387
|
+
"## b",
|
|
1567
1388
|
"",
|
|
1568
|
-
"
|
|
1389
|
+
"_The fixer left it unresolved._",
|
|
1569
1390
|
"",
|
|
1570
|
-
"
|
|
1391
|
+
"Left over.",
|
|
1571
1392
|
"",
|
|
1572
|
-
"
|
|
1393
|
+
"- [ ] fix",
|
|
1573
1394
|
"",
|
|
1574
|
-
"
|
|
1395
|
+
"# Dropped as noise",
|
|
1575
1396
|
"",
|
|
1576
|
-
"##
|
|
1397
|
+
"## n",
|
|
1577
1398
|
"",
|
|
1578
|
-
"
|
|
1399
|
+
"_The judge called it noise (p=0.8)._",
|
|
1400
|
+
"",
|
|
1401
|
+
"Meh.",
|
|
1402
|
+
"",
|
|
1403
|
+
"- [ ] fix",
|
|
1579
1404
|
"",
|
|
1580
1405
|
].join("\n"),
|
|
1581
1406
|
)
|
|
1407
|
+
expect(gate.validate(file)).toEqual([])
|
|
1408
|
+
expect(findingEntries(file).map((e) => [e.title, e.noise, e.fix])).toEqual([
|
|
1409
|
+
["a", false, false],
|
|
1410
|
+
["b", false, false],
|
|
1411
|
+
["n", true, false],
|
|
1412
|
+
])
|
|
1582
1413
|
})
|
|
1583
1414
|
|
|
1584
|
-
it("
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
]),
|
|
1589
|
-
).toBe("# Review: a\n\nToken\n-----\n\n_could_\n\n- [ ] ./a.ts#1\n")
|
|
1590
|
-
})
|
|
1591
|
-
|
|
1592
|
-
it("keeps a chunk's leading indented code block indented", () => {
|
|
1593
|
-
const code = "# Review: abc1234\n\n## Code\n\n const x = 1\n\n- [ ] ./a.ts#1-1\n"
|
|
1594
|
-
expect(rankedReview(code, [{ title: "Code", label: "could" }])).toContain(
|
|
1595
|
-
"_could_\n\n const x = 1",
|
|
1596
|
-
)
|
|
1597
|
-
})
|
|
1598
|
-
|
|
1599
|
-
it("drops a stale tier with no blank line under the heading, never a longer paragraph", () => {
|
|
1600
|
-
expect(unranked("## A\n_could_\n\nbody\n")).toBe("## A\nbody\n")
|
|
1601
|
-
expect(unranked("## A\n\n_could_\n- [ ] ./a.ts#1\n")).toBe("## A\n\n- [ ] ./a.ts#1\n")
|
|
1602
|
-
const code = "## A\n\n _could_\n"
|
|
1603
|
-
expect(unranked(code)).toBe(code)
|
|
1604
|
-
const prose = "## A\n\n_should: x_\nruns on\n"
|
|
1605
|
-
expect(unranked(prose)).toBe(prose)
|
|
1415
|
+
it("turns a lens's task boxes into plain bullets, so no box is read but its own", () => {
|
|
1416
|
+
const file = findingGateFile([{ title: "a", body: "- [ ] fix\n- [x] done" }], [])
|
|
1417
|
+
expect(file).toContain("- fix\n- done")
|
|
1418
|
+
expect(findingEntries(file)[0]!.boxes).toBe(1)
|
|
1606
1419
|
})
|
|
1420
|
+
})
|
|
1607
1421
|
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
expect(
|
|
1422
|
+
describe("nitFixBlock", () => {
|
|
1423
|
+
it("names the nit fix's commit, and says nothing with nothing to tell", () => {
|
|
1424
|
+
expect(nitFixBlock("0123456789")).toContain("Commit `0123456` worked on the human's nits")
|
|
1425
|
+
expect(nitFixBlock()).toBe("")
|
|
1611
1426
|
})
|
|
1612
1427
|
})
|
|
1613
1428
|
|