ai-delivery-workflow 0.4.0 → 0.5.1
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/README.md +7 -8
- package/bin/ai-delivery.mjs +2 -24
- package/bin/release-check.mjs +8 -2
- package/docs/CLI-PARAMETER-REFERENCE.zh-CN.md +6 -67
- package/docs/DUAL-REPOSITORY-WORKSPACE.zh-CN.md +14 -1
- package/docs/FILE-REFERENCE.zh-CN.md +17 -36
- package/docs/MAINTENANCE-VERIFICATION.zh-CN.md +2 -2
- package/docs/NPM-RELEASE-MANAGEMENT.zh-CN.md +2 -1
- package/docs/PROJECT-MANUAL.zh-CN.md +50 -43
- package/docs/STATE-CLI-MAINTENANCE.zh-CN.md +8 -10
- package/docs/STATE-CLI-USER-GUIDE.zh-CN.md +7 -17
- package/docs/adr/0006-product-line-candidate-inventory.md +20 -0
- package/docs/agents/domain.md +31 -6
- package/docs/agents/issue-tracker.md +17 -18
- package/docs/agents/triage-labels.md +7 -7
- package/docs/agents/workflow-manager-acceptance-matrix.md +9 -15
- package/docs/agents/workflow-manager-current-state.md +14 -17
- package/lib/delivery-state.mjs +59 -910
- package/lib/fs-utils.mjs +0 -16
- package/lib/npm-auth.mjs +16 -0
- package/lib/project-bootstrap.mjs +21 -58
- package/lib/project-installer.mjs +24 -180
- package/lib/project-repair.mjs +217 -0
- package/lib/toml-hooks.mjs +2 -4
- package/lib/workflow-manager-governance.mjs +3 -47
- package/lib/workspace.mjs +2 -3
- package/package.json +2 -2
- package/skills/ai-delivery-assemble-release/SKILL.md +10 -8
- package/skills/ai-delivery-assemble-release/agents/openai.yaml +3 -3
- package/skills/ai-delivery-assemble-release/assets/release-candidate-manifest.yaml +16 -4
- package/skills/ai-delivery-assemble-release/assets/release-git-plan.yaml +96 -6
- package/skills/ai-delivery-assemble-release/assets/version-inclusion.csv +2 -2
- package/skills/ai-delivery-assemble-release/references/release-assembly-contract.md +16 -2
- package/skills/ai-delivery-assemble-release/scripts/plan-release.mjs +127 -3
- package/skills/ai-delivery-bootstrap/SKILL.md +1 -1
- package/skills/ai-delivery-bootstrap/agents/openai.yaml +3 -3
- package/skills/ai-delivery-bootstrap/references/bootstrap-contract.md +1 -1
- package/skills/ai-delivery-checkpoint-task/SKILL.md +0 -4
- package/skills/ai-delivery-checkpoint-task/agents/openai.yaml +3 -3
- package/skills/ai-delivery-checkpoint-task/references/checkpoint-contract.md +2 -2
- package/skills/ai-delivery-checkpoint-task/scripts/hook-event.mjs +2 -8
- package/skills/ai-delivery-checkpoint-task/scripts/task-state.mjs +26 -46
- package/skills/ai-delivery-close-version/agents/openai.yaml +3 -3
- package/skills/ai-delivery-define-product/agents/openai.yaml +4 -4
- package/skills/ai-delivery-deploy-production/agents/openai.yaml +3 -3
- package/skills/ai-delivery-design-experience/SKILL.md +3 -3
- package/skills/ai-delivery-design-experience/agents/openai.yaml +4 -4
- package/skills/ai-delivery-design-experience/references/experience-contract.md +1 -11
- package/skills/ai-delivery-design-experience/references/prototype-management-contract.md +1 -1
- package/skills/ai-delivery-develop-iteration/agents/openai.yaml +3 -3
- package/skills/ai-delivery-evolve-workflow/agents/openai.yaml +3 -3
- package/skills/ai-delivery-execute-test/agents/openai.yaml +4 -4
- package/skills/ai-delivery-execute-work-package/agents/openai.yaml +4 -4
- package/skills/ai-delivery-manage-git/SKILL.md +9 -7
- package/skills/ai-delivery-manage-git/agents/openai.yaml +3 -3
- package/skills/ai-delivery-manage-git/references/git-policy.md +7 -3
- package/skills/ai-delivery-manage-git/scripts/release-git.mjs +995 -0
- package/skills/ai-delivery-manage-standards/agents/openai.yaml +4 -4
- package/skills/ai-delivery-orchestrate/SKILL.md +5 -7
- package/skills/ai-delivery-orchestrate/agents/openai.yaml +3 -3
- package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/tools/hooks/hook-event.mjs +2 -8
- package/skills/ai-delivery-orchestrate/assets/project-template/AGENTS.md +9 -8
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/CONTRIBUTING.md +25 -25
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/airbnb/DESIGN.md +545 -545
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/airbnb/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/airtable/DESIGN.md +554 -554
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/airtable/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/apple/DESIGN.md +562 -562
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/apple/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/binance/DESIGN.md +634 -634
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/binance/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bmw/DESIGN.md +544 -544
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bmw/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bmw-m/DESIGN.md +503 -503
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bmw-m/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bugatti/DESIGN.md +454 -454
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/bugatti/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cal/DESIGN.md +542 -542
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cal/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/claude/DESIGN.md +589 -589
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/claude/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/clay/DESIGN.md +541 -541
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/clay/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/clickhouse/DESIGN.md +544 -544
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/clickhouse/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cohere/DESIGN.md +451 -451
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cohere/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/coinbase/DESIGN.md +570 -570
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/coinbase/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/composio/DESIGN.md +506 -506
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/composio/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cursor/DESIGN.md +537 -537
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/cursor/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/dell-1996/DESIGN.md +632 -632
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/dell-1996/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/elevenlabs/DESIGN.md +504 -504
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/elevenlabs/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/expo/DESIGN.md +526 -526
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/expo/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ferrari/DESIGN.md +531 -531
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ferrari/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/figma/DESIGN.md +578 -578
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/figma/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/framer/DESIGN.md +544 -544
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/framer/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/hashicorp/DESIGN.md +575 -575
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/hashicorp/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/hp/DESIGN.md +670 -670
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/hp/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ibm/DESIGN.md +550 -550
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ibm/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/intercom/DESIGN.md +546 -546
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/intercom/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/kraken/DESIGN.md +125 -125
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/kraken/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/lamborghini/DESIGN.md +288 -288
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/lamborghini/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/linear.app/DESIGN.md +548 -548
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/linear.app/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/lovable/DESIGN.md +298 -298
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/lovable/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mastercard/DESIGN.md +365 -365
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mastercard/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/meta/DESIGN.md +683 -683
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/meta/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/minimax/DESIGN.md +746 -746
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/minimax/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mintlify/DESIGN.md +852 -852
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mintlify/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/miro/DESIGN.md +825 -825
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/miro/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mistral.ai/DESIGN.md +773 -773
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mistral.ai/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mongodb/DESIGN.md +767 -767
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/mongodb/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nike/DESIGN.md +575 -575
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nike/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nintendo-2001/DESIGN.md +649 -649
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nintendo-2001/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/notion/DESIGN.md +821 -821
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/notion/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nvidia/DESIGN.md +640 -640
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/nvidia/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ollama/DESIGN.md +539 -539
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/ollama/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/opencode.ai/DESIGN.md +521 -521
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/opencode.ai/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/pinterest/DESIGN.md +597 -597
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/pinterest/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/playstation/DESIGN.md +661 -661
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/playstation/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/posthog/DESIGN.md +690 -690
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/posthog/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/raycast/DESIGN.md +669 -669
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/raycast/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/renault/DESIGN.md +589 -589
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/renault/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/replicate/DESIGN.md +616 -616
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/replicate/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/resend/DESIGN.md +585 -585
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/resend/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/revolut/DESIGN.md +636 -636
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/revolut/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/runwayml/DESIGN.md +244 -244
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/runwayml/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/sanity/DESIGN.md +357 -357
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/sanity/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/sentry/DESIGN.md +551 -551
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/sentry/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/shopify/DESIGN.md +516 -516
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/shopify/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/slack/DESIGN.md +482 -482
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/spacex/DESIGN.md +363 -363
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/spacex/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/spotify/DESIGN.md +246 -246
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/spotify/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/starbucks/DESIGN.md +580 -580
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/starbucks/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/stripe/DESIGN.md +487 -487
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/stripe/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/supabase/DESIGN.md +462 -462
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/supabase/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/superhuman/DESIGN.md +448 -448
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/superhuman/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/tesla/DESIGN.md +286 -286
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/tesla/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/theverge/DESIGN.md +339 -339
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/theverge/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/together.ai/DESIGN.md +633 -633
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/together.ai/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/uber/DESIGN.md +636 -636
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/uber/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/vercel/DESIGN.md +736 -736
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/vercel/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/vodafone/DESIGN.md +538 -538
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/vodafone/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/voltagent/DESIGN.md +521 -521
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/voltagent/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/warp/DESIGN.md +526 -526
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/warp/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/webflow/DESIGN.md +588 -588
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/webflow/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/wired/DESIGN.md +497 -497
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/wired/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/wise/DESIGN.md +544 -544
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/wise/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/x.ai/DESIGN.md +465 -465
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/x.ai/README.md +5 -5
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/zapier/DESIGN.md +537 -537
- package/skills/ai-delivery-orchestrate/assets/project-template/ref/ui/design-md/zapier/README.md +5 -5
- package/skills/ai-delivery-orchestrate/references/formal-state-contract.md +11 -20
- package/skills/ai-delivery-orchestrate/references/workflow-model.md +2 -4
- package/skills/ai-delivery-orchestrate-release/SKILL.md +10 -10
- package/skills/ai-delivery-orchestrate-release/agents/openai.yaml +4 -4
- package/skills/ai-delivery-orchestrate-release/assets/release-request.yaml +4 -1
- package/skills/ai-delivery-orchestrate-release/assets/version-selection.yaml +13 -1
- package/skills/ai-delivery-orchestrate-release/references/release-workflow-contract.md +14 -0
- package/skills/ai-delivery-plan-iteration/agents/openai.yaml +4 -4
- package/skills/ai-delivery-prepare-platform/agents/openai.yaml +4 -4
- package/skills/ai-delivery-prepare-release/SKILL.md +6 -5
- package/skills/ai-delivery-prepare-release/agents/openai.yaml +4 -4
- package/skills/ai-delivery-prepare-release/assets/release-template/release-manifest.yaml +21 -2
- package/skills/ai-delivery-prepare-release/references/release-contract.md +5 -1
- package/skills/ai-delivery-review-change/agents/openai.yaml +4 -4
- package/skills/ai-delivery-triage-failure/agents/openai.yaml +4 -4
- package/skills/ai-delivery-validate-artifacts/agents/openai.yaml +4 -4
- package/skills/ai-delivery-verify-candidate/agents/openai.yaml +3 -3
- package/skills/ai-delivery-verify-production/SKILL.md +7 -4
- package/skills/ai-delivery-verify-production/agents/openai.yaml +3 -3
- package/skills/ai-delivery-verify-production/assets/production-verification-template/production-verification.json +9 -0
- package/skills/ai-delivery-verify-production/assets/production-verification-template/production-verification.md +20 -0
- package/skills/ai-delivery-verify-production/references/production-verification-contract.md +19 -3
- package/docs/PROTOTYPE-MIGRATION.zh-CN.md +0 -164
- package/docs/VIEWER-MAINTENANCE.zh-CN.md +0 -150
- package/docs/VIEWER-USER-GUIDE.zh-CN.md +0 -113
- package/lib/project-migration.mjs +0 -1193
- package/lib/prototype-migration.mjs +0 -713
- package/skills/ai-delivery-design-experience/assets/experience-template/LEGACY-COMPATIBILITY.md +0 -16
- package/skills/ai-delivery-design-experience/assets/experience-template/canvas-catalog.csv +0 -1
- package/skills/ai-delivery-design-experience/assets/experience-template/canvas-pages.csv +0 -1
- package/skills/ai-delivery-design-experience/assets/experience-template/page-catalog.csv +0 -1
- package/skills/ai-delivery-design-experience/assets/experience-template/prototype-file-terminals.csv +0 -1
- package/skills/ai-delivery-design-experience/assets/experience-template/prototype-files.csv +0 -1
- package/skills/ai-delivery-design-experience/assets/experience-template/prototype-manifest.yaml +0 -76
- package/skills/ai-delivery-design-experience/assets/experience-template/prototype-set.yaml +0 -24
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { parse as parseYaml } from "yaml";
|
|
5
|
+
import { atomicWrite, filesUnder } from "./fs-utils.mjs";
|
|
6
|
+
|
|
7
|
+
function toPosix(value) {
|
|
8
|
+
return value.replaceAll("\\", "/");
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function sha256(value) {
|
|
12
|
+
return crypto.createHash("sha256").update(value).digest("hex");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function treeDigest(root) {
|
|
16
|
+
const hash = crypto.createHash("sha256");
|
|
17
|
+
for (const file of filesUnder(root)) {
|
|
18
|
+
hash.update(toPosix(path.relative(root, file)));
|
|
19
|
+
hash.update("\0");
|
|
20
|
+
hash.update(fs.readFileSync(file));
|
|
21
|
+
hash.update("\0");
|
|
22
|
+
}
|
|
23
|
+
return hash.digest("hex");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function readStructured(file, label) {
|
|
27
|
+
try {
|
|
28
|
+
const text = fs.readFileSync(file, "utf8");
|
|
29
|
+
const value = path.extname(file).toLowerCase() === ".json" ? JSON.parse(text) : parseYaml(text);
|
|
30
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("expected a mapping");
|
|
31
|
+
return value;
|
|
32
|
+
} catch (error) {
|
|
33
|
+
throw new Error(`Cannot read ${label} (${toPosix(file)}): ${error.message}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function stableValue(value) {
|
|
38
|
+
if (Array.isArray(value)) return value.map(stableValue);
|
|
39
|
+
if (!value || typeof value !== "object") return value;
|
|
40
|
+
return Object.fromEntries(Object.keys(value).sort().map((key) => [key, stableValue(value[key])]));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function stableJson(value) {
|
|
44
|
+
return JSON.stringify(stableValue(value));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function uniqueSorted(values) {
|
|
48
|
+
return [...new Set((Array.isArray(values) ? values : []).map(String))].sort();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function unsignedRepairRecord(record) {
|
|
52
|
+
const unsigned = { ...record };
|
|
53
|
+
delete unsigned.record_checksum;
|
|
54
|
+
return unsigned;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function readRepairTransactions(project) {
|
|
58
|
+
const directory = path.join(project, ".workflow", "control", "repairs", "transactions");
|
|
59
|
+
const records = [];
|
|
60
|
+
let previousChecksum = null;
|
|
61
|
+
for (const file of filesUnder(directory).filter((item) => item.endsWith(".json"))) {
|
|
62
|
+
const record = readStructured(file, "repair transaction");
|
|
63
|
+
if (record.schema_version !== 1
|
|
64
|
+
|| !Number.isInteger(record.sequence)
|
|
65
|
+
|| record.sequence !== records.length + 1
|
|
66
|
+
|| record.previous_checksum !== previousChecksum
|
|
67
|
+
|| record.record_checksum !== sha256(stableJson(unsignedRepairRecord(record)))) {
|
|
68
|
+
throw new Error(`Repair transaction chain is invalid: ${toPosix(path.relative(project, file))}.`);
|
|
69
|
+
}
|
|
70
|
+
records.push(record);
|
|
71
|
+
previousChecksum = record.record_checksum;
|
|
72
|
+
}
|
|
73
|
+
return records;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function archiveIterationId(value) {
|
|
77
|
+
const iterationId = String(value || "");
|
|
78
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(iterationId)) {
|
|
79
|
+
throw new Error(`Invalid archive iteration ID: ${iterationId || "missing"}.`);
|
|
80
|
+
}
|
|
81
|
+
return iterationId;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function verifiedArchiveInvalidations(project, records) {
|
|
85
|
+
for (const record of records.filter((item) => item.transaction_type === "archive-invalidation")) {
|
|
86
|
+
const iterationId = archiveIterationId(record.target?.iteration_id);
|
|
87
|
+
const expectedArchivePath = `.workflow/control/archives/versions/${iterationId}`;
|
|
88
|
+
const expectedManifestPath = `${expectedArchivePath}/version-manifest.json`;
|
|
89
|
+
if (record.target.archive_path !== expectedArchivePath
|
|
90
|
+
|| record.target.manifest_path !== expectedManifestPath
|
|
91
|
+
|| !/^[a-f0-9]{64}$/.test(record.target.archive_sha256 || "")
|
|
92
|
+
|| !/^[a-f0-9]{64}$/.test(record.target.manifest_sha256 || "")) {
|
|
93
|
+
throw new Error(`Archive invalidation target is invalid: ${record.transaction_id}.`);
|
|
94
|
+
}
|
|
95
|
+
const archiveDirectory = path.join(project, ...expectedArchivePath.split("/"));
|
|
96
|
+
const manifestFile = path.join(project, ...expectedManifestPath.split("/"));
|
|
97
|
+
if (!fs.existsSync(manifestFile)
|
|
98
|
+
|| treeDigest(archiveDirectory) !== record.target.archive_sha256
|
|
99
|
+
|| sha256(fs.readFileSync(manifestFile)) !== record.target.manifest_sha256) {
|
|
100
|
+
throw new Error(`Invalidated archive ${iterationId} bytes changed after ${record.transaction_id}.`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function repairTransactionPath(sequence, transactionId) {
|
|
106
|
+
return `.workflow/control/repairs/transactions/${String(sequence).padStart(6, "0")}-${transactionId}.json`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function repairProject(project, options = {}) {
|
|
110
|
+
const root = path.resolve(project);
|
|
111
|
+
if (!fs.existsSync(root) || !fs.statSync(root).isDirectory()) {
|
|
112
|
+
throw new Error(`Project directory does not exist: ${root}`);
|
|
113
|
+
}
|
|
114
|
+
const iterationId = archiveIterationId(options.invalidateArchive);
|
|
115
|
+
const reason = String(options.reason || "").trim();
|
|
116
|
+
const actor = String(options.actor || "").trim();
|
|
117
|
+
const evidence = uniqueSorted(options.evidence);
|
|
118
|
+
if (!reason) throw new Error("Archive invalidation requires --reason.");
|
|
119
|
+
if (!actor.startsWith("human:")) {
|
|
120
|
+
throw new Error("Archive invalidation requires an explicit human actor through --actor human:<identity>.");
|
|
121
|
+
}
|
|
122
|
+
if (evidence.length < 2) {
|
|
123
|
+
throw new Error("Archive invalidation requires at least two --evidence values for RCA and recovery evidence.");
|
|
124
|
+
}
|
|
125
|
+
const archiveDirectory = path.join(root, ".workflow", "control", "archives", "versions", iterationId);
|
|
126
|
+
const manifestFile = path.join(archiveDirectory, "version-manifest.json");
|
|
127
|
+
if (!fs.existsSync(manifestFile)) throw new Error(`Version archive not found: ${iterationId}.`);
|
|
128
|
+
const manifest = readStructured(manifestFile, "version archive manifest");
|
|
129
|
+
if (manifest.iteration_id !== iterationId) {
|
|
130
|
+
throw new Error(`Version archive identity mismatch: expected ${iterationId}, found ${manifest.iteration_id || "missing"}.`);
|
|
131
|
+
}
|
|
132
|
+
const target = {
|
|
133
|
+
iteration_id: iterationId,
|
|
134
|
+
archive_path: toPosix(path.relative(root, archiveDirectory)),
|
|
135
|
+
manifest_path: toPosix(path.relative(root, manifestFile)),
|
|
136
|
+
manifest_sha256: sha256(fs.readFileSync(manifestFile)),
|
|
137
|
+
archive_sha256: treeDigest(archiveDirectory),
|
|
138
|
+
original_bytes_preserved: true,
|
|
139
|
+
};
|
|
140
|
+
const identity = { transaction_type: "archive-invalidation", target, correction: { actor, reason, evidence } };
|
|
141
|
+
const idempotencyKey = `archive-invalidation:${iterationId}:${sha256(stableJson(identity))}`;
|
|
142
|
+
const existingTransactions = readRepairTransactions(root);
|
|
143
|
+
verifiedArchiveInvalidations(root, existingTransactions);
|
|
144
|
+
const existing = existingTransactions.find((record) => record.idempotency_key === idempotencyKey);
|
|
145
|
+
const sequence = existing?.sequence || existingTransactions.length + 1;
|
|
146
|
+
const transactionId = existing?.transaction_id || `REPAIR-${sha256(idempotencyKey).slice(0, 16).toUpperCase()}`;
|
|
147
|
+
const transactionPath = repairTransactionPath(sequence, transactionId);
|
|
148
|
+
const report = {
|
|
149
|
+
command: "repair",
|
|
150
|
+
action: "archive-invalidation",
|
|
151
|
+
dry_run: Boolean(options.dryRun),
|
|
152
|
+
applied: false,
|
|
153
|
+
forward_only: true,
|
|
154
|
+
original_bytes_preserved: true,
|
|
155
|
+
target,
|
|
156
|
+
actor,
|
|
157
|
+
reason,
|
|
158
|
+
evidence,
|
|
159
|
+
transaction: {
|
|
160
|
+
transaction_id: transactionId,
|
|
161
|
+
path: transactionPath,
|
|
162
|
+
previous_checksum: existing?.previous_checksum || existingTransactions.at(-1)?.record_checksum || null,
|
|
163
|
+
},
|
|
164
|
+
eligibility: existing
|
|
165
|
+
? { iteration_id: iterationId, current: "invalidated", source_transaction_id: transactionId }
|
|
166
|
+
: { iteration_id: iterationId, current: "eligible", source_transaction_id: null },
|
|
167
|
+
};
|
|
168
|
+
if (report.dry_run || existing) return report;
|
|
169
|
+
|
|
170
|
+
const repairRoot = path.join(root, ".workflow", "control", "repairs");
|
|
171
|
+
const lockFile = path.join(repairRoot, ".repair.lock");
|
|
172
|
+
fs.mkdirSync(repairRoot, { recursive: true });
|
|
173
|
+
let lock;
|
|
174
|
+
try {
|
|
175
|
+
lock = fs.openSync(lockFile, "wx");
|
|
176
|
+
} catch (error) {
|
|
177
|
+
throw new Error(`Repair transaction is locked by another writer: ${error.message}`);
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
const currentTransactions = readRepairTransactions(root);
|
|
181
|
+
const duplicate = currentTransactions.find((record) => record.idempotency_key === idempotencyKey);
|
|
182
|
+
if (duplicate) {
|
|
183
|
+
report.transaction.transaction_id = duplicate.transaction_id;
|
|
184
|
+
report.transaction.path = repairTransactionPath(duplicate.sequence, duplicate.transaction_id);
|
|
185
|
+
report.eligibility = { iteration_id: iterationId, current: "invalidated", source_transaction_id: duplicate.transaction_id };
|
|
186
|
+
return report;
|
|
187
|
+
}
|
|
188
|
+
if (currentTransactions.length !== existingTransactions.length
|
|
189
|
+
|| (currentTransactions.at(-1)?.record_checksum || null) !== (existingTransactions.at(-1)?.record_checksum || null)) {
|
|
190
|
+
throw new Error("Repair transaction revision changed during apply; rerun the command.");
|
|
191
|
+
}
|
|
192
|
+
if (treeDigest(archiveDirectory) !== target.archive_sha256
|
|
193
|
+
|| sha256(fs.readFileSync(manifestFile)) !== target.manifest_sha256) {
|
|
194
|
+
throw new Error(`Version archive changed during repair apply: ${iterationId}.`);
|
|
195
|
+
}
|
|
196
|
+
const transaction = {
|
|
197
|
+
schema_version: 1,
|
|
198
|
+
sequence,
|
|
199
|
+
transaction_id: transactionId,
|
|
200
|
+
transaction_type: "archive-invalidation",
|
|
201
|
+
idempotency_key: idempotencyKey,
|
|
202
|
+
occurred_at: new Date().toISOString(),
|
|
203
|
+
target,
|
|
204
|
+
correction: { actor, reason, evidence },
|
|
205
|
+
previous_checksum: existingTransactions.at(-1)?.record_checksum || null,
|
|
206
|
+
};
|
|
207
|
+
transaction.record_checksum = sha256(stableJson(transaction));
|
|
208
|
+
atomicWrite(path.join(root, ...transactionPath.split("/")), `${JSON.stringify(transaction, null, 2)}\n`);
|
|
209
|
+
report.applied = true;
|
|
210
|
+
report.transaction.previous_checksum = transaction.previous_checksum;
|
|
211
|
+
report.eligibility = { iteration_id: iterationId, current: "invalidated", source_transaction_id: transactionId };
|
|
212
|
+
return report;
|
|
213
|
+
} finally {
|
|
214
|
+
if (lock !== undefined) fs.closeSync(lock);
|
|
215
|
+
fs.rmSync(lockFile, { force: true });
|
|
216
|
+
}
|
|
217
|
+
}
|
package/lib/toml-hooks.mjs
CHANGED
|
@@ -14,7 +14,6 @@ export const HOOK_EVENTS = [
|
|
|
14
14
|
];
|
|
15
15
|
|
|
16
16
|
const HOOK_COMMAND = "node .workflow/tools/hooks/hook-event.mjs";
|
|
17
|
-
const LEGACY_HOOK_COMMAND = "node .ai-delivery/hooks/hook-event.mjs";
|
|
18
17
|
|
|
19
18
|
function hookBlock(event, newline) {
|
|
20
19
|
return [
|
|
@@ -102,9 +101,8 @@ export function mergeHookConfig(existing, { force = false } = {}) {
|
|
|
102
101
|
const newline = existing.includes("\r\n") ? "\r\n" : "\n";
|
|
103
102
|
let text = existing.trimEnd();
|
|
104
103
|
const actions = [];
|
|
105
|
-
if (text.includes(
|
|
106
|
-
|
|
107
|
-
actions.push("migrate AI delivery Hook command into .workflow/tools");
|
|
104
|
+
if (text.includes("node .ai-delivery/hooks/hook-event.mjs")) {
|
|
105
|
+
throw new Error("Unsupported legacy Hook command; remove the .ai-delivery handler before installing the current Hook.");
|
|
108
106
|
}
|
|
109
107
|
if (force) {
|
|
110
108
|
const refreshed = removeDeliveryHandlerBlocks(text);
|
|
@@ -24,7 +24,6 @@ export const WORKFLOW_MANAGER_GOVERNANCE_SCHEMA_VERSION = "workflow-manager.gove
|
|
|
24
24
|
const RELATIONS_FILE = ".workflow/control/relations.yaml";
|
|
25
25
|
const SETTINGS_FILE = ".workflow/config/manager-settings.json";
|
|
26
26
|
const RECEIPTS_ROOT = ".workflow/control/receipts";
|
|
27
|
-
const EVENTS_FILE = ".workflow/control/events/workflow-manager-events.jsonl";
|
|
28
27
|
const SAFE_ID = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,191}$/;
|
|
29
28
|
const SAFE_ENTITY_TYPE = /^[a-z][a-z0-9-]{0,63}$/;
|
|
30
29
|
const RELATION_TYPES = new Set([
|
|
@@ -59,18 +58,6 @@ function contained(root, relative) {
|
|
|
59
58
|
return absolute;
|
|
60
59
|
}
|
|
61
60
|
|
|
62
|
-
function atomicWrite(file, content) {
|
|
63
|
-
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
64
|
-
const temporary = `${file}.${process.pid}.${crypto.randomUUID()}.tmp`;
|
|
65
|
-
fs.writeFileSync(temporary, content, { encoding: "utf8", flag: "wx" });
|
|
66
|
-
try {
|
|
67
|
-
fs.renameSync(temporary, file);
|
|
68
|
-
} catch (error) {
|
|
69
|
-
fs.rmSync(temporary, { force: true });
|
|
70
|
-
throw error;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
61
|
function requireHuman(actor) {
|
|
75
62
|
if (!/^human:[A-Za-z0-9._@/-]+$/.test(String(actor || ""))) {
|
|
76
63
|
throw new Error("Governed confirmation requires actor human:<identity>");
|
|
@@ -92,16 +79,13 @@ function receiptFiles(root) {
|
|
|
92
79
|
|
|
93
80
|
function replay(root, action, input, subject = null) {
|
|
94
81
|
if (!input.idempotency_key) return null;
|
|
95
|
-
const
|
|
96
|
-
const governedRequestChecksum = workflowManagerRequestChecksum(action, input, subject);
|
|
82
|
+
const expectedRequestChecksum = workflowManagerRequestChecksum(action, input, subject);
|
|
97
83
|
for (const file of receiptFiles(root)) {
|
|
98
84
|
try {
|
|
99
85
|
const receipt = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
100
86
|
if (receipt.action !== action || receipt.idempotency_key !== input.idempotency_key) continue;
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
&& (receipt.subject ?? null) === subject;
|
|
104
|
-
if (!legacy && !governed) {
|
|
87
|
+
if (receipt.request_checksum !== expectedRequestChecksum
|
|
88
|
+
|| (receipt.subject ?? null) !== subject) {
|
|
105
89
|
throw new Error("Idempotency key was already used for a different request");
|
|
106
90
|
}
|
|
107
91
|
return receipt;
|
|
@@ -112,34 +96,6 @@ function replay(root, action, input, subject = null) {
|
|
|
112
96
|
return null;
|
|
113
97
|
}
|
|
114
98
|
|
|
115
|
-
function record(root, action, input, detail = {}) {
|
|
116
|
-
const timestamp = new Date().toISOString();
|
|
117
|
-
const receipt = {
|
|
118
|
-
schema_version: 1,
|
|
119
|
-
receipt_id: `WMG-${crypto.randomUUID()}`,
|
|
120
|
-
action,
|
|
121
|
-
actor: input.actor,
|
|
122
|
-
idempotency_key: input.idempotency_key || null,
|
|
123
|
-
request_checksum: checksum({ action, input }),
|
|
124
|
-
applied_at: timestamp,
|
|
125
|
-
...detail,
|
|
126
|
-
};
|
|
127
|
-
receipt.receipt_checksum = checksum(receipt);
|
|
128
|
-
atomicWrite(contained(root, `${RECEIPTS_ROOT}/${receipt.receipt_id}.json`), `${JSON.stringify(receipt, null, 2)}\n`);
|
|
129
|
-
const event = {
|
|
130
|
-
schema_version: 1,
|
|
131
|
-
event_id: `WME-${crypto.randomUUID()}`,
|
|
132
|
-
type: `workflow-manager.${action}`,
|
|
133
|
-
occurred_at: timestamp,
|
|
134
|
-
receipt_id: receipt.receipt_id,
|
|
135
|
-
subject: detail.subject || null,
|
|
136
|
-
};
|
|
137
|
-
const eventFile = contained(root, EVENTS_FILE);
|
|
138
|
-
fs.mkdirSync(path.dirname(eventFile), { recursive: true });
|
|
139
|
-
fs.appendFileSync(eventFile, `${JSON.stringify(event)}\n`, "utf8");
|
|
140
|
-
return { receipt, event };
|
|
141
|
-
}
|
|
142
|
-
|
|
143
99
|
function relationsDocument(root) {
|
|
144
100
|
const file = contained(root, RELATIONS_FILE);
|
|
145
101
|
if (!fs.existsSync(file)) return { file, document: { schema_version: 1, revision: 0, relations: [] }, checksum: null };
|
package/lib/workspace.mjs
CHANGED
|
@@ -4,7 +4,6 @@ import { spawnSync } from "node:child_process";
|
|
|
4
4
|
import { parse as parseYaml, stringify as stringifyYaml } from "./yaml-runtime.mjs";
|
|
5
5
|
|
|
6
6
|
export const WORKSPACE_CONFIG = path.join(".workflow", "config", "workspace.yaml");
|
|
7
|
-
export const LEGACY_WORKSPACE_CONFIG = path.join(".ai-delivery", "workspace.yaml");
|
|
8
7
|
|
|
9
8
|
function toPosix(value) {
|
|
10
9
|
return value.replaceAll("\\", "/");
|
|
@@ -114,7 +113,7 @@ function initializeWorkflowRepository(workspaceRoot, branch, remote, heads, acti
|
|
|
114
113
|
const current = gitBranch(workspaceRoot);
|
|
115
114
|
if (current !== branch) {
|
|
116
115
|
if (gitHasCommit(workspaceRoot)) {
|
|
117
|
-
throw new Error(`Existing workflow repository must already use ${branch}; automatic
|
|
116
|
+
throw new Error(`Existing workflow repository must already use ${branch}; automatic branch changes are not supported.`);
|
|
118
117
|
}
|
|
119
118
|
if (!dryRun) runGit(workspaceRoot, ["symbolic-ref", "HEAD", `refs/heads/${branch}`]);
|
|
120
119
|
}
|
|
@@ -172,7 +171,7 @@ export function validateCodePath(workspaceRoot, codePath = "code") {
|
|
|
172
171
|
if (!normalized || normalized.includes("/") || normalized === "." || normalized === "..") {
|
|
173
172
|
throw new Error("Code path must be a relative direct child directory.");
|
|
174
173
|
}
|
|
175
|
-
if (new Set([".git", ".workflow", ".
|
|
174
|
+
if (new Set([".git", ".workflow", ".agents", ".codex"]).has(normalized)) {
|
|
176
175
|
throw new Error(`Reserved code path: ${normalized}`);
|
|
177
176
|
}
|
|
178
177
|
const absolute = path.resolve(workspaceRoot, normalized);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-delivery-workflow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Project-scoped Codex skills and hooks for artifact-driven AI software delivery",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"skills"
|
|
23
23
|
],
|
|
24
24
|
"scripts": {
|
|
25
|
-
"test": "node --test verification/*.test.mjs",
|
|
25
|
+
"test": "node --test --test-concurrency=4 verification/*.test.mjs",
|
|
26
26
|
"manager:build": "npm --prefix manager run build",
|
|
27
27
|
"skills:validate": "node bin/validate-skills.mjs",
|
|
28
28
|
"audit:generate": "node audit/generate-all.mjs",
|
|
@@ -9,19 +9,21 @@ Produce a deterministic release selection and auditable material package. Do not
|
|
|
9
9
|
|
|
10
10
|
## Select The Version Closure
|
|
11
11
|
|
|
12
|
-
1.
|
|
13
|
-
2.
|
|
14
|
-
3.
|
|
15
|
-
4.
|
|
12
|
+
1. Read the immutable R00 release request first. It must name the production branch and record the exact request-time `main` snapshot commit (`expected_main`); it is the release base for this release ID.
|
|
13
|
+
2. Build a JSON lineage input from registered version-closeout manifests. Include exactly one predecessor, status, candidate ID/commit, code Tag, workflow commit, workflow Tag, manifest path, and checksum per version.
|
|
14
|
+
3. Run `node scripts/plan-release.mjs --lineage <file> --release-id <id> --target <version> --requested-by <actor> --rationale <text> --workspace <workspace-root>`. Its captured `release_base` must equal the R00 snapshot. Do not use `--skip-git` outside isolated contract tests.
|
|
15
|
+
4. Preserve the JSON result as the source for `R01-version-selection`. The target's `version-ready/<version-id>/rN` value is an immutable Tag, never a branch.
|
|
16
|
+
5. Block on missing predecessors, branching, cycles, disconnected lineage, stale/ineligible versions, wrong `repo_id`, missing code or workflow Tags, workflow manifest checksum drift, backward targets, a changed production branch, or any failed adjacent code/workflow ancestry edge. For an incremental release, the release base must be an ancestor of the target Tag; for a same-version redeploy, the target Tag must already be an ancestor of or equal to the release base. Checking only production-to-target reachability is insufficient.
|
|
16
17
|
|
|
17
18
|
## Aggregate Materials
|
|
18
19
|
|
|
19
20
|
1. Copy the assets into `.workflow/releases/<release-id>/R03-material-aggregation/` and `R04-release-candidate/`.
|
|
20
21
|
2. Add every actual requirement, product, architecture, prototype, source, image, configuration, migration, infrastructure, test, security, risk, operations, rollback, and observability item to `release-material-index.csv`. Code entries require `repo_id`, `code_commit`, optional `code_tag`, `source_path`, source version, original workflow path, and SHA-256.
|
|
21
|
-
3. Record every selected version and immutable identity in `version-inclusion.csv`. Intermediate versions provide traceability;
|
|
22
|
-
4.
|
|
23
|
-
5.
|
|
22
|
+
3. Record every selected version and immutable identity in `version-inclusion.csv`. Intermediate versions provide traceability only; do not merge their Tags into the release branch.
|
|
23
|
+
4. At R04 invoke `$ai-delivery-manage-git`'s controlled `scripts/release-git.mjs create-candidate` operation with `--release-id`, `--release-branch`, R00 `--expected-main`, exactly one `--source-tag` and its immutable `--source-commit`, plus `--receipt <path> --apply`. For an incremental release it creates `release/<release-id>-<slug>` at that snapshot and merges that one Tag with `--no-ff`; for a same-version redeploy whose target is already reachable from the snapshot, it records the snapshot itself as the candidate with no new merge. It returns the only authoritative candidate receipt. Omitting `--apply` is a zero-write plan. Do not substitute a movable line/version branch head, cherry-picks, or repeated Tag merges.
|
|
24
|
+
5. Apply a release-only correction from the active candidate through `release-fix/<release-id>/<defect-id>`. A fix produces a new exact candidate identity and repeats all affected verification; it never rewrites historical version-ready Tags or manifests.
|
|
25
|
+
6. Freeze `release-candidate-manifest.yaml` with the request-time `main` base, exact source Tag/commit, integration commit, branch commit, image digest, material index checksum, environment/configuration snapshot requirements, rollback image, and any release-fix identities.
|
|
24
26
|
|
|
25
|
-
Same-version redeploy reuses immutable application identities but regenerates the release-scoped indexes, snapshots, verification, approval, deployment, and archive evidence.
|
|
27
|
+
Same-version redeploy reuses immutable application identities but regenerates the release-scoped indexes, snapshots, verification, approval, deployment, and archive evidence. A release-fix still advances the product-line candidate inventory through a distinct immutable successor; it never rewrites the predecessor inventory.
|
|
26
28
|
|
|
27
29
|
Read [release-assembly-contract.md](references/release-assembly-contract.md) before aggregation.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
interface:
|
|
2
|
-
display_name: "Assemble Release"
|
|
3
|
-
short_description: "Validate version lineage and aggregate release materials"
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "Assemble Release"
|
|
3
|
+
short_description: "Validate version lineage and aggregate release materials"
|
|
4
4
|
default_prompt: "Use $ai-delivery-assemble-release to validate both repositories, calculate the version closure, and assemble its candidate."
|
|
@@ -1,14 +1,25 @@
|
|
|
1
|
-
schema_version:
|
|
1
|
+
schema_version: 3
|
|
2
2
|
release_id: "REL-0001"
|
|
3
3
|
release_candidate_id: "RC-0001"
|
|
4
4
|
mode: "incremental"
|
|
5
5
|
target_version: "VER-0005"
|
|
6
|
-
|
|
6
|
+
release_branch: "release/REL-0001-short-slug"
|
|
7
|
+
release_base:
|
|
8
|
+
production_branch: "main"
|
|
9
|
+
commit: "<git-sha>"
|
|
10
|
+
captured_at: "<RFC3339>"
|
|
11
|
+
release_merge:
|
|
12
|
+
strategy: "no-ff-single-version-ready-tag"
|
|
13
|
+
merge_created: true # False when a same-version target is already in the release base.
|
|
14
|
+
source_tag: "version-ready/VER-0005/r1"
|
|
15
|
+
source_commit: "<git-sha>"
|
|
16
|
+
commit: "<git-sha>" # Null when merge_created is false.
|
|
17
|
+
candidate_receipt_ref: ".workflow/releases/REL-0001/R04-release-candidate/candidate-receipt.json"
|
|
7
18
|
repository:
|
|
8
19
|
repo_id: "app"
|
|
9
20
|
source_path: "code"
|
|
10
|
-
code_commit: "<git-sha>"
|
|
11
|
-
code_tag: "
|
|
21
|
+
code_commit: "<git-sha>" # Exact candidate commit: incremental merge result or same-version release base, never a mutable branch head.
|
|
22
|
+
code_tag: "release/REL-0001/r1"
|
|
12
23
|
workflow_identity:
|
|
13
24
|
workflow_commit: "<workflow-git-sha>"
|
|
14
25
|
workflow_tag: "workflow-ready/VER-0005/r1"
|
|
@@ -19,4 +30,5 @@ material_index_sha256: "<sha256>"
|
|
|
19
30
|
configuration_baseline_sha256: "<sha256>"
|
|
20
31
|
migration_set_sha256: "<sha256>"
|
|
21
32
|
rollback_image_digest: "sha256:<previous-digest>"
|
|
33
|
+
release_fixes: []
|
|
22
34
|
status: "immutable"
|
|
@@ -1,9 +1,99 @@
|
|
|
1
|
-
schema_version:
|
|
1
|
+
schema_version: 2
|
|
2
2
|
release_id: "REL-0001"
|
|
3
|
-
|
|
4
|
-
source_commit: "<git-sha>"
|
|
5
|
-
release_branch: "release/REL-0001-short-slug"
|
|
3
|
+
product_id: "PRODUCT-001"
|
|
6
4
|
production_branch: "main"
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
release_branch: "release/REL-0001-short-slug"
|
|
6
|
+
release_base:
|
|
7
|
+
expected_main: "<git-sha>"
|
|
8
|
+
captured_at: "<RFC3339>"
|
|
9
|
+
request_artifact: ".workflow/releases/REL-0001/R00-release-request/release-request.yaml"
|
|
10
|
+
target_version:
|
|
11
|
+
version_id: "VER-0005"
|
|
12
|
+
source_tag: "version-ready/VER-0005/r1"
|
|
13
|
+
source_commit: "<git-sha>"
|
|
14
|
+
source_relation_to_release_base: "incremental: target-descends-from-release-base; same-version-redeploy: target-already-in-release-base"
|
|
15
|
+
candidate_operation:
|
|
16
|
+
command: "release-git.mjs create-candidate"
|
|
17
|
+
required_arguments:
|
|
18
|
+
- "--release-id REL-0001"
|
|
19
|
+
- "--release-branch release/REL-0001-short-slug"
|
|
20
|
+
- "--expected-main <git-sha>"
|
|
21
|
+
- "--source-tag version-ready/VER-0005/r1"
|
|
22
|
+
- "--source-commit <git-sha>"
|
|
23
|
+
- "--receipt <path>"
|
|
24
|
+
- "--apply"
|
|
25
|
+
merge_strategy: "no-ff-single-version-ready-tag"
|
|
26
|
+
merge_created: true # False when a same-version target is already in the release base.
|
|
27
|
+
merge_intermediate_tags: false
|
|
28
|
+
release_candidate_commit: null
|
|
29
|
+
receipt_fields:
|
|
30
|
+
- "operation: create-release-candidate"
|
|
31
|
+
- "release_base_commit"
|
|
32
|
+
- "source_ref"
|
|
33
|
+
- "source_commit"
|
|
34
|
+
- "candidate_commit"
|
|
35
|
+
- "status: planned | applied | idempotent"
|
|
36
|
+
receipt_ref: null
|
|
37
|
+
status: "pending-controlled-git-operation"
|
|
38
|
+
promotion_operation:
|
|
39
|
+
command: "release-git.mjs promote"
|
|
40
|
+
required_arguments:
|
|
41
|
+
- "--release-id REL-0001"
|
|
42
|
+
- "--release-branch release/REL-0001-short-slug"
|
|
43
|
+
- "--expected-main <git-sha>"
|
|
44
|
+
- "--verified-release-commit <git-sha>"
|
|
45
|
+
- "--production-verification .workflow/releases/REL-0001/R09-production-verification/production-verification.json"
|
|
46
|
+
- "--receipt <path>"
|
|
47
|
+
- "--apply"
|
|
48
|
+
verified_release_commit: null
|
|
49
|
+
receipt_fields:
|
|
50
|
+
- "operation: promote-release-candidate"
|
|
51
|
+
- "production_verification.path"
|
|
52
|
+
- "production_verification.sha256"
|
|
53
|
+
- "old_main_head"
|
|
54
|
+
- "new_main_head"
|
|
55
|
+
- "status: planned | applied | idempotent"
|
|
56
|
+
receipt_ref: null
|
|
57
|
+
status: "pending-production-verification"
|
|
58
|
+
release_fix_synchronization:
|
|
59
|
+
line_branch: "line/PRODUCT-001"
|
|
60
|
+
command: "release-git.mjs sync-release-fix"
|
|
61
|
+
required_arguments:
|
|
62
|
+
- "--release-id REL-0001"
|
|
63
|
+
- "--source-ref release-fix/REL-0001/DEFECT-001"
|
|
64
|
+
- "--source-commit <git-sha>"
|
|
65
|
+
- "--verified-release-commit <git-sha>"
|
|
66
|
+
- "--expected-line <git-sha>"
|
|
67
|
+
- "--production-verification .workflow/releases/REL-0001/R09-production-verification/production-verification.json"
|
|
68
|
+
- "--candidate-inventory .workflow/releases/REL-0001/R10-release-archive/candidate-inventory.json"
|
|
69
|
+
- "--successor-candidate-inventory .workflow/releases/REL-0001/R10-release-archive/candidate-inventory-successor.json"
|
|
70
|
+
- "--receipt <path>"
|
|
71
|
+
- "--apply"
|
|
72
|
+
required_before_archive: true
|
|
73
|
+
expected_line: "<git-sha>"
|
|
74
|
+
candidate_inventory_contract:
|
|
75
|
+
schema_version: 2
|
|
76
|
+
scope: "product-line"
|
|
77
|
+
product_id: "PRODUCT-001"
|
|
78
|
+
line_branch: "line/PRODUCT-001"
|
|
79
|
+
root_release_id: forbidden
|
|
80
|
+
candidate_fields:
|
|
81
|
+
- "candidate_id"
|
|
82
|
+
- "release_id"
|
|
83
|
+
- "candidate_commit"
|
|
84
|
+
- "status"
|
|
85
|
+
successor_is_immutable: true
|
|
86
|
+
receipt_fields:
|
|
87
|
+
- "operation: synchronize-release-fix-to-line"
|
|
88
|
+
- "old_line_head"
|
|
89
|
+
- "new_line_head"
|
|
90
|
+
- "stale_candidate_ids"
|
|
91
|
+
- "candidate_status_updates"
|
|
92
|
+
- "production_verification.sha256"
|
|
93
|
+
- "candidate_inventory.sha256"
|
|
94
|
+
- "successor_candidate_inventory.path"
|
|
95
|
+
- "successor_candidate_inventory.sha256"
|
|
96
|
+
- "successor_candidate_inventory_write.status"
|
|
97
|
+
- "status: planned | applied | idempotent"
|
|
98
|
+
receipt_refs: []
|
|
9
99
|
rollback_branch_allowed: false
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
sequence,version_id,predecessor_version_id,candidate_id,candidate_commit,version_ready_tag,manifest_path,manifest_sha256,inclusion_type
|
|
2
|
-
1,VER-0001,,CAND-0001,<git-sha>,version-ready/VER-0001/r1,.workflow/iterations/VER-0001/06-version-closeout/version-manifest.yaml,<sha256>,dependency-closure
|
|
1
|
+
sequence,version_id,predecessor_version_id,candidate_id,candidate_commit,version_ready_tag,manifest_path,manifest_sha256,inclusion_type,release_code_role
|
|
2
|
+
1,VER-0001,,CAND-0001,<git-sha>,version-ready/VER-0001/r1,.workflow/iterations/VER-0001/06-version-closeout/version-manifest.yaml,<sha256>,dependency-closure,incremental-target-tag-merged-once-or-same-version-already-reachable
|
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
# Release Assembly Contract
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Candidate Identity
|
|
4
|
+
|
|
5
|
+
At R00, freeze the exact request-time production branch head as `expected_main`. A release candidate is not a checkout of the target Tag. For an incremental release, the controlled Git operation creates `release/<release-id>-<slug>` at that exact commit, confirms that `main` still equals it and that it is an ancestor of the selected target, then merges exactly one target `version-ready/<version-id>/rN` Tag with `--no-ff`. The resulting merge commit is the release-candidate identity. For a same-version redeploy, the selected target Tag must already be an ancestor of or equal to `expected_main`; no merge is created and the exact snapshot commit is the release-candidate identity.
|
|
6
|
+
|
|
7
|
+
The target Tag is immutable and resolves to the target version's `candidate_commit`. Never merge every intermediate Tag, use a movable branch head, or replace the single incremental target merge with cherry-picks. Intermediate versions appear only in the continuous dependency closure and material traceability. If `main` moves after R00 or before candidate acceptance, preserve the abandoned evidence as `stale` and start a new release request/snapshot; do not retarget the existing release branch.
|
|
8
|
+
|
|
9
|
+
`release-git.mjs create-candidate` receives `--release-id`, `--release-branch`, `--expected-main`, `--source-tag`, the resolved `--source-commit`, `--receipt`, and explicit `--apply`. Its receipt records `operation: create-release-candidate`, `release_id`, production branch, release branch, `release_base_commit`, `source_ref`, `source_commit`, `candidate_commit`, whether a merge was created, merge strategy, and `planned`, `applied`, or `idempotent` status. The candidate commit, not the branch's later head, is what R05 through R09 verify, approve, deploy, Tag, and ultimately promote.
|
|
10
|
+
|
|
11
|
+
## Materials And Closure
|
|
4
12
|
|
|
5
13
|
The material index is exhaustive for actual changes and contains stable item ID, category, source version, source artifact ID/path/checksum, target environment, application order, verification, and rollback/recovery action. Do not record secret values.
|
|
6
14
|
|
|
7
|
-
Require every adjacent version in the full dependency closure through the target, including already produced history, to descend from its predecessor in both the code repository (`candidate_commit`) and workflow repository (`workflow_commit`). Production-to-target reachability alone cannot prove that an intermediate version is included. Repeat the full closure check for same-version redeploy.
|
|
15
|
+
Require every adjacent version in the full dependency closure through the target, including already produced history, to descend from its predecessor in both the code repository (`candidate_commit`) and workflow repository (`workflow_commit`). Production-to-target reachability alone cannot prove that an intermediate version is included. Repeat the full closure check for same-version redeploy. When current production equals target, emit `same-version-redeploy`, an empty newly included range, and a fresh release identity.
|
|
16
|
+
|
|
17
|
+
## Release-Fix Reconciliation
|
|
18
|
+
|
|
19
|
+
Create `release-fix/<release-id>/<defect-id>` only from the active release candidate. After the corrected candidate has passed affected verification and production verification has decided `released`, freeze the R09 `production-verification.json` decision and a schema-2 R10 product-line `candidate-inventory.json` before synchronizing its fix commit into `line/<product-id>` through the protected `sync-release-fix` operation. The inventory has `scope: product-line`, `product_id`, `line_branch`, active candidate ID/commit, and all product-line candidate records. Each record retains its own `release_id`, ID, commit, and status; the root has no release ID. The operation checks that the active and verified records belong to the release being synchronized, derives stale updates instead of accepting a stale-candidate argument, and writes a separate immutable successor inventory rather than updating the source snapshot. Record its JSON receipt with the release ID, source ref/commit, verified release commit, old/new line heads, merge strategy, predecessor/successor inventory evidence bindings, derived stale candidate IDs/status updates, and status.
|
|
20
|
+
|
|
21
|
+
Invoke it with `--candidate-inventory <predecessor>` and, for `--apply`, a distinct unused `--successor-candidate-inventory <successor>`. If the fix commit is already reachable from the line, `release-git.mjs sync-release-fix` returns `status: idempotent` with unchanged old/new line heads rather than changing history, and only accepts the exact already-written successor on replay. Historical version-ready Tags and manifests remain immutable. The receipt marks every selectable candidate in the product line that does not contain a production-successful fix `stale`; it cannot be selected until recreated from current lineage. Subsequent synchronization begins from that successor inventory.
|