@ai-sdlc/orchestrator 0.9.0 → 0.10.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/dist/__test-helpers/git-env.d.ts +40 -0
- package/dist/__test-helpers/git-env.js +73 -0
- package/dist/admission-composite.d.ts +22 -0
- package/dist/admission-composite.js +85 -2
- package/dist/admission-enrichment.js +12 -2
- package/dist/admission-hc.d.ts +20 -1
- package/dist/admission-hc.js +12 -1
- package/dist/admission-score.d.ts +14 -0
- package/dist/admission-score.js +7 -1
- package/dist/cli/commands/git-remote.d.ts +25 -0
- package/dist/cli/commands/git-remote.js +80 -1
- package/dist/cli/commands/init-features.d.ts +208 -0
- package/dist/cli/commands/init-features.js +473 -0
- package/dist/cli/commands/init-templates.d.ts +104 -0
- package/dist/cli/commands/init-templates.js +399 -0
- package/dist/cli/commands/init.d.ts +22 -0
- package/dist/cli/commands/init.js +158 -1
- package/dist/design-authority.d.ts +13 -0
- package/dist/design-authority.js +13 -0
- package/dist/execute.js +8 -5
- package/dist/models/classifier.d.ts +3 -1
- package/dist/models/classifier.js +61 -5
- package/dist/pillar-breakdown.d.ts +23 -1
- package/dist/pillar-breakdown.js +9 -0
- package/dist/runtime/attestations.d.ts +502 -10
- package/dist/runtime/attestations.js +759 -24
- package/dist/runtime/parallelism-flag.d.ts +21 -3
- package/dist/runtime/parallelism-flag.js +27 -6
- package/dist/runtime/port-allocator.d.ts +11 -0
- package/dist/runtime/port-allocator.js +30 -0
- package/package.json +3 -2
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedded template strings scaffolded by `ai-sdlc init` (AISDLC-143).
|
|
3
|
+
*
|
|
4
|
+
* Why these live in code instead of being read from disk at runtime:
|
|
5
|
+
* - The orchestrator ships as an npm package; users `npm i -g
|
|
6
|
+
* @ai-sdlc/orchestrator` and run `ai-sdlc init` in a brand new repo.
|
|
7
|
+
* The `dist/` payload would not include arbitrary `*.yml` source
|
|
8
|
+
* fixtures unless we listed each one in `package.json#files` AND
|
|
9
|
+
* plumbed a `__dirname`-based loader through esm import-meta.url.
|
|
10
|
+
* - Embedded strings work identically when invoked via `node ./dist/...`
|
|
11
|
+
* from a checkout, via `npx @ai-sdlc/orchestrator init`, or via a
|
|
12
|
+
* pre-bundled binary, with no runtime filesystem dependency.
|
|
13
|
+
*
|
|
14
|
+
* Drift policy: when the canonical workflow at
|
|
15
|
+
* `.github/workflows/ai-sdlc-gate.yml` (or the audit-only
|
|
16
|
+
* `verify-attestation.yml`) is updated for adopters, mirror the change
|
|
17
|
+
* here. The init-workspace test suite includes a smoke check that the
|
|
18
|
+
* embedded copy at least parses as a YAML mapping; AISDLC-140 sub-3's
|
|
19
|
+
* cutover memo will add a hard byte-equality assertion against the live
|
|
20
|
+
* file once the framework's own copy stabilizes.
|
|
21
|
+
*
|
|
22
|
+
* Q-decisions baked into the templates:
|
|
23
|
+
* - Q1 (prescriptive default): the gate workflow is scaffolded
|
|
24
|
+
* unconditionally — every adopter gets `ai-sdlc/pr-ready` on day one.
|
|
25
|
+
* - Q3 (attestation = audit-only): verify-attestation template is the
|
|
26
|
+
* audit-only variant; signing infrastructure is opt-in via
|
|
27
|
+
* `--with-attestation`.
|
|
28
|
+
* - Q4(b) (interactive default with --yes escape hatch): see
|
|
29
|
+
* `init-features.ts` for the wizard wiring; this module just supplies
|
|
30
|
+
* the byte content.
|
|
31
|
+
*/
|
|
32
|
+
/** `.github/workflows/ai-sdlc-gate.yml` — single rollup PR-ready check. */
|
|
33
|
+
export declare const AI_SDLC_GATE_WORKFLOW = "name: AI-SDLC PR Ready Gate\n\n# Single rollup status check `ai-sdlc/pr-ready` that aggregates every PR\n# signal AI-SDLC adopters need into ONE branch-protection entry. Replaces\n# the historical pattern of enumerating N required checks by name + app_id,\n# which is brittle against path filters, [skip ci] tokens, matrix changes,\n# and multi-app posters. See `docs/operations/quality-gate.md` for the\n# full rationale.\n#\n# Industry pattern: `re-actors/alls-green` (\"alls-green\") is the de facto\n# community fix; named adopters include aiohttp, attrs, conda, setuptools,\n# pytest, pip-tools, Open edX, PyCA, PyPA, Mergify.\n\non:\n pull_request:\n types: [opened, synchronize, reopened]\n merge_group:\n types: [checks_requested]\n\nconcurrency:\n group: ai-sdlc-gate-${{ github.event.pull_request.number || github.event.merge_group.head_sha || github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: read\n pull-requests: read\n checks: write\n\njobs:\n detect:\n name: Detect Changes\n runs-on: ubuntu-latest\n outputs:\n docs_only: ${{ steps.filter.outputs.docs_only }}\n steps:\n - uses: actions/checkout@v4\n - id: filter\n uses: dorny/paths-filter@v3\n with:\n predicate-quantifier: 'every'\n filters: |\n docs_only:\n - 'docs/**'\n - '*.md'\n\n lint:\n name: Lint & Format\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - uses: pnpm/action-setup@v4\n - uses: actions/setup-node@v4\n with:\n node-version: 22\n cache: pnpm\n - run: pnpm install --frozen-lockfile\n - run: pnpm lint\n - run: pnpm format:check\n\n build-test:\n name: Build & Test (Node ${{ matrix.node-version }})\n needs: detect\n if: needs.detect.outputs.docs_only != 'true'\n runs-on: ubuntu-latest\n strategy:\n fail-fast: false\n matrix:\n node-version: [20, 22]\n steps:\n - uses: actions/checkout@v4\n - uses: pnpm/action-setup@v4\n - uses: actions/setup-node@v4\n with:\n node-version: ${{ matrix.node-version }}\n cache: pnpm\n - run: pnpm install --frozen-lockfile\n - run: pnpm build\n - run: pnpm test\n\n coverage:\n name: Coverage\n needs: detect\n if: needs.detect.outputs.docs_only != 'true'\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - uses: pnpm/action-setup@v4\n - uses: actions/setup-node@v4\n with:\n node-version: 22\n cache: pnpm\n - run: pnpm install --frozen-lockfile\n - run: pnpm build\n - run: pnpm test:coverage\n\n pr-ready:\n name: ai-sdlc/pr-ready\n needs: [detect, lint, build-test, coverage]\n if: always()\n runs-on: ubuntu-latest\n steps:\n - name: Aggregate required signals\n uses: re-actors/alls-green@release/v1\n with:\n jobs: ${{ toJSON(needs) }}\n";
|
|
34
|
+
/**
|
|
35
|
+
* `.github/workflows/verify-attestation.yml` — AUDIT-ONLY verifier.
|
|
36
|
+
*
|
|
37
|
+
* Per Q3 in /tmp/quality-gate-redesign-final.md, attestation infrastructure
|
|
38
|
+
* is opt-in and audit-only. This workflow logs verification results to the
|
|
39
|
+
* action run log but does NOT post a required-status check or block merges.
|
|
40
|
+
* Operators who want to promote attestation to a hard gate can edit the
|
|
41
|
+
* \`Log audit result\` step to write to commit statuses.
|
|
42
|
+
*/
|
|
43
|
+
export declare const VERIFY_ATTESTATION_WORKFLOW = "name: AI-SDLC Verify Review Attestation\n\n# Reads the DSSE attestation at .ai-sdlc/attestations/<head-sha>.dsse.json\n# and verifies the signature against any-of-N pubkeys in\n# .ai-sdlc/trusted-reviewers.yaml.\n#\n# AUDIT-ONLY: this workflow logs verification results (success/failure with\n# reason) for forensic purposes but does NOT post a required commit status.\n# The single merge gate is `ai-sdlc/pr-ready` from ai-sdlc-gate.yml.\n\non:\n pull_request:\n types: [opened, synchronize, reopened]\n branches: [main]\n paths-ignore:\n - 'docs/**'\n - '*.md'\n merge_group:\n types: [checks_requested]\n\nconcurrency:\n group: verify-attestation-${{ github.event.pull_request.number || github.event.merge_group.head_sha }}\n cancel-in-progress: true\n\njobs:\n verify:\n name: Verify attestation\n runs-on: ubuntu-latest\n permissions:\n contents: read\n steps:\n - name: Resolve subject SHA + base SHA from event payload\n id: resolve\n run: |\n if [ \"${{ github.event_name }}\" = \"merge_group\" ]; then\n echo \"head_sha=${{ github.event.merge_group.head_sha }}\" >> \"$GITHUB_OUTPUT\"\n echo \"base_sha=${{ github.event.merge_group.base_sha }}\" >> \"$GITHUB_OUTPUT\"\n else\n echo \"head_sha=${{ github.event.pull_request.head.sha }}\" >> \"$GITHUB_OUTPUT\"\n echo \"base_sha=${{ github.event.pull_request.base.sha }}\" >> \"$GITHUB_OUTPUT\"\n fi\n\n - uses: actions/checkout@v4\n with:\n fetch-depth: 0\n ref: ${{ steps.resolve.outputs.head_sha }}\n\n - name: Log audit result\n env:\n HEAD_SHA: ${{ steps.resolve.outputs.head_sha }}\n run: |\n if [ -f \".ai-sdlc/attestations/${HEAD_SHA}.dsse.json\" ]; then\n echo \"::notice::ai-sdlc attestation AUDIT \u2014 envelope present at ${HEAD_SHA}\"\n else\n echo \"::notice::ai-sdlc attestation AUDIT \u2014 no envelope on ${HEAD_SHA} (audit-only, not blocking)\"\n fi\n";
|
|
44
|
+
/**
|
|
45
|
+
* `.husky/pre-push` snippet that signs an attestation when one is missing
|
|
46
|
+
* for the current HEAD. Installed when `--with-attestation` is opted in;
|
|
47
|
+
* the actual `sign-attestation.mjs` script ships separately with the
|
|
48
|
+
* orchestrator and is referenced by the canonical command stub here.
|
|
49
|
+
*
|
|
50
|
+
* Adopters typically already have a `.husky/pre-push` from their existing
|
|
51
|
+
* tooling; the wizard appends our snippet behind a sentinel so we can
|
|
52
|
+
* extend an existing hook without trampling user content.
|
|
53
|
+
*/
|
|
54
|
+
export declare const HUSKY_PREPUSH_SIGN_SNIPPET = "# ai-sdlc:attestation-sign-block\n# Signs the DSSE attestation envelope for the current HEAD when verdict\n# files exist. Skip with AI_SDLC_SKIP_ATTESTATION_SIGN=1.\nif [ -z \"${AI_SDLC_SKIP_ATTESTATION_SIGN:-}\" ] && [ -x \"./scripts/check-attestation-sign.sh\" ]; then\n ./scripts/check-attestation-sign.sh\nfi\n# end ai-sdlc:attestation-sign-block\n";
|
|
55
|
+
/**
|
|
56
|
+
* `.ai-sdlc/trusted-reviewers.yaml` stub — empty allowlist with operator
|
|
57
|
+
* instructions. The wizard scaffolds this so adopters have a single file
|
|
58
|
+
* to receive contributor pubkey PRs into; bootstrap a contributor with
|
|
59
|
+
* `/ai-sdlc init-signing-key` and append the printed YAML block.
|
|
60
|
+
*/
|
|
61
|
+
export declare const TRUSTED_REVIEWERS_STUB = "# Trusted contributor signing keys for review attestations.\n#\n# This file is a stub created by `ai-sdlc init --with-attestation`. Add\n# entries by running `/ai-sdlc init-signing-key` on a contributor's\n# machine and opening a PR that appends the printed YAML block below.\n#\n# Schema:\n# - identity: free-form string (typically email or GitHub handle)\n# - machine: free-form label (lets one identity register multiple keys)\n# - pubkey: PEM-encoded ed25519 public key (multi-line block scalar)\n# - addedAt: ISO 8601 date the entry was added\n# - addedBy: GitHub handle of the maintainer who approved this entry's PR\n#\n# The verifier in CI uses a strict YAML format: every scalar value\n# single-quoted; `pubkey:` is a `|` block scalar with each PEM line\n# indented exactly 6 spaces; no tab characters anywhere.\n\nreviewers: []\n";
|
|
62
|
+
/**
|
|
63
|
+
* `.ai-sdlc/dor-config.yaml` stub — Definition-of-Ready rubric config.
|
|
64
|
+
*
|
|
65
|
+
* Mirrors the production DoR config used by the framework itself; ships
|
|
66
|
+
* in warn-only mode so a fresh adopter does not get blocked by the rubric
|
|
67
|
+
* while they tune it.
|
|
68
|
+
*/
|
|
69
|
+
export declare const DOR_CONFIG_STUB = "# Definition-of-Ready (DoR) gate configuration.\n#\n# The DoR rubric scores incoming issues + backlog tasks against seven\n# criteria (binary-testable ACs, no wishlist markers, references resolve,\n# bounded scope, surface named, done-state describable, no invisible\n# dependencies). Failing the rubric posts a clarification comment on the\n# issue / PR.\n#\n# Ships in warn-only mode by default \u2014 flip to 'enforce' after the soak\n# window confirms the false-positive rate is low.\n\napiVersion: ai-sdlc.io/v1alpha1\nkind: DorConfig\nmetadata:\n name: ai-sdlc-dor\nspec:\n rubricVersion: v1\n evaluationMode: warn-only\n\n notifications:\n authorChannel: true\n # dedicatedChannel:\n # slack: '#ai-sdlc-dor'\n\n staleness:\n warnAfterDays: 14\n closeAfterDays: 28\n closedLabel: 'closed-as-stale-dor'\n";
|
|
70
|
+
/** `.github/workflows/dor-ingress.yml` — minimal DoR ingress shim. */
|
|
71
|
+
export declare const DOR_INGRESS_WORKFLOW = "name: AI-SDLC DoR Ingress\n\n# Wires the DoR rubric into the GitHub issue + PR lifecycle:\n# - issues:opened / issues:edited \u2192 score the issue body, post the\n# idempotent clarification comment when needs-clarification.\n# - pull_request touching backlog/tasks/*.md \u2192 score the changed\n# task bodies (the in-repo equivalent of an issue).\n#\n# Ships in warn-only mode (see .ai-sdlc/dor-config.yaml). Flip the\n# config's `evaluationMode` to `enforce` after the soak window.\n\non:\n issues:\n types: [opened, edited]\n pull_request:\n types: [opened, synchronize, reopened]\n paths:\n - 'backlog/tasks/*.md'\n\nconcurrency:\n group: dor-ingress-${{ github.event.issue.number || github.event.pull_request.number }}\n cancel-in-progress: true\n\njobs:\n evaluate:\n name: Evaluate against DoR rubric\n runs-on: ubuntu-latest\n permissions:\n issues: write\n pull-requests: write\n contents: read\n steps:\n - uses: actions/checkout@v4\n - uses: pnpm/action-setup@v4\n - uses: actions/setup-node@v4\n with:\n node-version: 22\n cache: pnpm\n - run: pnpm install --frozen-lockfile\n - name: Evaluate DoR (placeholder \u2014 wire to your DoR runner)\n run: |\n echo \"::notice::DoR ingress shim invoked. Wire pnpm --filter @ai-sdlc/pipeline-cli evaluate-dor here.\"\n";
|
|
72
|
+
/**
|
|
73
|
+
* `.ai-sdlc/review-classifier.yaml` stub — cost-optimized review tiers.
|
|
74
|
+
*
|
|
75
|
+
* The actual classifier code ships via AISDLC-141 (a follow-up). For now
|
|
76
|
+
* the wizard scaffolds the config stub + a pointer to the classifier
|
|
77
|
+
* docs so adopters who opt in via `--with-classifier` are ready to flip
|
|
78
|
+
* on the workflow once AISDLC-141 lands.
|
|
79
|
+
*/
|
|
80
|
+
export declare const REVIEW_CLASSIFIER_STUB = "# Review classifier configuration (AISDLC-141, follow-up).\n#\n# The review classifier inspects a PR diff and decides which review tier\n# to invoke (cheap-pattern-match \u2192 mid-tier-LLM \u2192 full reviewer fan-out)\n# to keep review costs bounded as PR volume grows.\n#\n# This file is a stub scaffolded by `ai-sdlc init --with-classifier`.\n# The classifier runtime ships in AISDLC-141; until then this config is\n# advisory only. See docs/operations/init.md for the migration path.\n\napiVersion: ai-sdlc.io/v1alpha1\nkind: ReviewClassifier\nmetadata:\n name: default-classifier\nspec:\n tiers:\n - name: cheap\n maxFilesChanged: 5\n maxLinesChanged: 50\n strategy: pattern-match\n - name: mid\n maxFilesChanged: 20\n maxLinesChanged: 500\n strategy: single-llm-pass\n - name: full\n strategy: full-reviewer-fanout\n routing:\n docsOnly: cheap\n testOnly: cheap\n default: mid\n";
|
|
81
|
+
/**
|
|
82
|
+
* The set of feature templates exported as a single map so the wizard
|
|
83
|
+
* dispatcher can iterate without each feature growing its own switch
|
|
84
|
+
* statement.
|
|
85
|
+
*
|
|
86
|
+
* Each entry maps a relative path inside the target repo to the literal
|
|
87
|
+
* bytes to write. Paths are POSIX-style; the writer joins them onto the
|
|
88
|
+
* project dir using `node:path/join` which is platform-correct.
|
|
89
|
+
*/
|
|
90
|
+
export interface FeatureTemplateSet {
|
|
91
|
+
/** Files under the project root keyed by relative POSIX path. */
|
|
92
|
+
files: Record<string, string>;
|
|
93
|
+
}
|
|
94
|
+
export declare const DOR_TEMPLATES: FeatureTemplateSet;
|
|
95
|
+
export declare const ATTESTATION_TEMPLATES: FeatureTemplateSet;
|
|
96
|
+
export declare const CLASSIFIER_TEMPLATES: FeatureTemplateSet;
|
|
97
|
+
/**
|
|
98
|
+
* Always-on baseline workflow templates (regardless of wizard answers).
|
|
99
|
+
* Matches AC #4 in AISDLC-143: pipeline.yaml + agent-role.yaml +
|
|
100
|
+
* quality-gate.yaml + autonomy-policy.yaml are scaffolded by `initProject`
|
|
101
|
+
* (existing logic) and the gate workflow is scaffolded by this map.
|
|
102
|
+
*/
|
|
103
|
+
export declare const BASELINE_WORKFLOW_TEMPLATES: FeatureTemplateSet;
|
|
104
|
+
//# sourceMappingURL=init-templates.d.ts.map
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedded template strings scaffolded by `ai-sdlc init` (AISDLC-143).
|
|
3
|
+
*
|
|
4
|
+
* Why these live in code instead of being read from disk at runtime:
|
|
5
|
+
* - The orchestrator ships as an npm package; users `npm i -g
|
|
6
|
+
* @ai-sdlc/orchestrator` and run `ai-sdlc init` in a brand new repo.
|
|
7
|
+
* The `dist/` payload would not include arbitrary `*.yml` source
|
|
8
|
+
* fixtures unless we listed each one in `package.json#files` AND
|
|
9
|
+
* plumbed a `__dirname`-based loader through esm import-meta.url.
|
|
10
|
+
* - Embedded strings work identically when invoked via `node ./dist/...`
|
|
11
|
+
* from a checkout, via `npx @ai-sdlc/orchestrator init`, or via a
|
|
12
|
+
* pre-bundled binary, with no runtime filesystem dependency.
|
|
13
|
+
*
|
|
14
|
+
* Drift policy: when the canonical workflow at
|
|
15
|
+
* `.github/workflows/ai-sdlc-gate.yml` (or the audit-only
|
|
16
|
+
* `verify-attestation.yml`) is updated for adopters, mirror the change
|
|
17
|
+
* here. The init-workspace test suite includes a smoke check that the
|
|
18
|
+
* embedded copy at least parses as a YAML mapping; AISDLC-140 sub-3's
|
|
19
|
+
* cutover memo will add a hard byte-equality assertion against the live
|
|
20
|
+
* file once the framework's own copy stabilizes.
|
|
21
|
+
*
|
|
22
|
+
* Q-decisions baked into the templates:
|
|
23
|
+
* - Q1 (prescriptive default): the gate workflow is scaffolded
|
|
24
|
+
* unconditionally — every adopter gets `ai-sdlc/pr-ready` on day one.
|
|
25
|
+
* - Q3 (attestation = audit-only): verify-attestation template is the
|
|
26
|
+
* audit-only variant; signing infrastructure is opt-in via
|
|
27
|
+
* `--with-attestation`.
|
|
28
|
+
* - Q4(b) (interactive default with --yes escape hatch): see
|
|
29
|
+
* `init-features.ts` for the wizard wiring; this module just supplies
|
|
30
|
+
* the byte content.
|
|
31
|
+
*/
|
|
32
|
+
/** `.github/workflows/ai-sdlc-gate.yml` — single rollup PR-ready check. */
|
|
33
|
+
export const AI_SDLC_GATE_WORKFLOW = `name: AI-SDLC PR Ready Gate
|
|
34
|
+
|
|
35
|
+
# Single rollup status check \`ai-sdlc/pr-ready\` that aggregates every PR
|
|
36
|
+
# signal AI-SDLC adopters need into ONE branch-protection entry. Replaces
|
|
37
|
+
# the historical pattern of enumerating N required checks by name + app_id,
|
|
38
|
+
# which is brittle against path filters, [skip ci] tokens, matrix changes,
|
|
39
|
+
# and multi-app posters. See \`docs/operations/quality-gate.md\` for the
|
|
40
|
+
# full rationale.
|
|
41
|
+
#
|
|
42
|
+
# Industry pattern: \`re-actors/alls-green\` ("alls-green") is the de facto
|
|
43
|
+
# community fix; named adopters include aiohttp, attrs, conda, setuptools,
|
|
44
|
+
# pytest, pip-tools, Open edX, PyCA, PyPA, Mergify.
|
|
45
|
+
|
|
46
|
+
on:
|
|
47
|
+
pull_request:
|
|
48
|
+
types: [opened, synchronize, reopened]
|
|
49
|
+
merge_group:
|
|
50
|
+
types: [checks_requested]
|
|
51
|
+
|
|
52
|
+
concurrency:
|
|
53
|
+
group: ai-sdlc-gate-\${{ github.event.pull_request.number || github.event.merge_group.head_sha || github.ref }}
|
|
54
|
+
cancel-in-progress: true
|
|
55
|
+
|
|
56
|
+
permissions:
|
|
57
|
+
contents: read
|
|
58
|
+
pull-requests: read
|
|
59
|
+
checks: write
|
|
60
|
+
|
|
61
|
+
jobs:
|
|
62
|
+
detect:
|
|
63
|
+
name: Detect Changes
|
|
64
|
+
runs-on: ubuntu-latest
|
|
65
|
+
outputs:
|
|
66
|
+
docs_only: \${{ steps.filter.outputs.docs_only }}
|
|
67
|
+
steps:
|
|
68
|
+
- uses: actions/checkout@v4
|
|
69
|
+
- id: filter
|
|
70
|
+
uses: dorny/paths-filter@v3
|
|
71
|
+
with:
|
|
72
|
+
predicate-quantifier: 'every'
|
|
73
|
+
filters: |
|
|
74
|
+
docs_only:
|
|
75
|
+
- 'docs/**'
|
|
76
|
+
- '*.md'
|
|
77
|
+
|
|
78
|
+
lint:
|
|
79
|
+
name: Lint & Format
|
|
80
|
+
runs-on: ubuntu-latest
|
|
81
|
+
steps:
|
|
82
|
+
- uses: actions/checkout@v4
|
|
83
|
+
- uses: pnpm/action-setup@v4
|
|
84
|
+
- uses: actions/setup-node@v4
|
|
85
|
+
with:
|
|
86
|
+
node-version: 22
|
|
87
|
+
cache: pnpm
|
|
88
|
+
- run: pnpm install --frozen-lockfile
|
|
89
|
+
- run: pnpm lint
|
|
90
|
+
- run: pnpm format:check
|
|
91
|
+
|
|
92
|
+
build-test:
|
|
93
|
+
name: Build & Test (Node \${{ matrix.node-version }})
|
|
94
|
+
needs: detect
|
|
95
|
+
if: needs.detect.outputs.docs_only != 'true'
|
|
96
|
+
runs-on: ubuntu-latest
|
|
97
|
+
strategy:
|
|
98
|
+
fail-fast: false
|
|
99
|
+
matrix:
|
|
100
|
+
node-version: [20, 22]
|
|
101
|
+
steps:
|
|
102
|
+
- uses: actions/checkout@v4
|
|
103
|
+
- uses: pnpm/action-setup@v4
|
|
104
|
+
- uses: actions/setup-node@v4
|
|
105
|
+
with:
|
|
106
|
+
node-version: \${{ matrix.node-version }}
|
|
107
|
+
cache: pnpm
|
|
108
|
+
- run: pnpm install --frozen-lockfile
|
|
109
|
+
- run: pnpm build
|
|
110
|
+
- run: pnpm test
|
|
111
|
+
|
|
112
|
+
coverage:
|
|
113
|
+
name: Coverage
|
|
114
|
+
needs: detect
|
|
115
|
+
if: needs.detect.outputs.docs_only != 'true'
|
|
116
|
+
runs-on: ubuntu-latest
|
|
117
|
+
steps:
|
|
118
|
+
- uses: actions/checkout@v4
|
|
119
|
+
- uses: pnpm/action-setup@v4
|
|
120
|
+
- uses: actions/setup-node@v4
|
|
121
|
+
with:
|
|
122
|
+
node-version: 22
|
|
123
|
+
cache: pnpm
|
|
124
|
+
- run: pnpm install --frozen-lockfile
|
|
125
|
+
- run: pnpm build
|
|
126
|
+
- run: pnpm test:coverage
|
|
127
|
+
|
|
128
|
+
pr-ready:
|
|
129
|
+
name: ai-sdlc/pr-ready
|
|
130
|
+
needs: [detect, lint, build-test, coverage]
|
|
131
|
+
if: always()
|
|
132
|
+
runs-on: ubuntu-latest
|
|
133
|
+
steps:
|
|
134
|
+
- name: Aggregate required signals
|
|
135
|
+
uses: re-actors/alls-green@release/v1
|
|
136
|
+
with:
|
|
137
|
+
jobs: \${{ toJSON(needs) }}
|
|
138
|
+
`;
|
|
139
|
+
/**
|
|
140
|
+
* `.github/workflows/verify-attestation.yml` — AUDIT-ONLY verifier.
|
|
141
|
+
*
|
|
142
|
+
* Per Q3 in /tmp/quality-gate-redesign-final.md, attestation infrastructure
|
|
143
|
+
* is opt-in and audit-only. This workflow logs verification results to the
|
|
144
|
+
* action run log but does NOT post a required-status check or block merges.
|
|
145
|
+
* Operators who want to promote attestation to a hard gate can edit the
|
|
146
|
+
* \`Log audit result\` step to write to commit statuses.
|
|
147
|
+
*/
|
|
148
|
+
export const VERIFY_ATTESTATION_WORKFLOW = `name: AI-SDLC Verify Review Attestation
|
|
149
|
+
|
|
150
|
+
# Reads the DSSE attestation at .ai-sdlc/attestations/<head-sha>.dsse.json
|
|
151
|
+
# and verifies the signature against any-of-N pubkeys in
|
|
152
|
+
# .ai-sdlc/trusted-reviewers.yaml.
|
|
153
|
+
#
|
|
154
|
+
# AUDIT-ONLY: this workflow logs verification results (success/failure with
|
|
155
|
+
# reason) for forensic purposes but does NOT post a required commit status.
|
|
156
|
+
# The single merge gate is \`ai-sdlc/pr-ready\` from ai-sdlc-gate.yml.
|
|
157
|
+
|
|
158
|
+
on:
|
|
159
|
+
pull_request:
|
|
160
|
+
types: [opened, synchronize, reopened]
|
|
161
|
+
branches: [main]
|
|
162
|
+
paths-ignore:
|
|
163
|
+
- 'docs/**'
|
|
164
|
+
- '*.md'
|
|
165
|
+
merge_group:
|
|
166
|
+
types: [checks_requested]
|
|
167
|
+
|
|
168
|
+
concurrency:
|
|
169
|
+
group: verify-attestation-\${{ github.event.pull_request.number || github.event.merge_group.head_sha }}
|
|
170
|
+
cancel-in-progress: true
|
|
171
|
+
|
|
172
|
+
jobs:
|
|
173
|
+
verify:
|
|
174
|
+
name: Verify attestation
|
|
175
|
+
runs-on: ubuntu-latest
|
|
176
|
+
permissions:
|
|
177
|
+
contents: read
|
|
178
|
+
steps:
|
|
179
|
+
- name: Resolve subject SHA + base SHA from event payload
|
|
180
|
+
id: resolve
|
|
181
|
+
run: |
|
|
182
|
+
if [ "\${{ github.event_name }}" = "merge_group" ]; then
|
|
183
|
+
echo "head_sha=\${{ github.event.merge_group.head_sha }}" >> "$GITHUB_OUTPUT"
|
|
184
|
+
echo "base_sha=\${{ github.event.merge_group.base_sha }}" >> "$GITHUB_OUTPUT"
|
|
185
|
+
else
|
|
186
|
+
echo "head_sha=\${{ github.event.pull_request.head.sha }}" >> "$GITHUB_OUTPUT"
|
|
187
|
+
echo "base_sha=\${{ github.event.pull_request.base.sha }}" >> "$GITHUB_OUTPUT"
|
|
188
|
+
fi
|
|
189
|
+
|
|
190
|
+
- uses: actions/checkout@v4
|
|
191
|
+
with:
|
|
192
|
+
fetch-depth: 0
|
|
193
|
+
ref: \${{ steps.resolve.outputs.head_sha }}
|
|
194
|
+
|
|
195
|
+
- name: Log audit result
|
|
196
|
+
env:
|
|
197
|
+
HEAD_SHA: \${{ steps.resolve.outputs.head_sha }}
|
|
198
|
+
run: |
|
|
199
|
+
if [ -f ".ai-sdlc/attestations/\${HEAD_SHA}.dsse.json" ]; then
|
|
200
|
+
echo "::notice::ai-sdlc attestation AUDIT — envelope present at \${HEAD_SHA}"
|
|
201
|
+
else
|
|
202
|
+
echo "::notice::ai-sdlc attestation AUDIT — no envelope on \${HEAD_SHA} (audit-only, not blocking)"
|
|
203
|
+
fi
|
|
204
|
+
`;
|
|
205
|
+
/**
|
|
206
|
+
* `.husky/pre-push` snippet that signs an attestation when one is missing
|
|
207
|
+
* for the current HEAD. Installed when `--with-attestation` is opted in;
|
|
208
|
+
* the actual `sign-attestation.mjs` script ships separately with the
|
|
209
|
+
* orchestrator and is referenced by the canonical command stub here.
|
|
210
|
+
*
|
|
211
|
+
* Adopters typically already have a `.husky/pre-push` from their existing
|
|
212
|
+
* tooling; the wizard appends our snippet behind a sentinel so we can
|
|
213
|
+
* extend an existing hook without trampling user content.
|
|
214
|
+
*/
|
|
215
|
+
export const HUSKY_PREPUSH_SIGN_SNIPPET = `# ai-sdlc:attestation-sign-block
|
|
216
|
+
# Signs the DSSE attestation envelope for the current HEAD when verdict
|
|
217
|
+
# files exist. Skip with AI_SDLC_SKIP_ATTESTATION_SIGN=1.
|
|
218
|
+
if [ -z "\${AI_SDLC_SKIP_ATTESTATION_SIGN:-}" ] && [ -x "./scripts/check-attestation-sign.sh" ]; then
|
|
219
|
+
./scripts/check-attestation-sign.sh
|
|
220
|
+
fi
|
|
221
|
+
# end ai-sdlc:attestation-sign-block
|
|
222
|
+
`;
|
|
223
|
+
/**
|
|
224
|
+
* `.ai-sdlc/trusted-reviewers.yaml` stub — empty allowlist with operator
|
|
225
|
+
* instructions. The wizard scaffolds this so adopters have a single file
|
|
226
|
+
* to receive contributor pubkey PRs into; bootstrap a contributor with
|
|
227
|
+
* `/ai-sdlc init-signing-key` and append the printed YAML block.
|
|
228
|
+
*/
|
|
229
|
+
export const TRUSTED_REVIEWERS_STUB = `# Trusted contributor signing keys for review attestations.
|
|
230
|
+
#
|
|
231
|
+
# This file is a stub created by \`ai-sdlc init --with-attestation\`. Add
|
|
232
|
+
# entries by running \`/ai-sdlc init-signing-key\` on a contributor's
|
|
233
|
+
# machine and opening a PR that appends the printed YAML block below.
|
|
234
|
+
#
|
|
235
|
+
# Schema:
|
|
236
|
+
# - identity: free-form string (typically email or GitHub handle)
|
|
237
|
+
# - machine: free-form label (lets one identity register multiple keys)
|
|
238
|
+
# - pubkey: PEM-encoded ed25519 public key (multi-line block scalar)
|
|
239
|
+
# - addedAt: ISO 8601 date the entry was added
|
|
240
|
+
# - addedBy: GitHub handle of the maintainer who approved this entry's PR
|
|
241
|
+
#
|
|
242
|
+
# The verifier in CI uses a strict YAML format: every scalar value
|
|
243
|
+
# single-quoted; \`pubkey:\` is a \`|\` block scalar with each PEM line
|
|
244
|
+
# indented exactly 6 spaces; no tab characters anywhere.
|
|
245
|
+
|
|
246
|
+
reviewers: []
|
|
247
|
+
`;
|
|
248
|
+
/**
|
|
249
|
+
* `.ai-sdlc/dor-config.yaml` stub — Definition-of-Ready rubric config.
|
|
250
|
+
*
|
|
251
|
+
* Mirrors the production DoR config used by the framework itself; ships
|
|
252
|
+
* in warn-only mode so a fresh adopter does not get blocked by the rubric
|
|
253
|
+
* while they tune it.
|
|
254
|
+
*/
|
|
255
|
+
export const DOR_CONFIG_STUB = `# Definition-of-Ready (DoR) gate configuration.
|
|
256
|
+
#
|
|
257
|
+
# The DoR rubric scores incoming issues + backlog tasks against seven
|
|
258
|
+
# criteria (binary-testable ACs, no wishlist markers, references resolve,
|
|
259
|
+
# bounded scope, surface named, done-state describable, no invisible
|
|
260
|
+
# dependencies). Failing the rubric posts a clarification comment on the
|
|
261
|
+
# issue / PR.
|
|
262
|
+
#
|
|
263
|
+
# Ships in warn-only mode by default — flip to 'enforce' after the soak
|
|
264
|
+
# window confirms the false-positive rate is low.
|
|
265
|
+
|
|
266
|
+
apiVersion: ai-sdlc.io/v1alpha1
|
|
267
|
+
kind: DorConfig
|
|
268
|
+
metadata:
|
|
269
|
+
name: ai-sdlc-dor
|
|
270
|
+
spec:
|
|
271
|
+
rubricVersion: v1
|
|
272
|
+
evaluationMode: warn-only
|
|
273
|
+
|
|
274
|
+
notifications:
|
|
275
|
+
authorChannel: true
|
|
276
|
+
# dedicatedChannel:
|
|
277
|
+
# slack: '#ai-sdlc-dor'
|
|
278
|
+
|
|
279
|
+
staleness:
|
|
280
|
+
warnAfterDays: 14
|
|
281
|
+
closeAfterDays: 28
|
|
282
|
+
closedLabel: 'closed-as-stale-dor'
|
|
283
|
+
`;
|
|
284
|
+
/** `.github/workflows/dor-ingress.yml` — minimal DoR ingress shim. */
|
|
285
|
+
export const DOR_INGRESS_WORKFLOW = `name: AI-SDLC DoR Ingress
|
|
286
|
+
|
|
287
|
+
# Wires the DoR rubric into the GitHub issue + PR lifecycle:
|
|
288
|
+
# - issues:opened / issues:edited → score the issue body, post the
|
|
289
|
+
# idempotent clarification comment when needs-clarification.
|
|
290
|
+
# - pull_request touching backlog/tasks/*.md → score the changed
|
|
291
|
+
# task bodies (the in-repo equivalent of an issue).
|
|
292
|
+
#
|
|
293
|
+
# Ships in warn-only mode (see .ai-sdlc/dor-config.yaml). Flip the
|
|
294
|
+
# config's \`evaluationMode\` to \`enforce\` after the soak window.
|
|
295
|
+
|
|
296
|
+
on:
|
|
297
|
+
issues:
|
|
298
|
+
types: [opened, edited]
|
|
299
|
+
pull_request:
|
|
300
|
+
types: [opened, synchronize, reopened]
|
|
301
|
+
paths:
|
|
302
|
+
- 'backlog/tasks/*.md'
|
|
303
|
+
|
|
304
|
+
concurrency:
|
|
305
|
+
group: dor-ingress-\${{ github.event.issue.number || github.event.pull_request.number }}
|
|
306
|
+
cancel-in-progress: true
|
|
307
|
+
|
|
308
|
+
jobs:
|
|
309
|
+
evaluate:
|
|
310
|
+
name: Evaluate against DoR rubric
|
|
311
|
+
runs-on: ubuntu-latest
|
|
312
|
+
permissions:
|
|
313
|
+
issues: write
|
|
314
|
+
pull-requests: write
|
|
315
|
+
contents: read
|
|
316
|
+
steps:
|
|
317
|
+
- uses: actions/checkout@v4
|
|
318
|
+
- uses: pnpm/action-setup@v4
|
|
319
|
+
- uses: actions/setup-node@v4
|
|
320
|
+
with:
|
|
321
|
+
node-version: 22
|
|
322
|
+
cache: pnpm
|
|
323
|
+
- run: pnpm install --frozen-lockfile
|
|
324
|
+
- name: Evaluate DoR (placeholder — wire to your DoR runner)
|
|
325
|
+
run: |
|
|
326
|
+
echo "::notice::DoR ingress shim invoked. Wire pnpm --filter @ai-sdlc/pipeline-cli evaluate-dor here."
|
|
327
|
+
`;
|
|
328
|
+
/**
|
|
329
|
+
* `.ai-sdlc/review-classifier.yaml` stub — cost-optimized review tiers.
|
|
330
|
+
*
|
|
331
|
+
* The actual classifier code ships via AISDLC-141 (a follow-up). For now
|
|
332
|
+
* the wizard scaffolds the config stub + a pointer to the classifier
|
|
333
|
+
* docs so adopters who opt in via `--with-classifier` are ready to flip
|
|
334
|
+
* on the workflow once AISDLC-141 lands.
|
|
335
|
+
*/
|
|
336
|
+
export const REVIEW_CLASSIFIER_STUB = `# Review classifier configuration (AISDLC-141, follow-up).
|
|
337
|
+
#
|
|
338
|
+
# The review classifier inspects a PR diff and decides which review tier
|
|
339
|
+
# to invoke (cheap-pattern-match → mid-tier-LLM → full reviewer fan-out)
|
|
340
|
+
# to keep review costs bounded as PR volume grows.
|
|
341
|
+
#
|
|
342
|
+
# This file is a stub scaffolded by \`ai-sdlc init --with-classifier\`.
|
|
343
|
+
# The classifier runtime ships in AISDLC-141; until then this config is
|
|
344
|
+
# advisory only. See docs/operations/init.md for the migration path.
|
|
345
|
+
|
|
346
|
+
apiVersion: ai-sdlc.io/v1alpha1
|
|
347
|
+
kind: ReviewClassifier
|
|
348
|
+
metadata:
|
|
349
|
+
name: default-classifier
|
|
350
|
+
spec:
|
|
351
|
+
tiers:
|
|
352
|
+
- name: cheap
|
|
353
|
+
maxFilesChanged: 5
|
|
354
|
+
maxLinesChanged: 50
|
|
355
|
+
strategy: pattern-match
|
|
356
|
+
- name: mid
|
|
357
|
+
maxFilesChanged: 20
|
|
358
|
+
maxLinesChanged: 500
|
|
359
|
+
strategy: single-llm-pass
|
|
360
|
+
- name: full
|
|
361
|
+
strategy: full-reviewer-fanout
|
|
362
|
+
routing:
|
|
363
|
+
docsOnly: cheap
|
|
364
|
+
testOnly: cheap
|
|
365
|
+
default: mid
|
|
366
|
+
`;
|
|
367
|
+
export const DOR_TEMPLATES = {
|
|
368
|
+
files: {
|
|
369
|
+
'.ai-sdlc/dor-config.yaml': DOR_CONFIG_STUB,
|
|
370
|
+
'.github/workflows/dor-ingress.yml': DOR_INGRESS_WORKFLOW,
|
|
371
|
+
},
|
|
372
|
+
};
|
|
373
|
+
export const ATTESTATION_TEMPLATES = {
|
|
374
|
+
files: {
|
|
375
|
+
'.ai-sdlc/trusted-reviewers.yaml': TRUSTED_REVIEWERS_STUB,
|
|
376
|
+
'.github/workflows/verify-attestation.yml': VERIFY_ATTESTATION_WORKFLOW,
|
|
377
|
+
// The .gitkeep ensures the attestations dir is tracked in git so the
|
|
378
|
+
// first PR's envelope lands cleanly without "directory does not exist"
|
|
379
|
+
// errors from the signing script.
|
|
380
|
+
'.ai-sdlc/attestations/.gitkeep': '',
|
|
381
|
+
},
|
|
382
|
+
};
|
|
383
|
+
export const CLASSIFIER_TEMPLATES = {
|
|
384
|
+
files: {
|
|
385
|
+
'.ai-sdlc/review-classifier.yaml': REVIEW_CLASSIFIER_STUB,
|
|
386
|
+
},
|
|
387
|
+
};
|
|
388
|
+
/**
|
|
389
|
+
* Always-on baseline workflow templates (regardless of wizard answers).
|
|
390
|
+
* Matches AC #4 in AISDLC-143: pipeline.yaml + agent-role.yaml +
|
|
391
|
+
* quality-gate.yaml + autonomy-policy.yaml are scaffolded by `initProject`
|
|
392
|
+
* (existing logic) and the gate workflow is scaffolded by this map.
|
|
393
|
+
*/
|
|
394
|
+
export const BASELINE_WORKFLOW_TEMPLATES = {
|
|
395
|
+
files: {
|
|
396
|
+
'.github/workflows/ai-sdlc-gate.yml': AI_SDLC_GATE_WORKFLOW,
|
|
397
|
+
},
|
|
398
|
+
};
|
|
399
|
+
//# sourceMappingURL=init-templates.js.map
|
|
@@ -12,8 +12,24 @@
|
|
|
12
12
|
* orchestrator version that ran init, with an inline opt-out hint.
|
|
13
13
|
* - Skip `.cursor/mcp.json` unless Cursor is detected (project-local
|
|
14
14
|
* `.cursor/`, user-global `~/.cursor/`) or `--cursor` is passed.
|
|
15
|
+
*
|
|
16
|
+
* AISDLC-143 enhancements (Q4(b) of the quality-gate redesign):
|
|
17
|
+
* - Default invocation is now an interactive WIZARD (DoR / attestation /
|
|
18
|
+
* classifier / branch-protection prompts) so adopters get a guided
|
|
19
|
+
* bootstrap instead of having to read the docs to discover features.
|
|
20
|
+
* - `--yes` short-circuits all prompts to "accept defaults" (CI/scripts).
|
|
21
|
+
* - `--with-X` flags opt into individual features without prompting.
|
|
22
|
+
* - `--add <feature>` extends an already-initialized repo with a single
|
|
23
|
+
* feature, idempotently — re-running on an initialized repo is safe.
|
|
24
|
+
* - `.github/workflows/ai-sdlc-gate.yml` is scaffolded UNCONDITIONALLY
|
|
25
|
+
* so every adopter gets the `ai-sdlc/pr-ready` rollup check on day one
|
|
26
|
+
* (Q1: prescriptive default).
|
|
27
|
+
* - A "next steps" summary closes the run with operator action items
|
|
28
|
+
* conditional on which features were chosen.
|
|
15
29
|
*/
|
|
16
30
|
import { Command } from 'commander';
|
|
31
|
+
import { type WizardFlags } from './init-features.js';
|
|
32
|
+
export declare const PIPELINE_YAML = "apiVersion: ai-sdlc.io/v1alpha1\nkind: Pipeline\nmetadata:\n name: default\nspec:\n triggers:\n - event: issue.labeled\n filter:\n labels:\n - ai-eligible\n providers:\n sourceControl:\n type: github\n config:\n org: your-org\n stages:\n - name: validate\n qualityGates:\n - default-gates\n - name: code\n agent: default-agent\n timeout: PT30M\n onFailure:\n strategy: retry\n maxRetries: 2\n - name: review\n qualityGates:\n - default-gates\n # backlog: holds settings specific to the backlog-task (/ai-sdlc execute)\n # workflow. These were formerly in a separate pipeline-backlog.yaml file\n # (deprecated by AISDLC-245.5). Slash commands + pipeline-cli readers\n # prefer this canonical location.\n backlog:\n branching:\n pattern: 'ai-sdlc/{issueIdLower}-{slug}'\n targetBranch: main\n cleanup: on-merge\n pullRequest:\n titleTemplate: 'feat: {issueTitle} ({issueId})'\n descriptionSections:\n - summary\n - changes\n - closes\n includeProvenance: true\n closeKeyword: References\n";
|
|
17
33
|
/**
|
|
18
34
|
* Tier-based agent-role templates (AISDLC-79).
|
|
19
35
|
*
|
|
@@ -28,5 +44,11 @@ export type AgentRoleTier = 'coding' | 'research' | 'meta';
|
|
|
28
44
|
export declare const AGENT_ROLE_TIERS: readonly AgentRoleTier[];
|
|
29
45
|
/** Resolve the agent-role.yaml template for a given tier. Default = `coding`. */
|
|
30
46
|
export declare function getAgentRoleYaml(tier?: AgentRoleTier): string;
|
|
47
|
+
/**
|
|
48
|
+
* Build the WizardFlags struct from Commander's parsed options. Pulled
|
|
49
|
+
* out into a function so tests can drive the wizard pipeline directly
|
|
50
|
+
* without going through Commander's stateful option store.
|
|
51
|
+
*/
|
|
52
|
+
export declare function buildWizardFlags(opts: Record<string, unknown>): WizardFlags;
|
|
31
53
|
export declare const initCommand: Command;
|
|
32
54
|
//# sourceMappingURL=init.d.ts.map
|