chore: gate release video publish candidates

This commit is contained in:
Affaan Mustafa
2026-05-19 08:40:48 -04:00
committed by Affaan Mustafa
parent f3cd006252
commit 855e8c8336
4 changed files with 276 additions and 40 deletions

View File

@@ -8,9 +8,9 @@ social announcement.
| Field | Evidence | | Field | Evidence |
| --- | --- | | --- | --- |
| Upstream main | `c07276a347f8dac4945d2ad294124a708c19b108` | | Upstream main | `f3cd00625222fceedca00164b828db8803fe52d6` |
| Git remote | `https://github.com/affaan-m/ECC.git` | | Git remote | `https://github.com/affaan-m/ECC.git` |
| Evidence scope | Current `main` after PR #1990 harness-audit GitHub integration scoring, PR #1991 canonical ECC identity gate, PR #1992 release video-suite gate, PR #1993 growth outreach pack, and PR #1994 May 19 publication evidence refresh | | Evidence scope | Current `main` after PR #1990 harness-audit GitHub integration scoring, PR #1991 canonical ECC identity gate, PR #1992 release video-suite gate, PR #1993 growth outreach pack, PR #1994 May 19 publication evidence refresh, PR #1995 operator dashboard refresh, and PR #1996 primary render self-eval gate |
| Local status caveat | `git status --short --branch` was clean after pulling `origin/main`; generated evidence files are committed after the source snapshot they describe | | Local status caveat | `git status --short --branch` was clean after pulling `origin/main`; generated evidence files are committed after the source snapshot they describe |
The release operator must repeat all publish-facing checks from the exact final The release operator must repeat all publish-facing checks from the exact final
@@ -43,6 +43,8 @@ Tracked repositories in the platform audit were:
| PR #1992 | Merged the release video-suite gate, production manifest, validator, package file surface, preview-pack smoke wiring, release-surface tests, and compact CI JSON output | | PR #1992 | Merged the release video-suite gate, production manifest, validator, package file surface, preview-pack smoke wiring, release-surface tests, and compact CI JSON output |
| PR #1993 | Merged the partner, sponsor, consulting, conference, podcast, GitHub Discussion, and video CTA pack for the hypergrowth outbound lane | | PR #1993 | Merged the partner, sponsor, consulting, conference, podcast, GitHub Discussion, and video CTA pack for the hypergrowth outbound lane |
| PR #1994 | Merged the May 19 publication-evidence refresh, platform-audit evidence gate, preview-pack smoke evidence gate, and URL/readiness/roadmap references | | PR #1994 | Merged the May 19 publication-evidence refresh, platform-audit evidence gate, preview-pack smoke evidence gate, and URL/readiness/roadmap references |
| PR #1995 | Merged the May 19 operator dashboard refresh with the `$1,728/mo` MRR baseline, `$10,000/mo` target, and release/video/outbound top actions |
| PR #1996 | Merged the primary launch render self-eval gate for duration, size, resolution, video stream, and audio stream checks |
## Release And Growth Evidence ## Release And Growth Evidence
@@ -51,9 +53,9 @@ Tracked repositories in the platform audit were:
| Release-surface tests | `node tests/docs/ecc2-release-surface.test.js` | 25 passed, 0 failed | | Release-surface tests | `node tests/docs/ecc2-release-surface.test.js` | 25 passed, 0 failed |
| Preview-pack smoke | `npm run preview-pack:smoke -- --format json` | Ready true; digest `bc2bf157616e`; 30 required artifacts; 5 passed, 0 failed | | Preview-pack smoke | `npm run preview-pack:smoke -- --format json` | Ready true; digest `bc2bf157616e`; 30 required artifacts; 5 passed, 0 failed |
| Operator dashboard | `npm run operator:dashboard -- --markdown --write docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-19.md` | Generated May 19 dashboard with platform audit ready true, 0 tracked PRs, 0 tracked issues, 0 discussion gaps, `$1,728/mo` current MRR, `$10,000/mo` target MRR, and top actions for plugin publication, notifications, release video, outbound approval, AgentShield, and ECC Tools billing | | Operator dashboard | `npm run operator:dashboard -- --markdown --write docs/releases/2.0.0-rc.1/operator-readiness-dashboard-2026-05-19.md` | Generated May 19 dashboard with platform audit ready true, 0 tracked PRs, 0 tracked issues, 0 discussion gaps, `$1,728/mo` current MRR, `$10,000/mo` target MRR, and top actions for plugin publication, notifications, release video, outbound approval, AgentShield, and ECC Tools billing |
| Release video suite | `npm run release:video-suite -- --format json --summary` with `ECC_VIDEO_SOURCE_ROOT` and `ECC_VIDEO_RELEASE_SUITE_ROOT` | Ready true; 15/15 source assets present; 13/13 render, timeline, caption, EDL, and segment artifacts present; primary rough render self-eval passed at 144.759 seconds, 1920x1080, 1 audio stream, and 106.78 MB | | Release video suite | `npm run release:video-suite -- --format json --summary` with `ECC_VIDEO_SOURCE_ROOT` and `ECC_VIDEO_RELEASE_SUITE_ROOT` | Ready true; 15/15 source assets present; 13/13 render, timeline, caption, EDL, and segment artifacts present; 12/12 publish-candidate outputs present; primary rough render self-eval passed at 144.759 seconds, 1920x1080, 1 audio stream, and 106.78 MB |
| Full local suite | `node tests/run-all.js` | 2544 passed, 0 failed | | Full local suite | `node tests/run-all.js` | 2544 passed, 0 failed |
| PR #1993 CI | GitHub Actions run `26093792219` | Completed successfully for `d9ac22c697d9a8a8771512ab01e6df857c16776d`; all reported checks passed, including lint, validation, security scan, coverage, GitGuardian, and the macOS/Ubuntu/Windows test matrix | | PR #1996 CI | GitHub Actions run `26096847138` | Completed successfully for `f3cd00625222fceedca00164b828db8803fe52d6`; all reported checks passed, including lint, validation, security scan, coverage, GitGuardian, CodeRabbit, Cubic, and the macOS/Ubuntu/Windows test matrix |
| Public-path sanitization | `node scripts/ci/validate-no-personal-paths.js` through local suite and CI | Passed | | Public-path sanitization | `node scripts/ci/validate-no-personal-paths.js` through local suite and CI | Passed |
| Markdown and whitespace | `markdownlint` focused release docs plus `git diff --check` before PR #1993 | Passed | | Markdown and whitespace | `markdownlint` focused release docs plus `git diff --check` before PR #1993 | Passed |
@@ -63,7 +65,7 @@ Tracked repositories in the platform audit were:
| --- | --- | | --- | --- |
| Canonical repo identity | Public URLs and release docs now use `https://github.com/affaan-m/ECC` where public links are needed | | Canonical repo identity | Public URLs and release docs now use `https://github.com/affaan-m/ECC` where public links are needed |
| Release claim | Release notes and launch collateral frame ECC as the harness-native operator system for agentic work, not a Claude-only config pack | | Release claim | Release notes and launch collateral frame ECC as the harness-native operator system for agentic work, not a Claude-only config pack |
| Video proof | `video-suite-production.md` gates the local rough render, timeline, captions, source inventory, self-eval, and no-private-path publication rules | | Video proof | `video-suite-production.md` gates the local rough render, timeline, captions, source inventory, publish-candidate clip set, self-eval, and no-private-path publication rules |
| Growth proof | `partner-sponsor-talks-pack.md` provides approval-gated copy for sponsors, partners, consulting, talks, podcasts, GitHub Discussion, and video CTAs | | Growth proof | `partner-sponsor-talks-pack.md` provides approval-gated copy for sponsors, partners, consulting, talks, podcasts, GitHub Discussion, and video CTAs |
| Business baseline | Hypergrowth command center and partner pack use `$1,728/mo` current MRR, `$10,000/mo` target MRR, and `$8,272/mo` gap | | Business baseline | Hypergrowth command center and partner pack use `$1,728/mo` current MRR, `$10,000/mo` target MRR, and `$8,272/mo` gap |
| Operator dashboard | `operator-readiness-dashboard-2026-05-19.md` pulls the growth baseline into the same queue, publication, video, outbound, AgentShield, ECC Tools, Linear, and supply-chain control surface | | Operator dashboard | `operator-readiness-dashboard-2026-05-19.md` pulls the growth baseline into the same queue, publication, video, outbound, AgentShield, ECC Tools, Linear, and supply-chain control surface |
@@ -92,8 +94,8 @@ Tracked repositories in the platform audit were:
The tracked public PR queue, issue queue, discussion queue, canonical ECC The tracked public PR queue, issue queue, discussion queue, canonical ECC
identity, release video suite, preview pack, and growth outreach packet are identity, release video suite, preview pack, and growth outreach packet are
current on May 19, 2026 for `main` through current on May 19, 2026 for `main` through
`c07276a347f8dac4945d2ad294124a708c19b108`, with the May 19 dashboard `f3cd00625222fceedca00164b828db8803fe52d6`, with the publish-candidate
refresh staged for the next merge. video gate staged for the next merge.
This improves publication readiness but does not replace the approval-gated This improves publication readiness but does not replace the approval-gated
release, package, plugin, billing, Discord, and announcement steps in release, package, plugin, billing, Discord, and announcement steps in

