/**
 * RED-GREEN tests for the pack-publish workflow orchestrator.
 *
 * @connexum/ai-governance  F-NEW-PRODUCT-AGENT-VISIBILITY-CLUSTER-2026-05-12
 */
import { describe, it } from 'node:test';
import * as assert from 'node:assert/strict';
import { publishGeneratedPack, PackValidationError } from './pack-publish-workflow.js';
import { PackVersionStore } from './pack-versioning.js';
const baseManifest = (over = {}) => ({
    agentId: 'a',
    tools: ['Bash', 'WebFetch'],
    hooks: { preToolUse: true, postToolUse: true, postResponse: true },
    llmProvider: 'connexum-proxy/anthropic',
    pluginIntegrityVerified: true,
    rateLimitsConfigured: true,
    declaredApprovalGates: [],
    declaredForbiddenCapabilities: [],
    ...over,
});
describe('publishGeneratedPack workflow', () => {
    it('scan -> auto-pack -> publish (draft default) returns full result', () => {
        const result = publishGeneratedPack({
            manifest: baseManifest(),
            publishedBy: 'alice',
            autoPack: { acceptAllSuggestedRules: true },
        });
        assert.ok(result.autoPack.pack.id.startsWith('auto-pack-'));
        assert.equal(result.versionRecord.state, 'draft');
        assert.equal(result.versionRecord.publishedBy, 'alice');
        assert.ok(result.events.some((e) => e.kind === 'VERSION_PUBLISHED'));
    });
    it('postPublish: active transitions the version to active', () => {
        const result = publishGeneratedPack({
            manifest: baseManifest(),
            publishedBy: 'alice',
            autoPack: { acceptAllSuggestedRules: true },
            postPublish: 'active',
        });
        assert.equal(result.versionRecord.state, 'active');
        assert.ok(result.events.some((e) => e.kind === 'VERSION_ACTIVATED'));
    });
    it('postPublish: shadow places the version in shadow state', () => {
        const result = publishGeneratedPack({
            manifest: baseManifest(),
            publishedBy: 'alice',
            autoPack: { acceptAllSuggestedRules: true },
            postPublish: 'shadow',
        });
        assert.equal(result.versionRecord.state, 'shadow');
        assert.ok(result.events.some((e) => e.kind === 'VERSION_SHADOW_ENABLED'));
    });
    it('default changelog includes finding counts + score + acceptance ratio', () => {
        const result = publishGeneratedPack({
            manifest: baseManifest(),
            publishedBy: 'alice',
            autoPack: { acceptAllSuggestedRules: true },
        });
        assert.match(result.versionRecord.changelog ?? '', /Findings:/);
        assert.match(result.versionRecord.changelog ?? '', /Build-structure score/);
        assert.match(result.versionRecord.changelog ?? '', /Rules accepted/);
    });
    it('custom changelog overrides the default', () => {
        const result = publishGeneratedPack({
            manifest: baseManifest(),
            publishedBy: 'alice',
            autoPack: { acceptAllSuggestedRules: true },
            changelog: 'manual override',
        });
        assert.equal(result.versionRecord.changelog, 'manual override');
    });
    it('missing publishedBy throws (fail-closed)', () => {
        assert.throws(() => publishGeneratedPack({
            manifest: baseManifest(),
            publishedBy: '',
            autoPack: { acceptAllSuggestedRules: true },
        }), /publishedBy is required/);
    });
    it('caller-supplied versionStore is used; subsequent publishes share state', () => {
        const events = [];
        const store = new PackVersionStore((e) => events.push(e));
        // Publish v1 of agent-1, set active.
        const r1 = publishGeneratedPack({
            manifest: { ...baseManifest({ agentId: 'agent-1' }) },
            publishedBy: 'alice',
            autoPack: { acceptAllSuggestedRules: true, version: '1.0.0' },
            versionStore: store,
            postPublish: 'active',
        });
        assert.equal(r1.versionRecord.state, 'active');
        // Publish v2 of the SAME agent — strictest-wins applies inside the
        // generator; the version store sees two distinct versions.
        const r2 = publishGeneratedPack({
            manifest: { ...baseManifest({ agentId: 'agent-1' }) },
            publishedBy: 'alice',
            autoPack: { acceptAllSuggestedRules: true, version: '1.1.0' },
            versionStore: store,
            postPublish: 'active',
        });
        assert.equal(r2.versionRecord.state, 'active');
        const versions = store.listVersions(r1.autoPack.pack.id).map((v) => v.version);
        assert.deepEqual(versions, ['1.0.0', '1.1.0']);
        // After r2's setActive, v1 should be archived.
        assert.equal(store.getVersion(r1.autoPack.pack.id, '1.0.0')?.state, 'archived');
        assert.equal(store.getActiveVersion(r1.autoPack.pack.id)?.version, '1.1.0');
    });
    it('events array contains exactly the publish event when postPublish is draft', () => {
        const result = publishGeneratedPack({
            manifest: baseManifest(),
            publishedBy: 'alice',
            autoPack: { acceptAllSuggestedRules: true },
            // postPublish defaults to draft
        });
        const publishedEvents = result.events.filter((e) => e.kind === 'VERSION_PUBLISHED');
        const activatedEvents = result.events.filter((e) => e.kind === 'VERSION_ACTIVATED');
        assert.equal(publishedEvents.length, 1);
        assert.equal(activatedEvents.length, 0);
    });
    it('end-to-end: Lethal Trifecta manifest -> pack with proposed rules -> publish + active', () => {
        const result = publishGeneratedPack({
            manifest: baseManifest({ tools: ['WebFetch', 'Bash', 'postgres_query'] }),
            publishedBy: 'alice',
            autoPack: { acceptAllSuggestedRules: true },
            postPublish: 'active',
        });
        assert.ok(result.autoPack.acceptedRules.length >= 2);
        assert.ok(result.autoPack.reviewRequiredRisks.some((r) => r.startsWith('A01')));
        assert.equal(result.versionRecord.state, 'active');
    });
    // F-NEW-CLUSTER-UNWIRED-STUBS-2026-05-12 integration #1 — validator gate
    it('validation: successful publish returns the ValidationReport with ok=true', () => {
        const result = publishGeneratedPack({
            manifest: baseManifest(),
            publishedBy: 'alice',
            autoPack: { acceptAllSuggestedRules: true },
        });
        assert.equal(result.validation.ok, true);
        assert.deepEqual(result.validation.errors, []);
    });
    it('validation: invalid pack id throws PackValidationError carrying the report', () => {
        // packIdPrefix with whitespace -> built id "auto-pack-bad id-a" fails ID_RE
        let caught;
        try {
            publishGeneratedPack({
                manifest: baseManifest(),
                publishedBy: 'alice',
                autoPack: { acceptAllSuggestedRules: true, packIdPrefix: 'auto-pack-bad id' },
            });
        }
        catch (e) {
            caught = e;
        }
        assert.ok(caught instanceof PackValidationError);
        const err = caught;
        assert.equal(err.report.ok, false);
        assert.ok(err.report.errors.some((i) => i.field === 'id' && i.code === 'INVALID_FORMAT'));
    });
    it('validation: store is NOT mutated when validation fails (fail-closed)', () => {
        const events = [];
        const store = new PackVersionStore((e) => events.push(e));
        try {
            publishGeneratedPack({
                manifest: baseManifest(),
                publishedBy: 'alice',
                autoPack: { acceptAllSuggestedRules: true, packIdPrefix: 'auto-pack-bad id' },
                versionStore: store,
            });
        }
        catch {
            // expected
        }
        // No VERSION_PUBLISHED event reached the store sink.
        assert.equal(events.filter((e) => e.kind === 'VERSION_PUBLISHED').length, 0);
    });
});
//# sourceMappingURL=pack-publish-workflow.test.js.map