[verified] docs: update AeroSim Wave 15 roll-up
Build and publish Corp v1 Board portal / build (pull_request) Successful in 40s

This commit is contained in:
2026-09-07 04:40:52 +00:00
parent 5e2857e918
commit 61aa7d6454
5 changed files with 124 additions and 104 deletions
+9 -7
View File
@@ -48,21 +48,23 @@ A playable MVP covering a light trainer, commercial airliner, and fighter-style
- Project organization: [corp-v1-aerosim](https://gitea.lego-cloud.eu/corp-v1-aerosim)
- Skills organization: [corp-v1-aerosim-skills-code-agent](https://gitea.lego-cloud.eu/corp-v1-aerosim-skills-code-agent)
- [Application repository](https://gitea.lego-cloud.eu/corp-v1-aerosim/corp-v1-aerosim) — `test` at `efbf3967548f1cbf5e06f97fa9d659535e35a7b4`
- [Documentation repository](https://gitea.lego-cloud.eu/corp-v1-aerosim/corp-v1-aerosim-documentation) — `test` at `f686610a8b1b21825c66dc424f484fb2672933d7`
- [Application repository](https://gitea.lego-cloud.eu/corp-v1-aerosim/corp-v1-aerosim) — `test` at `09628fbb828380fbe159be7530da26f4bbf02129`
- [Documentation repository](https://gitea.lego-cloud.eu/corp-v1-aerosim/corp-v1-aerosim-documentation) — `test` at `d8a45594c33efc3acbd1523955d4f235facc9a1f`
- [Published documentation](https://pages.apps.lego-cloud.eu/corp-v1-aerosim/corp-v1-aerosim-documentation/) — protected by the existing Keycloak access layer
## Delivery progress checkpoint — 2026-09-03
## Delivery progress checkpoint — 2026-09-07
Release `1.0.0` contains 114 Tasks. Progress is reported by lifecycle checkpoint rather than collapsing implementation and release into one percentage.
| Measure | Progress | Meaning |
|---|---:|---|
| Canonical `ToBeReleased` | 8 / 114 (7.0%) | Wave 1 Tasks `TASK-0001`, `TASK-0008`, `TASK-0011`, and `TASK-0014` plus Wave 2 Tasks `TASK-0012`, `TASK-0015`, `TASK-0073`, and `TASK-0114` have reconciled canonical delivery evidence. The remaining 106 ReadyForDelivery Tasks have not reached this checkpoint. |
| Repository-verified implementation | 8 / 114 (7.0%) | The same eight Tasks are implemented at application `test` SHA `efbf3967548f1cbf5e06f97fa9d659535e35a7b4`; integrated publish task `1760` and validate task `1761` succeeded. This implementation measure is reported separately from canonical lifecycle and release state. |
| Released | 0 / 114 (0%) | No Release `1.0.0` artifact has been approved and released. `ToBeReleased` is not release authorization. |
| Canonical `ToBeReleased` | 49 / 114 (43.0%) | Canonical records place the Tasks in Waves 1–8 and 12–14 at the release-handoff state. This is not a release. |
| Repository-verified implementation pending reconciliation | 6 / 114 (5.3%) | `TASK-0048`, `TASK-0061`, `TASK-0065`, `TASK-0077`, `TASK-0083`, and `TASK-0111` are merged into the validated current application integration head, while their canonical records remain `InProgress`. This repository checkpoint does not replace canonical reconciliation. |
| Canonical `InProgress` | 7 / 114 (6.1%) | Wave 15 Tasks are claimed as one Delivery ownership unit and remain under implementation. |
| Canonical `ReadyForDelivery` | 58 / 114 (50.9%) | Unfinished Tasks in Waves 9–11 and 16–30 remain ready but unclaimed while Wave 15 is active. |
| Released | 0 / 114 (0.0%) | No Release `1.0.0` artifact has been approved and released. `ToBeReleased` is not release authorization. |
Wave 2 is complete: its final application head is `efbf3967548f1cbf5e06f97fa9d659535e35a7b4`, and its canonical documentation was merged through PR #143 at documentation `test` SHA `f686610a8b1b21825c66dc424f484fb2672933d7`. Documentation exact-head build task `1762` and integrated build task `1763` succeeded, and the deployed release-readiness readback passed. Wave 3 is active: `TASK-0013`, `TASK-0016`, `TASK-0074`, and `TASK-0115` are claimed and in progress, but are not yet implemented or merged. The authoritative task-level lifecycle remains in the [AeroSim documentation](https://pages.apps.lego-cloud.eu/corp-v1-aerosim/corp-v1-aerosim-documentation/); this Board record is a dated portfolio checkpoint, not a second task database.
Wave 15 is active, and 6 of its 7 Tasks are repository-verified through merged application PRs #85, #89, #90, #95, #96, and #97. The current application integration head is `09628fbb828380fbe159be7530da26f4bbf02129`; its integrated tasks `2718`–`2720` succeeded. `TASK-0078` remains canonical `InProgress`, and its implementation PR #92 is closed without merge, so Wave 16 remains unclaimed. The canonical Wave 15 claim remains at documentation `test` SHA `d8a45594c33efc3acbd1523955d4f235facc9a1f`, verified by PR #155 exact-head build task `2581` and integrated build task `2582`. The authoritative task-level lifecycle remains in the [AeroSim documentation](https://pages.apps.lego-cloud.eu/corp-v1-aerosim/corp-v1-aerosim-documentation/); this Board record is a dated portfolio checkpoint, not a second task database.
## Discord
+6
View File
@@ -50,5 +50,11 @@
},
"engines": {
"node": ">=20.0"
},
"pnpm": {
"overrides": {
"fast-uri": "3.1.6",
"serialize-javascript": "7.0.3"
}
}
}
+14 -18
View File
@@ -4,6 +4,10 @@ settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
overrides:
fast-uri: 3.1.6
serialize-javascript: 7.0.3
importers:
.:
@@ -3061,8 +3065,8 @@ packages:
fast-json-stable-stringify@2.1.0:
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
fast-uri@3.1.5:
resolution: {integrity: sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==}
fast-uri@3.1.6:
resolution: {integrity: sha512-7Ical1vFEMr0onbVzEDIreM22I4khW+fzyQPwvAFWBp1iwdshSZRsL4jjRvPG9JP1uiqMHRto+YU6R2/CzDz5Q==}
fast-xml-builder@1.3.1:
resolution: {integrity: sha512-pIM/1n3ntFXKYrUZwW7QCK0gAW7XY+wzj1YMIV3tLDvPj/V+zTGJK5e3/4WJfwj0qWw2ElNXiTixda/R+3YSug==}
@@ -4763,9 +4767,6 @@ packages:
resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
engines: {node: '>=10'}
randombytes@2.1.0:
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
range-parser@1.2.0:
resolution: {integrity: sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==}
engines: {node: '>= 0.6'}
@@ -5035,8 +5036,9 @@ packages:
resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==}
engines: {node: '>= 0.8.0'}
serialize-javascript@6.0.2:
resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
serialize-javascript@7.0.3:
resolution: {integrity: sha512-h+cZ/XXarqDgCjo+YSyQU/ulDEESGGf8AMK9pPNmhNSl/FzPl6L8pMp1leca5z6NuG6tvV/auC8/43tmovowww==}
engines: {node: '>=20.0.0'}
serve-handler@6.1.7:
resolution: {integrity: sha512-CinAq1xWb0vR3twAv9evEU8cNWkXCb9kd5ePAHUKJBkOsUpR1wt/CvGdeca7vqumL1U5cSaeVQ6zZMxiJ3yWsg==}
@@ -8904,7 +8906,7 @@ snapshots:
ajv@8.20.0:
dependencies:
fast-deep-equal: 3.1.3
fast-uri: 3.1.5
fast-uri: 3.1.6
json-schema-traverse: 1.0.0
require-from-string: 2.0.2
@@ -9337,7 +9339,7 @@ snapshots:
globby: 13.2.2
normalize-path: 3.0.0
schema-utils: 4.3.3
serialize-javascript: 6.0.2
serialize-javascript: 7.0.3
webpack: 5.109.2(@swc/core@1.15.47)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.26))(html-minifier-terser@7.2.0)(postcss@8.5.26)
core-js-compat@3.50.0:
@@ -9404,7 +9406,7 @@ snapshots:
jest-worker: 29.7.0
postcss: 8.5.26
schema-utils: 4.3.3
serialize-javascript: 6.0.2
serialize-javascript: 7.0.3
webpack: 5.109.2(@swc/core@1.15.47)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.26))(html-minifier-terser@7.2.0)(postcss@8.5.26)
optionalDependencies:
clean-css: 5.3.3
@@ -9847,7 +9849,7 @@ snapshots:
fast-json-stable-stringify@2.1.0: {}
fast-uri@3.1.5: {}
fast-uri@3.1.6: {}
fast-xml-builder@1.3.1:
dependencies:
@@ -11890,10 +11892,6 @@ snapshots:
quick-lru@5.1.1: {}
randombytes@2.1.0:
dependencies:
safe-buffer: 5.2.1
range-parser@1.2.0: {}
range-parser@1.2.1: {}
@@ -12247,9 +12245,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
serialize-javascript@6.0.2:
dependencies:
randombytes: 2.1.0
serialize-javascript@7.0.3: {}
serve-handler@6.1.7:
dependencies:
+56 -79
View File
@@ -85,8 +85,9 @@ for (const marker of ['corp-v1-dpvp', 'dpvp-maintainers', 'dpvp-skill-maintainer
}
const aerosimProject = read('docs/projects/aerosim.md');
const APP_SHA = 'efbf3967548f1cbf5e06f97fa9d659535e35a7b4';
const DOC_SHA = 'f686610a8b1b21825c66dc424f484fb2672933d7';
const APP_SHA = '09628fbb828380fbe159be7530da26f4bbf02129';
const DOC_SHA = 'd8a45594c33efc3acbd1523955d4f235facc9a1f';
const AEROSIM_CHECKPOINT_HEADING = 'Delivery progress checkpoint — 2026-09-07';
const markdownSection = (document, heading) => {
const marker = `## ${heading}`;
@@ -103,11 +104,7 @@ const uniqueLine = (text, predicate, description) => {
};
function verifyAeroSimProject(document) {
const requiredSectionHeadings = [
'Resources',
'Delivery progress checkpoint — 2026-09-03',
'Discord',
];
const requiredSectionHeadings = ['Resources', AEROSIM_CHECKPOINT_HEADING, 'Discord'];
const documentLines = document.split('\n');
const requiredSectionIndices = requiredSectionHeadings.map((heading) => {
const indices = documentLines.flatMap((line, index) => line === `## ${heading}` ? [index] : []);
@@ -119,28 +116,27 @@ function verifyAeroSimProject(document) {
'AeroSim required sections must follow Resources, checkpoint, Discord order',
);
for (const marker of [
'Delivery progress checkpoint — 2026-09-03',
'8 / 114',
'7.0%',
'0 / 114',
'TASK-0012',
'TASK-0015',
'TASK-0073',
'TASK-0114',
'TASK-0013',
'TASK-0016',
'TASK-0074',
'TASK-0115',
'PR #143',
'1760',
'1761',
'1762',
'1763',
'efbf3967548f1cbf5e06f97fa9d659535e35a7b4',
'f686610a8b1b21825c66dc424f484fb2672933d7',
'106 ReadyForDelivery',
]) {
const requiredMarkers = [
AEROSIM_CHECKPOINT_HEADING,
'49 / 114',
'43.0%',
'6 / 114 (5.3%)',
'7 / 114 (6.1%)',
'58 / 114 (50.9%)',
'PR #155',
'2581',
'2582',
APP_SHA,
DOC_SHA,
'Wave 15 is active',
'6 of its 7 Tasks are repository-verified',
'PRs #85, #89, #90, #95, #96, and #97',
'integrated tasks `2718`–`2720`',
'`TASK-0078` remains canonical `InProgress`',
'PR #92 is closed without merge',
'Wave 16 remains unclaimed',
];
for (const marker of requiredMarkers) {
assert.ok(document.includes(marker), `AeroSim progress checkpoint is missing: ${marker}`);
}
@@ -150,7 +146,7 @@ function verifyAeroSimProject(document) {
assert.match(applicationResource, new RegExp(`application.*\\b${APP_SHA}\\b`, 'i'), 'application repository must reference the application SHA');
assert.match(documentationResource, new RegExp(`documentation.*\\b${DOC_SHA}\\b`, 'i'), 'documentation repository must reference the documentation SHA');
const checkpoint = markdownSection(document, 'Delivery progress checkpoint — 2026-09-03');
const checkpoint = markdownSection(document, AEROSIM_CHECKPOINT_HEADING);
const checkpointLines = checkpoint.split('\n');
const checkpointTableHeader = '| Measure | Progress | Meaning |';
const checkpointTableHeaderIndices = checkpointLines.flatMap(
@@ -158,62 +154,43 @@ function verifyAeroSimProject(document) {
);
assert.equal(checkpointTableHeaderIndices.length, 1, 'AeroSim checkpoint table header must appear exactly once');
const checkpointTableHeaderIndex = checkpointTableHeaderIndices[0];
assert.equal(
checkpointLines[checkpointTableHeaderIndex + 1],
'|---|---:|---|',
'AeroSim checkpoint table separator must exactly preserve its three columns and progress alignment',
);
assert.equal(checkpointLines[checkpointTableHeaderIndex + 1], '|---|---:|---|', 'AeroSim checkpoint table separator must exactly preserve its three columns and progress alignment');
const expectedRows = [
'Canonical `ToBeReleased`',
'Repository-verified implementation pending reconciliation',
'Canonical `InProgress`',
'Canonical `ReadyForDelivery`',
'Released',
];
assert.deepEqual(
checkpointLines.slice(checkpointTableHeaderIndex + 2, checkpointTableHeaderIndex + 5).map(
(line) => line.match(/^\| (Canonical `ToBeReleased`|Repository-verified implementation|Released) \|/)?.[1],
checkpointLines.slice(checkpointTableHeaderIndex + 2, checkpointTableHeaderIndex + 7).map(
(line) => line.match(/^\| ([^|]+?) \|/)?.[1],
),
['Canonical `ToBeReleased`', 'Repository-verified implementation', 'Released'],
'AeroSim checkpoint rows must follow canonical, implementation, released order',
expectedRows,
'AeroSim checkpoint rows must preserve canonical, reconciliation, active, ready, and released order',
);
const canonicalRow = uniqueLine(checkpoint, (line) => line.startsWith('| Canonical `ToBeReleased` |'), 'canonical ToBeReleased row');
const implementationRow = uniqueLine(checkpoint, (line) => line.startsWith('| Repository-verified implementation |'), 'repository-verified implementation row');
const implementationRow = uniqueLine(checkpoint, (line) => line.startsWith('| Repository-verified implementation pending reconciliation |'), 'repository-verified pending-reconciliation row');
const inProgressRow = uniqueLine(checkpoint, (line) => line.startsWith('| Canonical `InProgress` |'), 'canonical InProgress row');
const readyRow = uniqueLine(checkpoint, (line) => line.startsWith('| Canonical `ReadyForDelivery` |'), 'canonical ReadyForDelivery row');
const releasedRow = uniqueLine(checkpoint, (line) => line.startsWith('| Released |'), 'released row');
const waveStatus = uniqueLine(checkpoint, (line) => line.startsWith('Wave 2 is complete:'), 'Wave 2/Wave 3 status paragraph');
const waveStatus = uniqueLine(checkpoint, (line) => line.startsWith('Wave 15 is active'), 'Wave 15 status paragraph');
assert.match(releasedRow, /\|\s*0\s*\/\s*114\s*\(0%\)/i, 'AeroSim must distinguish released progress');
assert.match(canonicalRow, /\|\s*8\s*\/\s*114\s*\(7\.0%\)/i, 'AeroSim must expose canonical delivery completion');
assert.match(implementationRow, /\|\s*8\s*\/\s*114\s*\(7\.0%\)/i, 'AeroSim must expose repository-verified implementation separately');
assert.match(
canonicalRow,
/Wave 2 Tasks `TASK-0012`, `TASK-0015`, `TASK-0073`, and `TASK-0114`/,
'AeroSim Wave 2 task group must remain on the canonical completion row',
);
assert.match(
implementationRow,
new RegExp('application `test` SHA `' + APP_SHA + '`; integrated publish task `1760` and validate task `1761` succeeded', 'i'),
'AeroSim implementation row must bind the application SHA, publish task 1760, and validate task 1761',
);
assert.match(waveStatus, new RegExp('final application head is `' + APP_SHA + '`'), 'Wave 2 status must bind the final application head to the application SHA');
assert.match(waveStatus, new RegExp('documentation `test` SHA `' + DOC_SHA + '`'), 'Wave 2 status must bind the documentation merge to the documentation SHA');
assert.match(
waveStatus,
/Documentation exact-head build task `1762` and integrated build task `1763` succeeded/,
'Wave 2 status must bind exact-head build task 1762 and integrated build task 1763',
);
assert.match(
waveStatus,
/Wave 3 is active: `TASK-0013`, `TASK-0016`, `TASK-0074`, and `TASK-0115` are claimed/,
'AeroSim Wave 3 task group must remain in the active Wave 3 clause',
);
assert.match(waveStatus, /Wave 3[^\n]*claimed[^\n]*not (?:yet )?implemented or merged/i, 'AeroSim must distinguish active Wave 3 claims from implementation');
assert.match(canonicalRow, /\|\s*49\s*\/\s*114\s*\(43\.0%\)/i, 'AeroSim must expose canonical ToBeReleased progress');
assert.match(implementationRow, /\|\s*6\s*\/\s*114\s*\(5\.3%\)/i, 'AeroSim must expose repository-verified pending reconciliation separately');
assert.match(inProgressRow, /\|\s*7\s*\/\s*114\s*\(6\.1%\)/i, 'AeroSim must expose canonical InProgress progress');
assert.match(readyRow, /\|\s*58\s*\/\s*114\s*\(50\.9%\)/i, 'AeroSim must expose canonical ReadyForDelivery progress');
assert.match(releasedRow, /\|\s*0\s*\/\s*114\s*\(0\.0%\)/i, 'AeroSim must distinguish released progress');
assert.match(waveStatus, new RegExp('documentation `test` SHA `' + DOC_SHA + '`[^\\n]*PR #155 exact-head build task'), 'Wave 15 status must bind PR #155 to the documentation SHA');
assert.match(waveStatus, /exact-head build task `2581`[^\n]*integrated build task `2582`/i, 'Wave 15 status must bind exact-head and integrated documentation tasks');
assert.match(waveStatus, new RegExp('application integration head is `' + APP_SHA + '`'), 'Wave 15 status must bind the current application SHA');
assert.match(waveStatus, /6 of its 7 Tasks are repository-verified[^\n]*PRs #85, #89, #90, #95, #96, and #97/i, 'Wave 15 status must enumerate repository-verified integration evidence');
assert.match(waveStatus, /`TASK-0078` remains canonical `InProgress`[^\n]*PR #92 is closed without merge/i, 'Wave 15 status must preserve the unmerged Task state');
assert.match(readyRow, /Waves 9–11 and 16–30 remain ready but unclaimed/i, 'ReadyForDelivery must identify both earlier and later unclaimed waves');
assert.match(waveStatus, /dated portfolio checkpoint, not a second task database/i, 'AeroSim must remain a non-authoritative portfolio checkpoint');
for (const [staleMarker, stalePattern] of [
['4 / 114', /(?<!\d)4\s*\/\s*114(?!\d)/],
['3.5%', /(?<![\d.])3\.5%(?![\d.])/],
['5 / 114', /(?<!\d)5\s*\/\s*114(?!\d)/],
['4.4%', /(?<![\d.])4\.4%(?![\d.])/],
['58d33ffbd3ca21ffdc5882a75de8fe71c25188b6', /58d33ffbd3ca21ffdc5882a75de8fe71c25188b6/],
['29d5e7810e63f3407f62730c1b2c71bc0644310b', /29d5e7810e63f3407f62730c1b2c71bc0644310b/],
]) {
assert.doesNotMatch(document, stalePattern, `stale AeroSim checkpoint marker must not remain: ${staleMarker}`);
}
assert.doesNotMatch(waveStatus, /Wave 2 is active/i, 'Wave 2 must not remain active');
assert.doesNotMatch(checkpoint, /Repository-verified implementation \|/i, 'ambiguous cumulative implementation row must not return');
assert.doesNotMatch(document, /8\s*\/\s*114\s*\(7\.0%\)/i, 'stale Wave 2 portfolio metrics must not remain');
assert.doesNotMatch(waveStatus, /Wave 3 is active/i, 'stale active-wave wording must not remain');
}
verifyAeroSimProject(aerosimProject);
+39
View File
@@ -0,0 +1,39 @@
import assert from 'node:assert/strict';
import {readFile} from 'node:fs/promises';
import test from 'node:test';
const project = await readFile(new URL('../docs/projects/aerosim.md', import.meta.url), 'utf8');
const packageJson = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8'));
const lockfile = await readFile(new URL('../pnpm-lock.yaml', import.meta.url), 'utf8');
test('AeroSim portfolio roll-up reports the verified Wave 15 checkpoint', () => {
assert.match(project, /## Delivery progress checkpoint — 2026-09-07/);
assert.match(project, /Canonical `ToBeReleased` \| 49 \/ 114 \(43\.0%\)/);
assert.match(project, /Repository-verified implementation pending reconciliation \| 6 \/ 114 \(5\.3%\)/);
assert.match(project, /Canonical `InProgress` \| 7 \/ 114 \(6\.1%\)/);
assert.match(project, /Canonical `ReadyForDelivery` \| 58 \/ 114 \(50\.9%\)/);
assert.match(project, /Released \| 0 \/ 114 \(0\.0%\)/);
assert.match(project, /Wave 15 is active/);
assert.match(project, /6 of its 7 Tasks are repository-verified/);
assert.match(project, /`TASK-0048`, `TASK-0061`, `TASK-0065`, `TASK-0077`, `TASK-0083`, and `TASK-0111`/);
assert.match(project, /`TASK-0078` remains canonical `InProgress`[^\n]*PR #92 is closed without merge/);
assert.match(project, /`09628fbb828380fbe159be7530da26f4bbf02129`/);
assert.match(project, /`d8a45594c33efc3acbd1523955d4f235facc9a1f`/);
assert.match(project, /PRs #85, #89, #90, #95, #96, and #97/);
assert.match(project, /integrated tasks `2718`–`2720`/);
assert.match(project, /Waves 9–11 and 16–30 remain ready but unclaimed/);
assert.doesNotMatch(project, /Repository-verified implementation pending reconciliation \| 0 \/ 114/);
assert.doesNotMatch(project, /`7f26eca79eadef3171564fc60035e9866c2c848e`/);
assert.doesNotMatch(project, /Wave 3 is active/);
});
test('portal pins patched audit dependencies without downgrading consumers', () => {
assert.deepEqual(packageJson.pnpm?.overrides, {
'fast-uri': '3.1.6',
'serialize-javascript': '7.0.3',
});
assert.match(lockfile, /fast-uri@3\.1\.6:/);
assert.match(lockfile, /serialize-javascript@7\.0\.3:/);
assert.doesNotMatch(lockfile, /fast-uri@3\.1\.5:/);
assert.doesNotMatch(lockfile, /serialize-javascript@6\.0\.2:/);
});