View File

@@ -106,6 +106,27 @@ Required local rough v1 artifacts:
- `segments/primary-launch-v1/08-oss-paid-model.mp4` - `segments/primary-launch-v1/08-oss-paid-model.mp4`
- `segments/primary-launch-v1/09-close-shipping-system.mp4` - `segments/primary-launch-v1/09-close-shipping-system.mp4`
## Publish-Candidate Outputs
The release validator also expects the current publish-candidate set under
`renders/publish-candidates/`. These are still local review files, not public
uploads or committed media.
| Output | Target |
| --- | --- |
| `ecc-2-primary-launch.mp4` | 90-150s, 1920x1080, audio |
| `ecc-2-primary-launch.captions.srt` | primary captions |
| `ecc-2-install-proof-wide.mp4` | 25-35s, 1920x1080, audio |
| `ecc-2-install-proof-vertical.mp4` | 25-35s, 1080x1920, audio |
| `ecc-2-what-is-ecc-wide.mp4` | 45-60s, 1920x1080, audio |
| `ecc-2-what-is-ecc-vertical.mp4` | 45-60s, 1080x1920, audio |
| `ecc-2-security-proof-wide.mp4` | 45-60s, 1920x1080, audio |
| `ecc-2-security-proof-vertical.mp4` | 45-60s, 1080x1920, audio |
| `ecc-2-money-proof-wide.mp4` | 30-45s, 1920x1080, audio |
| `ecc-2-money-proof-vertical.mp4` | 30-45s, 1080x1920, audio |
| `ecc-2-social-proof-wide.mp4` | 30-45s, 1920x1080, audio |
| `ecc-2-social-proof-vertical.mp4` | 30-45s, 1080x1920, audio |
## video-use compatible workflow ## video-use compatible workflow
Use the same production shape as Video Use while keeping the ECC-specific media Use the same production shape as Video Use while keeping the ECC-specific media
@@ -155,6 +176,8 @@ Then manually check the final render for:
- validator self-eval passes for the primary render: 90-150 seconds, at least - validator self-eval passes for the primary render: 90-150 seconds, at least
1280x720, video stream present, audio stream present, and non-empty output; 1280x720, video stream present, audio stream present, and non-empty output;
- validator self-eval passes for the publish-candidate set: primary MP4 plus
captions and five short clips in both wide and vertical formats;
- no blank frames or accidental desktop exposure; - no blank frames or accidental desktop exposure;
- no stale repo name, pivot, rename, or Claude-only framing in captions; - no stale repo name, pivot, rename, or Claude-only framing in captions;
- no captions that rewrite speech into a false claim; - no captions that rewrite speech into a false claim;

