engineering-process 2.4.0__tar.gz → 2.6.0__tar.gz
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.
- {engineering_process-2.4.0/engineering_process.egg-info → engineering_process-2.6.0}/PKG-INFO +94 -4
- {engineering_process-2.4.0 → engineering_process-2.6.0}/README.md +93 -3
- engineering_process-2.6.0/RELEASE_NOTES.md +49 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/__init__.py +1 -1
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/cli.py +198 -7
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/commands.py +93 -16
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/contracts.py +2 -0
- engineering_process-2.6.0/engineering_process/evidence.py +180 -0
- engineering_process-2.6.0/engineering_process/impact.py +231 -0
- engineering_process-2.6.0/engineering_process/lifecycle.py +1556 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/pr_description.py +229 -1
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/project.py +60 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/release_notes.py +52 -5
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/repository.py +69 -8
- {engineering_process-2.4.0 → engineering_process-2.6.0/engineering_process.egg-info}/PKG-INFO +94 -4
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process.egg-info/SOURCES.txt +5 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/process_assets/skills/change-plan/SKILL.md +23 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/process_assets/skills/change-review/SKILL.md +17 -3
- engineering_process-2.6.0/process_assets/skills/change-verify/SKILL.md +131 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/process_assets/skills/process-improve/SKILL.md +24 -9
- {engineering_process-2.4.0 → engineering_process-2.6.0}/pyproject.toml +3 -1
- {engineering_process-2.4.0 → engineering_process-2.6.0}/schemas/project.schema.json +90 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/schemas/receipt.schema.json +7 -5
- engineering_process-2.6.0/schemas/release-change.schema.json +79 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/schemas/release-notes-data.schema.json +44 -1
- engineering_process-2.6.0/schemas/release.schema.json +105 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/schemas/run.schema.json +4 -0
- engineering_process-2.6.0/schemas/verification-impact-selection.schema.json +143 -0
- engineering_process-2.6.0/schemas/verification-selection.schema.json +91 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_architecture.py +2 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_artifact_standards.py +384 -2
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_automation.py +6 -1
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_cli.py +117 -1
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_commands.py +114 -3
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_contracts.py +47 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_distribution.py +16 -0
- engineering_process-2.6.0/tests/test_impact.py +374 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_lifecycle.py +586 -11
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_release.py +170 -18
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_repository.py +63 -2
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_review_contexts.py +125 -22
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_skills.py +12 -1
- engineering_process-2.4.0/RELEASE_NOTES.md +0 -22
- engineering_process-2.4.0/engineering_process/lifecycle.py +0 -730
- engineering_process-2.4.0/process_assets/skills/change-verify/SKILL.md +0 -54
- engineering_process-2.4.0/schemas/release-change.schema.json +0 -20
- engineering_process-2.4.0/schemas/release.schema.json +0 -40
- {engineering_process-2.4.0 → engineering_process-2.6.0}/LICENSE +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/MANIFEST.in +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/__main__.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/_supervisor_contract.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/_supervisor_posix.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/_supervisor_windows.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/_windows_job.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/adoption.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/artifact_standards.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/automation_name.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/distribution.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/helper_launch.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/issue.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/production_engineering.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/publication_compat.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/release.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/requirements-dev.txt +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/requirements-runtime.txt +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/review_contexts.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/skills.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/source_publication.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process/supervision.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process.egg-info/dependency_links.txt +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process.egg-info/entry_points.txt +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process.egg-info/requires.txt +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/engineering_process.egg-info/top_level.txt +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/process-graph.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/process_assets/skills/change-complete/SKILL.md +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/process_assets/skills/change-implement/SKILL.md +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/process_assets/skills/change-start/SKILL.md +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/process_assets/skills/deliver-change/SKILL.md +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/process_assets/skills/production-engineering/SKILL.md +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/process_assets/skills/production-engineering/invariants.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/process_assets/standards/automation-name.v1.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/process_assets/standards/issue.v1.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/process_assets/standards/pull-request.v1.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/process_assets/standards/release-notes.v1.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/schemas/artifact-selection.schema.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/schemas/artifact-standard.schema.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/schemas/automation-name-data.schema.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/schemas/change.schema.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/schemas/issue-data.schema.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/schemas/plan.schema.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/schemas/pr-description-data.schema.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/schemas/process-graph.schema.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/schemas/process-lock.schema.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/schemas/production-engineering.schema.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/schemas/project-legacy.schema.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/schemas/renovate-preset.schema.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/schemas/review.schema.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/setup.cfg +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/templates/AGENTS.process.md +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/templates/PULL_REQUEST_TEMPLATE.md +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/templates/adopt-process-windows-job.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/templates/adopt-process.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/templates/renovate.json +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_adoption.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_production_engineering.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_publication_compat.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_publication_workflow.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_pypi_cache.py +0 -0
- {engineering_process-2.4.0 → engineering_process-2.6.0}/tests/test_supervisor_posix.py +0 -0
{engineering_process-2.4.0/engineering_process.egg-info → engineering_process-2.6.0}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: engineering-process
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.6.0
|
|
4
4
|
Summary: A small agent-neutral engineering lifecycle with managed adoption
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/phuongnse/engineering-process
|
|
@@ -86,6 +86,32 @@ but cannot establish native conversation freshness or inspect removed history,
|
|
|
86
86
|
other clones or other repositories. Keep native creation, non-inherited dispatch
|
|
87
87
|
and effective settings evidence in the existing handoff.
|
|
88
88
|
|
|
89
|
+
Verification keeps two caller intents explicit. `change verify --profile PROFILE`
|
|
90
|
+
always refreshes the named profile. `change explain` is read-only; it shows the
|
|
91
|
+
accepted required profiles, valid prior evidence, remaining work, inapplicable
|
|
92
|
+
optional profiles, and blocked or unknown decisions. `change verify --remaining`
|
|
93
|
+
executes only remaining work and reuses a complete profile report only when the
|
|
94
|
+
candidate, contract/plan, project policy, process authority, runtime, and bounded
|
|
95
|
+
child environment match. Legacy evidence without that identity reruns. This is
|
|
96
|
+
whole-profile reuse: equal check IDs and ordered side effects are never merged, and
|
|
97
|
+
the lifecycle receipt still records only actual executions.
|
|
98
|
+
|
|
99
|
+
Reuse is stage-aware rather than a blanket cache: the contract and plan travel by
|
|
100
|
+
digest; valid whole-profile verification can satisfy a continuation request; review
|
|
101
|
+
and finish consume the same reports after rechecking the snapshot; and a new
|
|
102
|
+
implementation cycle invalidates verification. Operation-local calculation reuse is
|
|
103
|
+
allowed only before a mutation/concurrency boundary. Impact feedback and generated
|
|
104
|
+
documents remain derived artifacts and never replace final required profiles or
|
|
105
|
+
independent review.
|
|
106
|
+
|
|
107
|
+
Consumers that can prove complete changed-path coverage may opt selected required
|
|
108
|
+
profiles into final impact assurance with `impactProfiles.schemaVersion: 2` and
|
|
109
|
+
`finalProfiles`. Each opted profile must declare an explicit global unit whose paths
|
|
110
|
+
include the universal `**` pattern for cross-cutting reach. The lifecycle then
|
|
111
|
+
records the selected units as final
|
|
112
|
+
verification evidence; missing or unresolved coverage blocks rather than silently
|
|
113
|
+
falling back. Existing version 1 policies remain feedback-only.
|
|
114
|
+
|
|
89
115
|
`processctl change review replace-reused` repairs only an initial pending assignment
|
|
90
116
|
proven to reuse another change's agent context, before a submitted review or normal
|
|
91
117
|
report file exists. It validates a fresh replacement and current verification,
|
|
@@ -156,6 +182,33 @@ Python 3.11 or newer and Git are required. A consumer owns .process/project.json
|
|
|
156
182
|
"timeoutSeconds": 600
|
|
157
183
|
}
|
|
158
184
|
]
|
|
185
|
+
},
|
|
186
|
+
"impactProfiles": {
|
|
187
|
+
"schemaVersion": 1,
|
|
188
|
+
"profiles": {
|
|
189
|
+
"development": [
|
|
190
|
+
{
|
|
191
|
+
"id": "unit-tests",
|
|
192
|
+
"run": ["python", "-m", "unittest", "tests.test_orders"],
|
|
193
|
+
"timeoutSeconds": 600,
|
|
194
|
+
"paths": ["src/orders/**", "tests/test_orders.py"]
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"id": "cross-cutting",
|
|
198
|
+
"run": ["python", "-m", "unittest"],
|
|
199
|
+
"timeoutSeconds": 900,
|
|
200
|
+
"paths": ["**/process-policy.json"]
|
|
201
|
+
}
|
|
202
|
+
],
|
|
203
|
+
"review": [
|
|
204
|
+
{
|
|
205
|
+
"id": "package",
|
|
206
|
+
"run": ["python", "-m", "build"],
|
|
207
|
+
"timeoutSeconds": 600,
|
|
208
|
+
"paths": ["src/**", "pyproject.toml"]
|
|
209
|
+
}
|
|
210
|
+
]
|
|
211
|
+
}
|
|
159
212
|
}
|
|
160
213
|
}
|
|
161
214
|
|
|
@@ -502,6 +555,41 @@ Register implementation and run every required profile:
|
|
|
502
555
|
processctl change verify --change-id change-123 --profile development
|
|
503
556
|
processctl change verify --change-id change-123 --profile review
|
|
504
557
|
|
|
558
|
+
When continuing an incomplete verification, inspect and execute the necessary set:
|
|
559
|
+
|
|
560
|
+
processctl change explain --change-id change-123
|
|
561
|
+
processctl change verify --change-id change-123 --remaining
|
|
562
|
+
|
|
563
|
+
The explicit `--profile` form remains a refresh and is never silently converted to
|
|
564
|
+
reuse.
|
|
565
|
+
|
|
566
|
+
For fast feedback, consumers may declare a versioned `impactProfiles` policy in
|
|
567
|
+
`.process/project.json` and run only units related to the candidate paths:
|
|
568
|
+
|
|
569
|
+
processctl change explain --change-id change-123 --impact
|
|
570
|
+
processctl change verify --change-id change-123 --affected --affected-profile development
|
|
571
|
+
|
|
572
|
+
Each impact unit owns an exact command and path-pattern coverage. Matching is
|
|
573
|
+
explicit and deterministic; overlapping units all run. A unit with
|
|
574
|
+
`scope: "global"` may subsume narrower units only when its declared paths include
|
|
575
|
+
the universal `**` pattern; a narrower pattern never covers unrelated paths. Every
|
|
576
|
+
changed path must resolve for
|
|
577
|
+
each requested profile. Missing policy, unsupported policy, or an unmapped path is
|
|
578
|
+
`unresolved`/`unavailable`: the process launches nothing and returns the action
|
|
579
|
+
`inspect-diff-and-update-impact-policy`. The agent must inspect the diff and
|
|
580
|
+
dependency reach, update the consumer-owned mapping or obtain an owner decision,
|
|
581
|
+
then repeat the explanation. It must not use a full profile as a fallback.
|
|
582
|
+
|
|
583
|
+
Affected execution under a version 1 policy is feedback evidence only and never
|
|
584
|
+
advances the lifecycle or satisfies a required profile. A consumer that can prove
|
|
585
|
+
complete coverage may use schema version 2 with `finalProfiles`; `--remaining` then
|
|
586
|
+
records the selected units as `impact-assurance` evidence. Each opted profile needs
|
|
587
|
+
an explicit global unit with the universal `**` pattern for cross-cutting reach, and
|
|
588
|
+
unresolved final coverage
|
|
589
|
+
blocks rather than falling back silently. Explicit `--profile` remains the full
|
|
590
|
+
refresh. Consumers that do not adopt the opt-in retain the existing final boundary;
|
|
591
|
+
the affected command does not guess a policy for them.
|
|
592
|
+
|
|
505
593
|
Assign an independent reviewer and submit its report:
|
|
506
594
|
|
|
507
595
|
processctl change review start \
|
|
@@ -588,9 +676,11 @@ At any point:
|
|
|
588
676
|
## Release to consumer PR
|
|
589
677
|
|
|
590
678
|
Each release includes [reviewed release contents](RELEASE_NOTES.md) generated from
|
|
591
|
-
the canonical manifest: shipped
|
|
592
|
-
|
|
593
|
-
|
|
679
|
+
the canonical manifest: one record per shipped feature/fix, its source issue, the
|
|
680
|
+
problem and affected paths, the application action, compatibility impact, important
|
|
681
|
+
notes, and upgrade guidance. The release PR reviews this file; the GitHub Release
|
|
682
|
+
publishes the same contents. See [the release procedure](RELEASING.md) for authoring
|
|
683
|
+
and checks.
|
|
594
684
|
|
|
595
685
|
This producer's release identity inputs and text assets declared by
|
|
596
686
|
`tool.setuptools.data-files` use UTF-8 without BOM and LF, matching `.gitattributes`.
|
|
@@ -62,6 +62,32 @@ but cannot establish native conversation freshness or inspect removed history,
|
|
|
62
62
|
other clones or other repositories. Keep native creation, non-inherited dispatch
|
|
63
63
|
and effective settings evidence in the existing handoff.
|
|
64
64
|
|
|
65
|
+
Verification keeps two caller intents explicit. `change verify --profile PROFILE`
|
|
66
|
+
always refreshes the named profile. `change explain` is read-only; it shows the
|
|
67
|
+
accepted required profiles, valid prior evidence, remaining work, inapplicable
|
|
68
|
+
optional profiles, and blocked or unknown decisions. `change verify --remaining`
|
|
69
|
+
executes only remaining work and reuses a complete profile report only when the
|
|
70
|
+
candidate, contract/plan, project policy, process authority, runtime, and bounded
|
|
71
|
+
child environment match. Legacy evidence without that identity reruns. This is
|
|
72
|
+
whole-profile reuse: equal check IDs and ordered side effects are never merged, and
|
|
73
|
+
the lifecycle receipt still records only actual executions.
|
|
74
|
+
|
|
75
|
+
Reuse is stage-aware rather than a blanket cache: the contract and plan travel by
|
|
76
|
+
digest; valid whole-profile verification can satisfy a continuation request; review
|
|
77
|
+
and finish consume the same reports after rechecking the snapshot; and a new
|
|
78
|
+
implementation cycle invalidates verification. Operation-local calculation reuse is
|
|
79
|
+
allowed only before a mutation/concurrency boundary. Impact feedback and generated
|
|
80
|
+
documents remain derived artifacts and never replace final required profiles or
|
|
81
|
+
independent review.
|
|
82
|
+
|
|
83
|
+
Consumers that can prove complete changed-path coverage may opt selected required
|
|
84
|
+
profiles into final impact assurance with `impactProfiles.schemaVersion: 2` and
|
|
85
|
+
`finalProfiles`. Each opted profile must declare an explicit global unit whose paths
|
|
86
|
+
include the universal `**` pattern for cross-cutting reach. The lifecycle then
|
|
87
|
+
records the selected units as final
|
|
88
|
+
verification evidence; missing or unresolved coverage blocks rather than silently
|
|
89
|
+
falling back. Existing version 1 policies remain feedback-only.
|
|
90
|
+
|
|
65
91
|
`processctl change review replace-reused` repairs only an initial pending assignment
|
|
66
92
|
proven to reuse another change's agent context, before a submitted review or normal
|
|
67
93
|
report file exists. It validates a fresh replacement and current verification,
|
|
@@ -132,6 +158,33 @@ Python 3.11 or newer and Git are required. A consumer owns .process/project.json
|
|
|
132
158
|
"timeoutSeconds": 600
|
|
133
159
|
}
|
|
134
160
|
]
|
|
161
|
+
},
|
|
162
|
+
"impactProfiles": {
|
|
163
|
+
"schemaVersion": 1,
|
|
164
|
+
"profiles": {
|
|
165
|
+
"development": [
|
|
166
|
+
{
|
|
167
|
+
"id": "unit-tests",
|
|
168
|
+
"run": ["python", "-m", "unittest", "tests.test_orders"],
|
|
169
|
+
"timeoutSeconds": 600,
|
|
170
|
+
"paths": ["src/orders/**", "tests/test_orders.py"]
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"id": "cross-cutting",
|
|
174
|
+
"run": ["python", "-m", "unittest"],
|
|
175
|
+
"timeoutSeconds": 900,
|
|
176
|
+
"paths": ["**/process-policy.json"]
|
|
177
|
+
}
|
|
178
|
+
],
|
|
179
|
+
"review": [
|
|
180
|
+
{
|
|
181
|
+
"id": "package",
|
|
182
|
+
"run": ["python", "-m", "build"],
|
|
183
|
+
"timeoutSeconds": 600,
|
|
184
|
+
"paths": ["src/**", "pyproject.toml"]
|
|
185
|
+
}
|
|
186
|
+
]
|
|
187
|
+
}
|
|
135
188
|
}
|
|
136
189
|
}
|
|
137
190
|
|
|
@@ -478,6 +531,41 @@ Register implementation and run every required profile:
|
|
|
478
531
|
processctl change verify --change-id change-123 --profile development
|
|
479
532
|
processctl change verify --change-id change-123 --profile review
|
|
480
533
|
|
|
534
|
+
When continuing an incomplete verification, inspect and execute the necessary set:
|
|
535
|
+
|
|
536
|
+
processctl change explain --change-id change-123
|
|
537
|
+
processctl change verify --change-id change-123 --remaining
|
|
538
|
+
|
|
539
|
+
The explicit `--profile` form remains a refresh and is never silently converted to
|
|
540
|
+
reuse.
|
|
541
|
+
|
|
542
|
+
For fast feedback, consumers may declare a versioned `impactProfiles` policy in
|
|
543
|
+
`.process/project.json` and run only units related to the candidate paths:
|
|
544
|
+
|
|
545
|
+
processctl change explain --change-id change-123 --impact
|
|
546
|
+
processctl change verify --change-id change-123 --affected --affected-profile development
|
|
547
|
+
|
|
548
|
+
Each impact unit owns an exact command and path-pattern coverage. Matching is
|
|
549
|
+
explicit and deterministic; overlapping units all run. A unit with
|
|
550
|
+
`scope: "global"` may subsume narrower units only when its declared paths include
|
|
551
|
+
the universal `**` pattern; a narrower pattern never covers unrelated paths. Every
|
|
552
|
+
changed path must resolve for
|
|
553
|
+
each requested profile. Missing policy, unsupported policy, or an unmapped path is
|
|
554
|
+
`unresolved`/`unavailable`: the process launches nothing and returns the action
|
|
555
|
+
`inspect-diff-and-update-impact-policy`. The agent must inspect the diff and
|
|
556
|
+
dependency reach, update the consumer-owned mapping or obtain an owner decision,
|
|
557
|
+
then repeat the explanation. It must not use a full profile as a fallback.
|
|
558
|
+
|
|
559
|
+
Affected execution under a version 1 policy is feedback evidence only and never
|
|
560
|
+
advances the lifecycle or satisfies a required profile. A consumer that can prove
|
|
561
|
+
complete coverage may use schema version 2 with `finalProfiles`; `--remaining` then
|
|
562
|
+
records the selected units as `impact-assurance` evidence. Each opted profile needs
|
|
563
|
+
an explicit global unit with the universal `**` pattern for cross-cutting reach, and
|
|
564
|
+
unresolved final coverage
|
|
565
|
+
blocks rather than falling back silently. Explicit `--profile` remains the full
|
|
566
|
+
refresh. Consumers that do not adopt the opt-in retain the existing final boundary;
|
|
567
|
+
the affected command does not guess a policy for them.
|
|
568
|
+
|
|
481
569
|
Assign an independent reviewer and submit its report:
|
|
482
570
|
|
|
483
571
|
processctl change review start \
|
|
@@ -564,9 +652,11 @@ At any point:
|
|
|
564
652
|
## Release to consumer PR
|
|
565
653
|
|
|
566
654
|
Each release includes [reviewed release contents](RELEASE_NOTES.md) generated from
|
|
567
|
-
the canonical manifest: shipped
|
|
568
|
-
|
|
569
|
-
|
|
655
|
+
the canonical manifest: one record per shipped feature/fix, its source issue, the
|
|
656
|
+
problem and affected paths, the application action, compatibility impact, important
|
|
657
|
+
notes, and upgrade guidance. The release PR reviews this file; the GitHub Release
|
|
658
|
+
publishes the same contents. See [the release procedure](RELEASING.md) for authoring
|
|
659
|
+
and checks.
|
|
570
660
|
|
|
571
661
|
This producer's release identity inputs and text assets declared by
|
|
572
662
|
`tool.setuptools.data-files` use UTF-8 without BOM and LF, matching `.gitattributes`.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Engineering Process v2.6.0
|
|
2
|
+
|
|
3
|
+
Changes since v2.5.0.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Select and assure verification units from explicit change impact.** ([#205](https://github.com/phuongnse/engineering-process/issues/205))
|
|
8
|
+
- **Problem:** A consumer could only choose a whole profile or reuse a whole-profile result, so a small change lacked a standard way to run related verification units. When impact was unclear, an automatic full-suite fallback could hide that dependency reach had not been resolved, while explicit coverage could not yet satisfy a final required profile.
|
|
9
|
+
- **What changed:** Add versioned consumer-owned impactProfiles, deterministic changed-path resolution, change explain --impact, and change verify --affected. Every path must resolve to matching units or the command stops with an explicit re-analysis action; an explicit global pattern is the only broad selection rule. Add a schema-version 2 finalProfiles opt-in so complete explicit coverage can run selected units as final impact-assurance evidence. Policy or candidate changes, missing coverage and unresolved paths fail closed; schema-version 1 policies remain feedback-only.
|
|
10
|
+
- **Where:** `schemas/project.schema.json`, `schemas/verification-impact-selection.schema.json`, `schemas/verification-selection.schema.json`, `schemas/run.schema.json`, `schemas/receipt.schema.json`, `engineering_process/impact.py`, `engineering_process/repository.py`, `engineering_process/lifecycle.py`, `engineering_process/cli.py`, `engineering_process/project.py`, `process_assets/skills/change-verify/SKILL.md`, `process_assets/skills/change-plan/SKILL.md`, `SELF_HOSTING.md`, `README.md`, `tests/test_contracts.py`, `tests/test_impact.py`, `tests/test_lifecycle.py`, `tests/test_skills.py`
|
|
11
|
+
- **Apply:** Adopt the package release, add impactProfiles to the consumer project policy, map every changed path to one or more independently executable commands, and run change explain --impact before change verify --affected. Opt selected required profiles into schema version 2 finalProfiles only after reviewing complete path coverage and global cross-cutting units; then run change verify --remaining. Resolve every unresolved path by inspecting the diff/dependency reach and updating the consumer-owned mapping or recording an owner decision.
|
|
12
|
+
- **Compatibility:** Backward-compatible opt-in. Existing project files, explicit profile verification, whole-profile reuse, required lifecycle profiles, and final review/release evidence remain supported. Consumers without impactProfiles receive a clear unavailable result, and schema-version 1 policies remain feedback-only.
|
|
13
|
+
- **Notes:** Path patterns are a versioned consumer policy, not a process guess. Overlapping units all run; a global unit may subsume narrower units only when its declared paths include the explicit universal \*\* pattern, while narrower patterns never cover unrelated paths. Affected feedback does not advance the lifecycle or prove final assurance. Final assurance records execution mode and selection identity in the existing lifecycle evidence; it does not create a second lifecycle or infer coverage from filenames, labels, commands, or diagnostics.
|
|
14
|
+
|
|
15
|
+
## Fixes
|
|
16
|
+
|
|
17
|
+
- **Render release records as readable Markdown without gratuitous escapes.** ([#171](https://github.com/phuongnse/engineering-process/issues/171))
|
|
18
|
+
- **Problem:** Generated release notes escaped every punctuation mark and padded ordinary code references, making otherwise complete issue-level records difficult to read.
|
|
19
|
+
- **What changed:** Escape only Markdown and HTML-sensitive metadata syntax, keep ordinary punctuation readable, and render simple owned references as normal inline code while retaining safe fencing for embedded backticks.
|
|
20
|
+
- **Where:** `engineering_process/release_notes.py`, `tests/test_release.py`, `release-changes/README.md`, `RELEASING.md`, `ARTIFACT_STANDARDS.md`, `RELEASE_NOTES.md`
|
|
21
|
+
- **Apply:** Use the normal prepare-release workflow and review the generated RELEASE\_NOTES.md against release.json before publication.
|
|
22
|
+
- **Compatibility:** No breaking change. Schema-v5 manifests and legacy release-note data remain readable; the selected release-notes@1 structure and published v2.5.0 body are not rewritten.
|
|
23
|
+
- **Notes:** This correction applies to subsequently generated release bodies. Published release artifacts remain immutable and must be corrected only through the owner's release policy.
|
|
24
|
+
- **Batch reusable verification evidence across lifecycle stages.** ([#198](https://github.com/phuongnse/engineering-process/issues/198))
|
|
25
|
+
- **Problem:** Continuation verification could make repeated reuse decisions and authority calculations one profile at a time even when several reports already covered the same unchanged candidate.
|
|
26
|
+
- **What changed:** Batch valid whole-profile reuse decisions into one canonical state write and reuse one process-authority digest across stable evidence comparisons. Preserve the selected runtime path spelling and virtual-environment symlinks across POSIX and Windows while retaining fresh candidate snapshots, runtime identity checks, explicit refresh semantics, and correction-cycle invalidation.
|
|
27
|
+
- **Where:** `engineering_process/evidence.py`, `engineering_process/lifecycle.py`, `engineering_process/pr_description.py`, `process_assets/skills/change-verify/SKILL.md`, `README.md`, `tests/test_lifecycle.py`, `tests/test_skills.py`
|
|
28
|
+
- **Apply:** Use change verify --remaining for continuation work. The process reuses only exact valid reports and records reuse without relaunching their child commands.
|
|
29
|
+
- **Compatibility:** No breaking change. Explicit profile verification remains an unconditional refresh; stale, legacy, or mismatched evidence reruns; final review and finish still require exact-snapshot evidence.
|
|
30
|
+
- **Notes:** The optimization is operation-scoped and does not add a persistent success cache or reuse evidence across a changed candidate, mutation boundary, or incompatible runtime. Runtime path normalization no longer dereferences the selected executable before constructing the bounded child PATH.
|
|
31
|
+
- **Make the full verification suite deterministic and expose bounded timing diagnostics.** ([#201](https://github.com/phuongnse/engineering-process/issues/201))
|
|
32
|
+
- **Problem:** The repository-owned full verification suite took about six minutes on Windows and review-context tests incorrectly reported stale evidence when run after the complete suite, while local output did not identify the slowest tests.
|
|
33
|
+
- **What changed:** Give review-context tests an isolated fixture owner, seed their verified states once per test class, use the same bounded child environment as the verification boundary, and report aggregate, slow-test, fixture-setup, and profile timing without changing profile exit semantics or deleting behavioral coverage. Lifecycle fixtures clone an immutable Git snapshot instead of copying a live .git directory, avoiding races with Git maintenance locks.
|
|
34
|
+
- **Where:** `tests/test_review_contexts.py`, `tests/test_lifecycle.py`, `verification/run_test_suite.py`
|
|
35
|
+
- **Apply:** Run the normal development and review profiles; use the bounded suite timing and slow-test summary to diagnose future cost, and do not replace final verification with a focused subset.
|
|
36
|
+
- **Compatibility:** No breaking change. Existing profile commands, required checks, skip behavior, process/Git/filesystem boundaries, and stored evidence semantics remain supported.
|
|
37
|
+
- **Notes:** The reviewed change evidence records repeated comparable self-consumer measurements and the bounded improvement method; it does not establish a universal latency target. Shared mutable checkouts and blanket mocks remain out of scope.
|
|
38
|
+
|
|
39
|
+
## Upgrade and compatibility
|
|
40
|
+
|
|
41
|
+
Merge the complete hash-locked package/adoption PR, update the local and CI environments to the selected version, and start a fresh agent session.
|
|
42
|
+
|
|
43
|
+
Consumer CI, naming conventions and branch-protection settings remain consumer-owned; adoption does not configure them automatically.
|
|
44
|
+
|
|
45
|
+
No breaking changes are included. Read each change's Apply, Compatibility and Notes entry before adopting.
|
|
46
|
+
|
|
47
|
+
See [versioning and compatibility](https://github.com/phuongnse/engineering-process/blob/v2.6.0/VERSIONING.md) and [adoption guidance](https://github.com/phuongnse/engineering-process/blob/v2.6.0/SELF_HOSTING.md).
|
|
48
|
+
|
|
49
|
+
[Full change comparison](https://github.com/phuongnse/engineering-process/compare/v2.5.0...v2.6.0)
|
|
@@ -38,10 +38,14 @@ from .lifecycle import (
|
|
|
38
38
|
start_change,
|
|
39
39
|
start_review,
|
|
40
40
|
submit_review,
|
|
41
|
+
resolve_impact_work,
|
|
42
|
+
resolve_verification_work,
|
|
43
|
+
verify_affected,
|
|
44
|
+
verify_remaining,
|
|
41
45
|
verify_change,
|
|
42
46
|
)
|
|
43
47
|
from .issue import render_issue
|
|
44
|
-
from .project import load_project, readiness_summary
|
|
48
|
+
from .project import impact_profiles, load_project, readiness_summary
|
|
45
49
|
from .production_engineering import (
|
|
46
50
|
validate_plan_assessments,
|
|
47
51
|
validate_review_assessments,
|
|
@@ -53,7 +57,13 @@ from .publication_compat import (
|
|
|
53
57
|
validate_range,
|
|
54
58
|
)
|
|
55
59
|
from .release import validate_release
|
|
56
|
-
from .pr_description import
|
|
60
|
+
from .pr_description import (
|
|
61
|
+
body_issues,
|
|
62
|
+
build_pr_description_data,
|
|
63
|
+
render_description,
|
|
64
|
+
render_renovate_preset,
|
|
65
|
+
render_template,
|
|
66
|
+
)
|
|
57
67
|
from .release_notes import render_notes
|
|
58
68
|
from .repository import repository_snapshot, same_checkpoint
|
|
59
69
|
from .skills import validate_skills
|
|
@@ -87,9 +97,16 @@ def _result(command: str, status: str = "passed", **details: Any) -> dict[str, A
|
|
|
87
97
|
return {"command": command, "status": status, **details}
|
|
88
98
|
|
|
89
99
|
|
|
90
|
-
def _state_result(
|
|
100
|
+
def _state_result(
|
|
101
|
+
command: str,
|
|
102
|
+
state: dict[str, Any],
|
|
103
|
+
*,
|
|
104
|
+
status: str = "passed",
|
|
105
|
+
**details: Any,
|
|
106
|
+
) -> dict[str, Any]:
|
|
91
107
|
return _result(
|
|
92
108
|
command,
|
|
109
|
+
status=status,
|
|
93
110
|
changeId=state["changeId"],
|
|
94
111
|
phase=state["phase"],
|
|
95
112
|
cycle=state["cycle"],
|
|
@@ -120,6 +137,7 @@ def command_project_validate(args: argparse.Namespace) -> Result:
|
|
|
120
137
|
"project validate",
|
|
121
138
|
project=project["project"],
|
|
122
139
|
profiles=sorted(project["profiles"]),
|
|
140
|
+
impactProfiles=sorted(impact_profiles(project)),
|
|
123
141
|
requiredProfiles=project["lifecycle"]["requiredProfiles"],
|
|
124
142
|
readiness=readiness_summary(project),
|
|
125
143
|
), 0
|
|
@@ -311,7 +329,84 @@ def command_change_implement(args: argparse.Namespace) -> Result:
|
|
|
311
329
|
|
|
312
330
|
def command_change_verify(args: argparse.Namespace) -> Result:
|
|
313
331
|
process_root = _process_root(args)
|
|
332
|
+
if getattr(args, "affected", False):
|
|
333
|
+
selected_profiles = tuple(getattr(args, "affected_profile", []) or []) or None
|
|
334
|
+
state, selection, executions = verify_affected(
|
|
335
|
+
args.project_root,
|
|
336
|
+
process_root,
|
|
337
|
+
{},
|
|
338
|
+
args.change_id,
|
|
339
|
+
profiles=selected_profiles,
|
|
340
|
+
)
|
|
341
|
+
execution_status = executions[0]["status"] if executions else None
|
|
342
|
+
status = (
|
|
343
|
+
"passed"
|
|
344
|
+
if selection["status"] == "ready" and execution_status == "passed"
|
|
345
|
+
else selection["status"]
|
|
346
|
+
if selection["status"] != "ready"
|
|
347
|
+
else "failed"
|
|
348
|
+
)
|
|
349
|
+
return _state_result(
|
|
350
|
+
"change verify",
|
|
351
|
+
state,
|
|
352
|
+
status=status,
|
|
353
|
+
selection=selection,
|
|
354
|
+
execution="affected",
|
|
355
|
+
evidence="feedback-only; does not satisfy a required full profile",
|
|
356
|
+
executions=executions,
|
|
357
|
+
), (0 if status == "passed" else 1)
|
|
358
|
+
if getattr(args, "affected_profile", []):
|
|
359
|
+
raise ProcessError("--affected-profile requires --affected")
|
|
314
360
|
project = load_project(args.project_root, process_root)
|
|
361
|
+
if args.remaining:
|
|
362
|
+
state, selection = verify_remaining(
|
|
363
|
+
args.project_root, process_root, project, args.change_id
|
|
364
|
+
)
|
|
365
|
+
executions = []
|
|
366
|
+
failures = []
|
|
367
|
+
for profile in selection["executeProfiles"]:
|
|
368
|
+
report = state["verification"].get(profile)
|
|
369
|
+
if report is None:
|
|
370
|
+
failures.append(profile)
|
|
371
|
+
continue
|
|
372
|
+
if report["status"] != "passed":
|
|
373
|
+
failures.append(profile)
|
|
374
|
+
check_duration = sum(check["durationMs"] for check in report["checks"])
|
|
375
|
+
executions.append(
|
|
376
|
+
{
|
|
377
|
+
"profile": profile,
|
|
378
|
+
"status": report["status"],
|
|
379
|
+
"executionMode": report.get("executionMode", "full"),
|
|
380
|
+
"launchCount": len(report["checks"]),
|
|
381
|
+
"durationMs": report.get("durationMs", check_duration),
|
|
382
|
+
"checkDurationMs": check_duration,
|
|
383
|
+
"processOverheadMs": max(
|
|
384
|
+
0, report.get("durationMs", check_duration) - check_duration
|
|
385
|
+
),
|
|
386
|
+
}
|
|
387
|
+
)
|
|
388
|
+
contract = state.get("contract", {})
|
|
389
|
+
required_profiles = (
|
|
390
|
+
contract.get("document", {}).get("requiredProfiles", [])
|
|
391
|
+
if isinstance(contract, dict)
|
|
392
|
+
else []
|
|
393
|
+
)
|
|
394
|
+
verification = state.get("verification", {})
|
|
395
|
+
required_profiles_passed = bool(required_profiles) and all(
|
|
396
|
+
isinstance(verification.get(profile), dict)
|
|
397
|
+
and verification[profile].get("status") == "passed"
|
|
398
|
+
for profile in required_profiles
|
|
399
|
+
)
|
|
400
|
+
complete = state["phase"] == "verified" and required_profiles_passed
|
|
401
|
+
return _state_result(
|
|
402
|
+
"change verify",
|
|
403
|
+
state,
|
|
404
|
+
status="passed" if complete and not failures else "failed",
|
|
405
|
+
selection=selection,
|
|
406
|
+
execution="remaining",
|
|
407
|
+
executions=executions,
|
|
408
|
+
failures=failures,
|
|
409
|
+
), (0 if complete and not failures else 1)
|
|
315
410
|
state, report = verify_change(
|
|
316
411
|
args.project_root, process_root, project, args.change_id, args.profile
|
|
317
412
|
)
|
|
@@ -321,6 +416,27 @@ def command_change_verify(args: argparse.Namespace) -> Result:
|
|
|
321
416
|
), code
|
|
322
417
|
|
|
323
418
|
|
|
419
|
+
def command_change_explain(args: argparse.Namespace) -> Result:
|
|
420
|
+
process_root = _process_root(args)
|
|
421
|
+
if getattr(args, "impact", False):
|
|
422
|
+
profiles = (args.profile,) if args.profile else None
|
|
423
|
+
selection = resolve_impact_work(
|
|
424
|
+
args.project_root,
|
|
425
|
+
process_root,
|
|
426
|
+
{},
|
|
427
|
+
args.change_id,
|
|
428
|
+
profiles=profiles,
|
|
429
|
+
)
|
|
430
|
+
return _result("change explain", selection=selection), 0
|
|
431
|
+
if getattr(args, "profile", None):
|
|
432
|
+
raise ProcessError("--profile for change explain requires --impact")
|
|
433
|
+
project = load_project(args.project_root, process_root)
|
|
434
|
+
selection = resolve_verification_work(
|
|
435
|
+
args.project_root, process_root, project, args.change_id
|
|
436
|
+
)
|
|
437
|
+
return _result("change explain", selection=selection), 0
|
|
438
|
+
|
|
439
|
+
|
|
324
440
|
def command_change_review_start(args: argparse.Namespace) -> Result:
|
|
325
441
|
process_root = _process_root(args)
|
|
326
442
|
state = start_review(
|
|
@@ -434,13 +550,37 @@ def command_artifact(args: argparse.Namespace) -> Result:
|
|
|
434
550
|
f"{standard.document['adapter']} state must be "
|
|
435
551
|
+ " or ".join(sorted(allowed_states))
|
|
436
552
|
)
|
|
437
|
-
|
|
553
|
+
if getattr(args, "change_id", None) is not None and standard.document["adapter"] == "pr-description":
|
|
554
|
+
overrides = (
|
|
555
|
+
load_and_validate(
|
|
556
|
+
args.data_file,
|
|
557
|
+
"pr-description-data",
|
|
558
|
+
schema_root=schemas_root(process_root),
|
|
559
|
+
)
|
|
560
|
+
if args.data_file is not None
|
|
561
|
+
else None
|
|
562
|
+
)
|
|
563
|
+
data = build_pr_description_data(
|
|
564
|
+
args.project_root,
|
|
565
|
+
process_root,
|
|
566
|
+
args.change_id,
|
|
567
|
+
overrides=overrides,
|
|
568
|
+
standard=standard,
|
|
569
|
+
)
|
|
570
|
+
elif args.data_file is not None:
|
|
571
|
+
data = load_and_validate(
|
|
572
|
+
args.data_file,
|
|
573
|
+
standard.document["adapter"] + "-data",
|
|
574
|
+
schema_root=schemas_root(process_root),
|
|
575
|
+
)
|
|
576
|
+
else:
|
|
577
|
+
data = None
|
|
438
578
|
if data is not None:
|
|
439
579
|
renderer = {"pr-description": render_description, "release-notes": render_notes, "automation-name": render_name, "issue": render_issue}[standard.document["adapter"]]
|
|
440
580
|
payload = renderer(standard, data, state=state, process_root=process_root).encode("utf-8")
|
|
441
581
|
details["dataDigest"] = digest_json(data)
|
|
442
582
|
elif operation == "render" or standard.document["adapter"] != "pr-description":
|
|
443
|
-
raise ProcessError("this artifact operation requires --data-file")
|
|
583
|
+
raise ProcessError("this artifact operation requires --data-file or --change-id")
|
|
444
584
|
if operation == "validate":
|
|
445
585
|
actual = read_document(args.body_file)
|
|
446
586
|
if data is None:
|
|
@@ -460,6 +600,38 @@ def command_artifact(args: argparse.Namespace) -> Result:
|
|
|
460
600
|
return _result(f"artifact {operation}", status, **details, issues=issues), (1 if issues else 0)
|
|
461
601
|
|
|
462
602
|
|
|
603
|
+
def command_artifact_prepare_pr_data(args: argparse.Namespace) -> Result:
|
|
604
|
+
process_root = _process_root(args)
|
|
605
|
+
standard = resolve_standard(args.project_root, process_root, "pull-request")
|
|
606
|
+
overrides = (
|
|
607
|
+
load_and_validate(
|
|
608
|
+
args.data_file,
|
|
609
|
+
"pr-description-data",
|
|
610
|
+
schema_root=schemas_root(process_root),
|
|
611
|
+
)
|
|
612
|
+
if args.data_file is not None
|
|
613
|
+
else None
|
|
614
|
+
)
|
|
615
|
+
data = build_pr_description_data(
|
|
616
|
+
args.project_root,
|
|
617
|
+
process_root,
|
|
618
|
+
args.change_id,
|
|
619
|
+
overrides=overrides,
|
|
620
|
+
standard=standard,
|
|
621
|
+
)
|
|
622
|
+
payload = formatted_json_bytes(data)
|
|
623
|
+
details: dict[str, Any] = {
|
|
624
|
+
"changeId": args.change_id,
|
|
625
|
+
"dataDigest": digest_json(data),
|
|
626
|
+
}
|
|
627
|
+
if args.output is not None:
|
|
628
|
+
args.output.write_bytes(payload)
|
|
629
|
+
details["output"] = str(args.output)
|
|
630
|
+
else:
|
|
631
|
+
details["data"] = data
|
|
632
|
+
return _result("artifact prepare-pr-data", "passed", **details), 0
|
|
633
|
+
|
|
634
|
+
|
|
463
635
|
def _add_common(parser: argparse.ArgumentParser, *, project: bool = True) -> None:
|
|
464
636
|
if project:
|
|
465
637
|
parser.add_argument("--project-root", type=_root, default=Path.cwd())
|
|
@@ -536,7 +708,21 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
536
708
|
change_implement.add_argument("--change-id", required=True)
|
|
537
709
|
change_verify = _leaf(change_commands, "verify", command_change_verify)
|
|
538
710
|
change_verify.add_argument("--change-id", required=True)
|
|
539
|
-
change_verify.
|
|
711
|
+
verify_scope = change_verify.add_mutually_exclusive_group(required=True)
|
|
712
|
+
verify_scope.add_argument("--profile")
|
|
713
|
+
verify_scope.add_argument("--remaining", action="store_true")
|
|
714
|
+
verify_scope.add_argument("--affected", action="store_true")
|
|
715
|
+
change_verify.add_argument(
|
|
716
|
+
"--affected-profile",
|
|
717
|
+
action="append",
|
|
718
|
+
default=[],
|
|
719
|
+
help="limit --affected to one or more accepted profiles",
|
|
720
|
+
)
|
|
721
|
+
|
|
722
|
+
change_explain = _leaf(change_commands, "explain", command_change_explain)
|
|
723
|
+
change_explain.add_argument("--change-id", required=True)
|
|
724
|
+
change_explain.add_argument("--impact", action="store_true")
|
|
725
|
+
change_explain.add_argument("--profile")
|
|
540
726
|
|
|
541
727
|
review = change_commands.add_parser("review")
|
|
542
728
|
review_commands = review.add_subparsers(dest="review_command", required=True)
|
|
@@ -564,12 +750,17 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
564
750
|
|
|
565
751
|
artifact = commands.add_parser("artifact", help="Generate and verify consumer-selected artifact standards")
|
|
566
752
|
artifact_commands = artifact.add_subparsers(dest="artifact_command", required=True)
|
|
753
|
+
prepare_pr_data = _leaf(artifact_commands, "prepare-pr-data", command_artifact_prepare_pr_data)
|
|
754
|
+
prepare_pr_data.add_argument("--change-id", required=True)
|
|
755
|
+
prepare_pr_data.add_argument("--data-file", type=Path)
|
|
756
|
+
prepare_pr_data.add_argument("--output", type=Path)
|
|
567
757
|
for name in ("show", "template", "renovate-preset", "render", "validate"):
|
|
568
758
|
leaf = _leaf(artifact_commands, name, command_artifact)
|
|
569
759
|
leaf.add_argument("--artifact", required=True)
|
|
570
760
|
if name in {"render", "validate"}:
|
|
571
761
|
leaf.add_argument("--state", choices=("draft", "ready", "open", "closed"))
|
|
572
|
-
leaf.add_argument("--
|
|
762
|
+
leaf.add_argument("--change-id")
|
|
763
|
+
leaf.add_argument("--data-file", type=Path, required=False)
|
|
573
764
|
if name == "validate":
|
|
574
765
|
leaf.add_argument("--body-file", type=Path, required=True)
|
|
575
766
|
else:
|