View File

@@ -183,6 +183,135 @@ const REQUIRED_SUITE_ARTIFACTS = [
}, },
]; ];
const REQUIRED_PUBLISH_CANDIDATES = [
{
id: 'publish-primary-launch',
relativePath: 'renders/publish-candidates/ecc-2-primary-launch.mp4',
kind: 'video',
minDurationSeconds: 90,
maxDurationSeconds: 150,
minWidth: 1920,
minHeight: 1080,
minSizeMb: 5,
requiresAudio: true,
},
{
id: 'publish-primary-launch-captions',
relativePath: 'renders/publish-candidates/ecc-2-primary-launch.captions.srt',
kind: 'captions',
},
{
id: 'publish-install-proof-wide',
relativePath: 'renders/publish-candidates/ecc-2-install-proof-wide.mp4',
kind: 'video',
minDurationSeconds: 25,
maxDurationSeconds: 35,
minWidth: 1920,
minHeight: 1080,
minSizeMb: 1,
requiresAudio: true,
},
{
id: 'publish-install-proof-vertical',
relativePath: 'renders/publish-candidates/ecc-2-install-proof-vertical.mp4',
kind: 'video',
minDurationSeconds: 25,
maxDurationSeconds: 35,
minWidth: 1080,
minHeight: 1920,
minSizeMb: 1,
requiresAudio: true,
},
{
id: 'publish-what-is-ecc-wide',
relativePath: 'renders/publish-candidates/ecc-2-what-is-ecc-wide.mp4',
kind: 'video',
minDurationSeconds: 45,
maxDurationSeconds: 60,
minWidth: 1920,
minHeight: 1080,
minSizeMb: 2,
requiresAudio: true,
},
{
id: 'publish-what-is-ecc-vertical',
relativePath: 'renders/publish-candidates/ecc-2-what-is-ecc-vertical.mp4',
kind: 'video',
minDurationSeconds: 45,
maxDurationSeconds: 60,
minWidth: 1080,
minHeight: 1920,
minSizeMb: 2,
requiresAudio: true,
},
{
id: 'publish-security-proof-wide',
relativePath: 'renders/publish-candidates/ecc-2-security-proof-wide.mp4',
kind: 'video',
minDurationSeconds: 45,
maxDurationSeconds: 60,
minWidth: 1920,
minHeight: 1080,
minSizeMb: 2,
requiresAudio: true,
},
{
id: 'publish-security-proof-vertical',
relativePath: 'renders/publish-candidates/ecc-2-security-proof-vertical.mp4',
kind: 'video',
minDurationSeconds: 45,
maxDurationSeconds: 60,
minWidth: 1080,
minHeight: 1920,
minSizeMb: 2,
requiresAudio: true,
},
{
id: 'publish-money-proof-wide',
relativePath: 'renders/publish-candidates/ecc-2-money-proof-wide.mp4',
kind: 'video',
minDurationSeconds: 30,
maxDurationSeconds: 45,
minWidth: 1920,
minHeight: 1080,
minSizeMb: 2,
requiresAudio: true,
},
{
id: 'publish-money-proof-vertical',
relativePath: 'renders/publish-candidates/ecc-2-money-proof-vertical.mp4',
kind: 'video',
minDurationSeconds: 30,
maxDurationSeconds: 45,
minWidth: 1080,
minHeight: 1920,
minSizeMb: 2,
requiresAudio: true,
},
{
id: 'publish-social-proof-wide',
relativePath: 'renders/publish-candidates/ecc-2-social-proof-wide.mp4',
kind: 'video',
minDurationSeconds: 30,
maxDurationSeconds: 45,
minWidth: 1920,
minHeight: 1080,
minSizeMb: 2,
requiresAudio: true,
},
{
id: 'publish-social-proof-vertical',
relativePath: 'renders/publish-candidates/ecc-2-social-proof-vertical.mp4',
kind: 'video',
minDurationSeconds: 30,
maxDurationSeconds: 45,
minWidth: 1080,
minHeight: 1920,
minSizeMb: 2,
requiresAudio: true,
},
];
function usage() { function usage() {
console.log([ console.log([
'Usage: node scripts/release-video-suite.js [options]', 'Usage: node scripts/release-video-suite.js [options]',
@@ -471,22 +600,83 @@ function inspectSourceAssets(sourceRoot, skipProbe) {
}); });
} }
function inspectSuiteArtifacts(suiteRoot, skipProbe) { function validateVideoArtifact(artifact, media, skipProbe) {
return REQUIRED_SUITE_ARTIFACTS.map(artifact => { if (artifact.kind !== 'video' || skipProbe) {
if (!suiteRoot) { return [];
}
const failures = [];
if (media.probe !== 'ok') {
failures.push(`ffprobe ${media.probe}`);
}
if (
Number.isFinite(artifact.minDurationSeconds)
&& (
!Number.isFinite(media.durationSeconds)
|| media.durationSeconds < artifact.minDurationSeconds
)
) {
failures.push(`duration below ${artifact.minDurationSeconds}s`);
}
if (
Number.isFinite(artifact.maxDurationSeconds)
&& (
!Number.isFinite(media.durationSeconds)
|| media.durationSeconds > artifact.maxDurationSeconds
)
) {
failures.push(`duration above ${artifact.maxDurationSeconds}s`);
}
if (
Number.isFinite(artifact.minSizeMb)
&& (!Number.isFinite(media.sizeMb) || media.sizeMb < artifact.minSizeMb)
) {
failures.push(`size below ${artifact.minSizeMb} MB`);
}
if (
Number.isFinite(artifact.minWidth)
&& (!Number.isFinite(media.width) || media.width < artifact.minWidth)
) {
failures.push(`width below ${artifact.minWidth}`);
}
if (
Number.isFinite(artifact.minHeight)
&& (!Number.isFinite(media.height) || media.height < artifact.minHeight)
) {
failures.push(`height below ${artifact.minHeight}`);
}
if (artifact.requiresAudio && (!Number.isFinite(media.audioStreams) || media.audioStreams < 1)) {
failures.push('audio stream missing');
}
return failures;
}
function inspectArtifactCollection(rootDir, artifacts, skipProbe) {
return artifacts.map(artifact => {
if (!rootDir) {
return { return {
...artifact, ...artifact,
status: 'missing', status: 'missing',
configured: false, configured: false,
validationFailures: [],
}; };
} }
const filePath = path.join(suiteRoot, artifact.relativePath); const filePath = path.join(rootDir, artifact.relativePath);
if (!fs.existsSync(filePath)) { if (!fs.existsSync(filePath)) {
return { return {
...artifact, ...artifact,
status: 'missing', status: 'missing',
configured: true, configured: true,
validationFailures: [],
}; };
} }
@@ -496,44 +686,26 @@ function inspectSuiteArtifacts(suiteRoot, skipProbe) {
durationSeconds: null, durationSeconds: null,
probe: 'not-media', probe: 'not-media',
}; };
const validationFailures = validateVideoArtifact(artifact, media, skipProbe);
let durationStatus = 'pass';
if (
artifact.kind === 'video'
&& Number.isFinite(artifact.minDurationSeconds)
&& Number.isFinite(media.durationSeconds)
&& media.durationSeconds < artifact.minDurationSeconds
) {
durationStatus = 'fail';
}
if (
artifact.kind === 'video'
&& Number.isFinite(artifact.maxDurationSeconds)
&& Number.isFinite(media.durationSeconds)
&& media.durationSeconds > artifact.maxDurationSeconds
) {
durationStatus = 'fail';
}
if (
artifact.kind === 'video'
&& Number.isFinite(artifact.minDurationSeconds)
&& !skipProbe
&& media.durationSeconds === null
) {
durationStatus = 'fail';
}
return { return {
...artifact, ...artifact,
status: durationStatus === 'pass' ? 'present' : 'invalid', status: validationFailures.length === 0 ? 'present' : 'invalid',
configured: true, configured: true,
validationFailures,
...media, ...media,
}; };
}); });
} }
function inspectSuiteArtifacts(suiteRoot, skipProbe) {
return inspectArtifactCollection(suiteRoot, REQUIRED_SUITE_ARTIFACTS, skipProbe);
}
function inspectPublishCandidates(suiteRoot, skipProbe) {
return inspectArtifactCollection(suiteRoot, REQUIRED_PUBLISH_CANDIDATES, skipProbe);
}
function evaluatePrimaryRender(suiteArtifacts, skipProbe) { function evaluatePrimaryRender(suiteArtifacts, skipProbe) {
const primary = suiteArtifacts.find(artifact => artifact.id === 'primary-render-v1'); const primary = suiteArtifacts.find(artifact => artifact.id === 'primary-render-v1');
@@ -617,8 +789,10 @@ function buildReport(options = {}) {
]); ]);
const sourceAssets = inspectSourceAssets(sourceRoot, skipProbe); const sourceAssets = inspectSourceAssets(sourceRoot, skipProbe);
const suiteArtifacts = inspectSuiteArtifacts(suiteRoot, skipProbe); const suiteArtifacts = inspectSuiteArtifacts(suiteRoot, skipProbe);
const publishCandidates = inspectPublishCandidates(suiteRoot, skipProbe);
const missingSourceAssets = sourceAssets.filter(asset => asset.status !== 'present'); const missingSourceAssets = sourceAssets.filter(asset => asset.status !== 'present');
const missingSuiteArtifacts = suiteArtifacts.filter(artifact => artifact.status !== 'present'); const missingSuiteArtifacts = suiteArtifacts.filter(artifact => artifact.status !== 'present');
const missingPublishCandidates = publishCandidates.filter(candidate => candidate.status !== 'present');
const primaryRenderSelfEval = evaluatePrimaryRender(suiteArtifacts, skipProbe); const primaryRenderSelfEval = evaluatePrimaryRender(suiteArtifacts, skipProbe);
const checks = [ const checks = [
@@ -682,6 +856,23 @@ function buildReport(options = {}) {
primaryRenderSelfEval.summary, primaryRenderSelfEval.summary,
primaryRenderSelfEval.fix primaryRenderSelfEval.fix
), ),
makeCheck(
'video-publish-candidates-present',
missingPublishCandidates.length === 0 ? 'pass' : 'fail',
missingPublishCandidates.length === 0
? `${publishCandidates.length} publish-candidate MP4/caption artifacts are present and self-evaluable`
: `missing or invalid publish candidates: ${missingPublishCandidates.map(candidate => {
const reason = candidate.validationFailures && candidate.validationFailures.length > 0
? ` (${candidate.validationFailures.join(', ')})`
: '';
return `${candidate.relativePath}${reason}`;
}).join(', ')}`,
'Render the publish-candidate MP4/caption set under renders/publish-candidates before release review.',
{
configured: Boolean(suiteRoot),
missing: missingPublishCandidates.map(candidate => candidate.relativePath),
}
),
]; ];
const failed = checks.filter(check => check.status !== 'pass'); const failed = checks.filter(check => check.status !== 'pass');
@@ -713,6 +904,7 @@ function buildReport(options = {}) {
checks, checks,
sourceAssets, sourceAssets,
suiteArtifacts, suiteArtifacts,
publishCandidates,
top_actions: topActions, top_actions: topActions,
}; };
} }
@@ -748,6 +940,7 @@ function summarizeReport(report) {
})), })),
sourceAssetSummary: summarizeItems(report.sourceAssets), sourceAssetSummary: summarizeItems(report.sourceAssets),
suiteArtifactSummary: summarizeItems(report.suiteArtifacts), suiteArtifactSummary: summarizeItems(report.suiteArtifacts),
publishCandidateSummary: summarizeItems(report.publishCandidates),
primaryRender: primaryRender ? { primaryRender: primaryRender ? {
status: primaryRender.status, status: primaryRender.status,
durationSeconds: primaryRender.durationSeconds, durationSeconds: primaryRender.durationSeconds,
@@ -780,6 +973,11 @@ function renderText(report) {
); );
} }
if (report.publishCandidates.length > 0) {
const present = report.publishCandidates.filter(item => item.status === 'present').length;
lines.push(`Publish candidates: ${present}/${report.publishCandidates.length} present`);
}
if (report.top_actions.length > 0) { if (report.top_actions.length > 0) {
lines.push(''); lines.push('');
lines.push('Top actions:'); lines.push('Top actions:');
@@ -822,6 +1020,7 @@ if (require.main === module) {
} }
module.exports = { module.exports = {
REQUIRED_PUBLISH_CANDIDATES,
REQUIRED_SOURCE_ASSETS, REQUIRED_SOURCE_ASSETS,
REQUIRED_SUITE_ARTIFACTS, REQUIRED_SUITE_ARTIFACTS,
buildReport, buildReport,

View File

@@ -10,6 +10,7 @@ const { execFileSync, spawnSync } = require('child_process');
const SCRIPT = path.join(__dirname, '..', '..', 'scripts', 'release-video-suite.js'); const SCRIPT = path.join(__dirname, '..', '..', 'scripts', 'release-video-suite.js');
const { const {
REQUIRED_PUBLISH_CANDIDATES,
REQUIRED_SOURCE_ASSETS, REQUIRED_SOURCE_ASSETS,
REQUIRED_SUITE_ARTIFACTS, REQUIRED_SUITE_ARTIFACTS,
buildReport, buildReport,
@@ -75,6 +76,10 @@ function seedMedia(sourceRoot, suiteRoot) {
for (const artifact of REQUIRED_SUITE_ARTIFACTS) { for (const artifact of REQUIRED_SUITE_ARTIFACTS) {
writeFile(suiteRoot, artifact.relativePath, `artifact ${artifact.id}`); writeFile(suiteRoot, artifact.relativePath, `artifact ${artifact.id}`);
} }
for (const candidate of REQUIRED_PUBLISH_CANDIDATES) {
writeFile(suiteRoot, candidate.relativePath, `candidate ${candidate.id}`);
}
} }
function run(args = [], options = {}) { function run(args = [], options = {}) {
@@ -175,8 +180,13 @@ function runTests() {
))); )));
assert.strictEqual(report.sourceAssets.length, REQUIRED_SOURCE_ASSETS.length); assert.strictEqual(report.sourceAssets.length, REQUIRED_SOURCE_ASSETS.length);
assert.strictEqual(report.suiteArtifacts.length, REQUIRED_SUITE_ARTIFACTS.length); assert.strictEqual(report.suiteArtifacts.length, REQUIRED_SUITE_ARTIFACTS.length);
assert.strictEqual(report.publishCandidates.length, REQUIRED_PUBLISH_CANDIDATES.length);
assert.ok(renderText(report).includes('Ready: yes')); assert.ok(renderText(report).includes('Ready: yes'));
assert.strictEqual(summarizeReport(report).sourceAssetSummary.present, REQUIRED_SOURCE_ASSETS.length); assert.strictEqual(summarizeReport(report).sourceAssetSummary.present, REQUIRED_SOURCE_ASSETS.length);
assert.strictEqual(
summarizeReport(report).publishCandidateSummary.present,
REQUIRED_PUBLISH_CANDIDATES.length
);
} finally { } finally {
cleanup(rootDir); cleanup(rootDir);
cleanup(sourceRoot); cleanup(sourceRoot);
@@ -202,6 +212,7 @@ function runTests() {
assert.ok(report.checks.some(check => check.id === 'video-source-assets-present' && check.status === 'fail')); assert.ok(report.checks.some(check => check.id === 'video-source-assets-present' && check.status === 'fail'));
assert.ok(report.checks.some(check => check.id === 'video-release-artifacts-present' && check.status === 'fail')); assert.ok(report.checks.some(check => check.id === 'video-release-artifacts-present' && check.status === 'fail'));
assert.ok(report.checks.some(check => check.id === 'video-primary-render-self-eval' && check.status === 'fail')); assert.ok(report.checks.some(check => check.id === 'video-primary-render-self-eval' && check.status === 'fail'));
assert.ok(report.checks.some(check => check.id === 'video-publish-candidates-present' && check.status === 'fail'));
} finally { } finally {
cleanup(rootDir); cleanup(rootDir);
} }
@@ -269,6 +280,7 @@ function runTests() {
assert.strictEqual(parsed.suiteRootConfigured, true); assert.strictEqual(parsed.suiteRootConfigured, true);
assert.strictEqual(parsed.sourceAssetSummary.present, REQUIRED_SOURCE_ASSETS.length); assert.strictEqual(parsed.sourceAssetSummary.present, REQUIRED_SOURCE_ASSETS.length);
assert.strictEqual(parsed.suiteArtifactSummary.present, REQUIRED_SUITE_ARTIFACTS.length); assert.strictEqual(parsed.suiteArtifactSummary.present, REQUIRED_SUITE_ARTIFACTS.length);
assert.strictEqual(parsed.publishCandidateSummary.present, REQUIRED_PUBLISH_CANDIDATES.length);
} finally { } finally {
cleanup(rootDir); cleanup(rootDir);
cleanup(sourceRoot); cleanup(sourceRoot);