methodology-framework 0.1.2__tar.gz → 0.3.2__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.
Files changed (37) hide show
  1. {methodology_framework-0.1.2/src/methodology_framework.egg-info → methodology_framework-0.3.2}/PKG-INFO +192 -47
  2. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/README.md +189 -46
  3. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/pyproject.toml +4 -1
  4. methodology_framework-0.3.2/src/methodology_framework/bootstrap_jira.py +702 -0
  5. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework/build_playbook.py +30 -9
  6. methodology_framework-0.3.2/src/methodology_framework/jira_discovery.py +389 -0
  7. methodology_framework-0.3.2/src/methodology_framework/playbooks/bindings/meth.yaml +10 -0
  8. methodology_framework-0.3.2/src/methodology_framework/playbooks/bindings/scrum.yaml +11 -0
  9. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework/playbooks/scrum-router.body.md +35 -25
  10. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework/sync_stories_to_jira.py +250 -138
  11. {methodology_framework-0.1.2 → methodology_framework-0.3.2/src/methodology_framework.egg-info}/PKG-INFO +192 -47
  12. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework.egg-info/SOURCES.txt +4 -0
  13. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework.egg-info/requires.txt +2 -0
  14. methodology_framework-0.3.2/tests/test_bootstrap_jira.py +719 -0
  15. methodology_framework-0.3.2/tests/test_jira_discovery.py +247 -0
  16. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/tests/test_sync_stories_to_jira.py +233 -167
  17. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/tests/test_workflows.py +3 -5
  18. methodology_framework-0.1.2/src/methodology_framework/bootstrap_jira.py +0 -618
  19. methodology_framework-0.1.2/tests/test_bootstrap_jira.py +0 -392
  20. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/LICENSE +0 -0
  21. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/setup.cfg +0 -0
  22. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework/__init__.py +0 -0
  23. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework/__main__.py +0 -0
  24. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework/jira_shapes/__init__.py +0 -0
  25. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework/jira_shapes/automation_rules.yaml +0 -0
  26. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework/jira_shapes/custom_fields.yaml +0 -0
  27. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework/jira_shapes/workflow.yaml +0 -0
  28. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework/populate_acus.py +0 -0
  29. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework/register_playbook_with_devin.py +0 -0
  30. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework/specs/devin-story-format.md +0 -0
  31. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework/templates/github_workflows/populate-story-acus-caller.yml +0 -0
  32. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework/templates/story.md +0 -0
  33. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework.egg-info/dependency_links.txt +0 -0
  34. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/src/methodology_framework.egg-info/top_level.txt +0 -0
  35. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/tests/test_build_playbook.py +0 -0
  36. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/tests/test_populate_acus.py +0 -0
  37. {methodology_framework-0.1.2 → methodology_framework-0.3.2}/tests/test_register_playbook_with_devin.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: methodology-framework
3
- Version: 0.1.2
3
+ Version: 0.3.2
4
4
  Summary: Portable process tooling for agent-driven delivery — scripts, playbooks, templates, and specs.
5
5
  Author: whiteout59
6
6
  License-Expression: Apache-2.0
@@ -10,6 +10,7 @@ License-File: LICENSE
10
10
  Requires-Dist: requests<3,>=2.31
11
11
  Requires-Dist: python-frontmatter<2,>=1.1
12
12
  Requires-Dist: pyyaml<7,>=6.0
13
+ Requires-Dist: colorama<1,>=0.4
13
14
  Provides-Extra: dev
14
15
  Requires-Dist: pytest<9,>=8.0; extra == "dev"
15
16
  Requires-Dist: requests-mock<2,>=1.12; extra == "dev"
@@ -17,6 +18,7 @@ Requires-Dist: ruff==0.15.14; extra == "dev"
17
18
  Requires-Dist: mypy<2,>=1.10; extra == "dev"
18
19
  Requires-Dist: types-requests<3,>=2.31; extra == "dev"
19
20
  Requires-Dist: types-PyYAML<7,>=6.0; extra == "dev"
21
+ Requires-Dist: types-colorama<1,>=0.4; extra == "dev"
20
22
  Requires-Dist: vcrpy<9,>=7.0; extra == "dev"
21
23
  Dynamic: license-file
22
24
 
@@ -38,69 +40,101 @@ pip install -e .
38
40
  - `methodology_framework/playbooks/` -- parameterized playbook bodies (package data)
39
41
  - `methodology_framework/templates/` -- story and process templates (package data)
40
42
  - `methodology_framework/specs/` -- format specs (package data)
41
- - `methodology_framework.bootstrap_jira` -- bootstrap a Jira project with the canonical workflow, custom fields, and automation rules
43
+ - `methodology_framework.bootstrap_jira` -- verify a Jira project matches the canonical shape (read-only spec-compliance checker)
42
44
  - `methodology_framework/jira_shapes/` -- canonical Jira shape definitions (YAML, package data)
43
45
 
44
- ## Jira Bootstrap
46
+ ## Jira Bootstrap (Verify Mode)
45
47
 
46
- Adopting projects provision their Jira project shape from a single CLI command
47
- instead of manually configuring 30+ admin UI screens.
48
+ The CLI checks whether a Jira project matches the methodology-framework's
49
+ canonical shape and reports gaps. It does **not** provision — operators apply
50
+ gaps via the Jira UI. This read-only design lets the tool run in CI as a gate.
51
+
52
+ > **v0.2.0 breaking change:** `--apply` and `--dry-run` were removed.
53
+ > The CLI is now a spec-compliance verifier. See `operator-verify-runbook.md`
54
+ > for the operator workflow.
48
55
 
49
56
  ### Prerequisites
50
57
 
51
58
  - Python 3.12+
52
59
  - `pip install methodology-framework` (or `pip install -e .` from source)
53
- - For `--apply` mode: `JIRA_ADMIN_TOKEN` environment variable set to a Jira
54
- admin API token, and `JIRA_USER_EMAIL` set to the email of the Atlassian
55
- account that owns that token
60
+ - For `--verify` mode: `JIRA_ADMIN_TOKEN` environment variable set to a Jira
61
+ API token (admin scope is **not** required; a regular user token with read
62
+ access is sufficient), and `JIRA_USER_EMAIL` set to the email of the
63
+ Atlassian account that owns the token
56
64
 
57
65
  ### Usage
58
66
 
59
67
  ```bash
60
- # Dry-run (default) print what would be applied, no side-effects
68
+ # Verifyquery Jira and report spec-compliance gaps (read-only)
69
+ export JIRA_ADMIN_TOKEN="<your-token>"
70
+ export JIRA_USER_EMAIL="<your-email>"
61
71
  python -m methodology_framework bootstrap-jira \
62
72
  --project-key=MYPROJ \
63
73
  --jira-host=myorg.atlassian.net \
64
- --dry-run
74
+ --verify
65
75
 
66
- # Export emit an importable config bundle (YAML); no API calls
76
+ # JSON output (stable schema safe for CI parsing)
67
77
  python -m methodology_framework bootstrap-jira \
68
78
  --project-key=MYPROJ \
69
79
  --jira-host=myorg.atlassian.net \
70
- --export /tmp/jira-bundle.yaml
80
+ --verify --output=json
71
81
 
72
- # Apply — provision the Jira project via admin API
73
- export JIRA_ADMIN_TOKEN="<your-token>"
74
- export JIRA_USER_EMAIL="<your-email>"
82
+ # Markdown output
75
83
  python -m methodology_framework bootstrap-jira \
76
84
  --project-key=MYPROJ \
77
85
  --jira-host=myorg.atlassian.net \
78
- --apply
86
+ --verify --output=markdown
79
87
 
80
- # Apply with --force to skip confirmation prompts
88
+ # Export emit an importable config bundle (YAML); no API calls
81
89
  python -m methodology_framework bootstrap-jira \
82
90
  --project-key=MYPROJ \
83
91
  --jira-host=myorg.atlassian.net \
84
- --apply --force
92
+ --export /tmp/jira-bundle.yaml
85
93
  ```
86
94
 
95
+ ### Exit codes
96
+
97
+ | Code | Meaning |
98
+ |------|---------|
99
+ | `0` | All spec items verified OK |
100
+ | `1` | One or more items missing (gaps found) |
101
+ | `2` | One or more items unverifiable (API limitation; operator must inspect manually) |
102
+ | `3` | Error (connectivity, auth, or runtime failure) |
103
+
87
104
  ### Flags
88
105
 
89
106
  | Flag | Required | Description |
90
107
  |------|----------|-------------|
91
108
  | `--project-key` | Yes | Jira project key (e.g. `SCRUM`). Substituted for `{{PROJECT_KEY}}` in shape defs. |
92
109
  | `--jira-host` | Yes | Jira Cloud host (e.g. `myorg.atlassian.net`). No `https://` prefix. |
93
- | `--dry-run` | No | Print what would be applied (default if no mode specified). |
94
- | `--apply` | No | POST/PUT to Jira admin API. Requires `JIRA_ADMIN_TOKEN` env var. |
95
- | `--export <path>` | No | Emit importable config bundle at `<path>`. |
96
- | `--force` | No | Skip confirmation prompts during `--apply`. |
110
+ | `--verify` | No | Query Jira and report spec-compliance gaps (read-only). |
111
+ | `--export <path>` | No | Emit importable config bundle at `<path>`. No API calls. |
112
+ | `--output` | No | Output format for `--verify`: `text` (default), `json`, `markdown`. |
97
113
 
98
114
  ### Environment variables
99
115
 
100
116
  | Variable | When needed | Description |
101
117
  |----------|-------------|-------------|
102
- | `JIRA_ADMIN_TOKEN` | `--apply` mode | Jira admin API token. **Never** accepted as a CLI flag. |
103
- | `JIRA_USER_EMAIL` | `--apply` mode | Email of the Atlassian account that owns the API token. Used with the token for HTTP Basic auth. **Never** accepted as a CLI flag. |
118
+ | `JIRA_ADMIN_TOKEN` | `--verify` mode | Jira API token. Admin scope is **not** required; a regular user token with read access is sufficient. **Never** accepted as a CLI flag. |
119
+ | `JIRA_USER_EMAIL` | `--verify` mode | Email of the Atlassian account that owns the API token. Used with the token for HTTP Basic auth. **Never** accepted as a CLI flag. |
120
+
121
+ ### JSON output schema (v0.2.0)
122
+
123
+ ```json
124
+ {
125
+ "spec_version": "0.2.0",
126
+ "project_key": "METH",
127
+ "verified_at": "2025-05-31T00:00:00Z",
128
+ "items": [
129
+ {"resource_type": "status", "name": "To Do", "result": "ok", "details": null},
130
+ {"resource_type": "custom_field", "name": "Story File", "result": "missing", "details": "Operator must create via Settings → Custom fields → Create"}
131
+ ],
132
+ "summary": {"total": 14, "ok": 12, "missing": 1, "unverifiable": 1},
133
+ "exit_code": 1
134
+ }
135
+ ```
136
+
137
+ Any breaking change to this schema requires a MAJOR version bump.
104
138
 
105
139
  ### Shape definitions
106
140
 
@@ -129,10 +163,63 @@ framework's workflows by SemVer tag.
129
163
  > in the caller so updates are deliberate, not silent. This matches the
130
164
  > version-pinning model per methodology requirements § 4.13.
131
165
 
166
+ ### Required inputs
167
+
168
+ | Input | Required | Default | Description |
169
+ |-------|----------|---------|-------------|
170
+ | `project-key` | **Yes** | — | Jira project key (e.g. `METH`, `SCRUM`). No default — sync errors if absent. |
171
+ | `jira-base-url` | **Yes** | — | Jira Cloud base URL (e.g. `https://icpipeline.atlassian.net`). |
172
+ | `jira-user-email` | **Yes** | — | Jira service account email for HTTP Basic auth. |
173
+ | `stories-dir` | No | `docs/stories` | Relative path to the stories directory. |
174
+ | `phase-regex` | No | `^phase\d+$` | Regex for phase directory matching. Empty string (`""`) disables phase labeling entirely. |
175
+ | `repo-url` | No | *(auto)* | Override repo URL. Normally derived from `GITHUB_SERVER_URL` + `GITHUB_REPOSITORY` (GHA-native). |
176
+
177
+ ### Per-tenant discovery
178
+
179
+ Sync discovers all tenant-specific Jira IDs at runtime via the REST API,
180
+ using canonical **names** as lookup keys. The names come from the framework's
181
+ shape definitions (`jira_shapes/*.yaml`) — the same spec the verifier
182
+ (`bootstrap-jira --verify`) enforces.
183
+
184
+ **Custom fields** (discovered via `GET /rest/api/3/field`):
185
+
186
+ | Name | Purpose |
187
+ |------|---------|
188
+ | `Requirement IDs` | Multi-value field for REQ-id traceability |
189
+ | `Story File` | URL to the canonical story `.md` file in the repo |
190
+ | `Agent Estimate` | Numeric estimate in agent-hours |
191
+
192
+ **Statuses** (discovered via `GET /rest/api/3/project/{key}/statuses`):
193
+
194
+ | Name | Category |
195
+ |------|----------|
196
+ | `To Do` | TODO |
197
+ | `Ready for AI agent` | TODO |
198
+ | `In Progress` | IN_PROGRESS |
199
+ | `In Review` | IN_PROGRESS |
200
+ | `Waiting` | IN_PROGRESS |
201
+ | `Blocked` | IN_PROGRESS |
202
+ | `Done` | DONE |
203
+ | `Won't do` | DONE |
204
+
205
+ **Transitions**: Sourced from the workflow spec (`jira_shapes/workflow.yaml`).
206
+
207
+ **Link types** (discovered via `GET /rest/api/3/issueLinkType`):
208
+ `Blocks` (inward: "is blocked by").
209
+
210
+ **Issue types** (discovered via `GET /rest/api/3/issuetype`):
211
+ `Story`, `Sub-task`.
212
+
213
+ If any required name is missing from the target project, sync fails fast:
214
+ ```
215
+ ERROR: Required custom field 'Story File' not found in Jira project METH;
216
+ run 'methodology-framework bootstrap-jira --verify --project-key=METH' to identify the gap.
217
+ ```
218
+
132
219
  ### Story sync workflow
133
220
 
134
221
  Syncs story `.md` files from the adopter's repo to Jira. Create
135
- `.github/workflows/sync.yml` in the adopter repo:
222
+ `.github/workflows/sync-stories.yml` in the adopter repo:
136
223
 
137
224
  ```yaml
138
225
  name: Sync stories to Jira
@@ -155,17 +242,17 @@ on:
155
242
 
156
243
  jobs:
157
244
  sync:
158
- uses: whiteout59/methodology-framework/.github/workflows/sync.yml@v0.1.0
245
+ permissions:
246
+ contents: write
247
+ pull-requests: read
248
+ uses: whiteout59/methodology-framework/.github/workflows/sync.yml@v0.3.0
159
249
  with:
160
- project_key: SCRUM
161
- repo: whiteout59/centralized-pipeline-ui
162
- story_path_pattern: "docs/stories/{phase1,phase2}/**/*.md"
163
- cf_story_file: "customfield_10073"
164
- cf_requirement_ids: "customfield_10141"
165
- cf_agent_estimate: "customfield_10074"
250
+ project_key: MYPROJ
166
251
  mode: ${{ github.event.inputs.mode || 'since-ref' }}
167
252
  jira_base_url: "https://myorg.atlassian.net"
168
253
  jira_user_email: "devin-sync@myorg.atlassian.net"
254
+ # stories_dir: "docs/stories" # default
255
+ # phase_regex: "^phase\\d+$" # default; set "" to disable
169
256
  secrets:
170
257
  JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
171
258
  ```
@@ -179,6 +266,34 @@ for nightly or `workflow_dispatch` full-corpus syncs.
179
266
  > inherited by default in reusable workflows. Using `secrets: inherit`
180
267
  > works but is brittle — prefer explicit mapping.
181
268
 
269
+ #### Required caller permissions
270
+
271
+ The reusable sync workflow declares `permissions: contents: write`
272
+ internally (for `jira_key` + `agent_acus` writeback commits). GitHub
273
+ Actions requires the **caller** to grant at least the same permissions
274
+ at the job level — otherwise the workflow fails at the `uses:`
275
+ resolution step with:
276
+
277
+ ```
278
+ The workflow is requesting 'contents: write', but is only allowed 'contents: read'.
279
+ ```
280
+
281
+ Add a job-level `permissions:` block to your caller:
282
+
283
+ ```yaml
284
+ jobs:
285
+ sync:
286
+ permissions:
287
+ contents: write
288
+ pull-requests: read
289
+ uses: whiteout59/methodology-framework/.github/workflows/sync.yml@v0.2.0
290
+ # ... with: / secrets: as above
291
+ ```
292
+
293
+ > **Job-scoped, not workflow-scoped.** Keep `permissions:` on the job,
294
+ > not the top-level `on:` — if future jobs are added to the same file,
295
+ > they should not inherit write access they don't need.
296
+
182
297
  ### Playbook build + register workflow
183
298
 
184
299
  Builds a concrete playbook from a parameterized body + bindings file,
@@ -210,6 +325,16 @@ jobs:
210
325
  > 4 levels deep. If your repo wraps these workflows in another
211
326
  > caller layer, verify the total nesting depth stays within limits.
212
327
 
328
+ ## How this repo evolves
329
+
330
+ The methodology-framework repo itself uses the same sync workflow it
331
+ ships to adopters. Framework-side evolution stories (new specs, CLI
332
+ features, workflow improvements) are drafted as `.md` files under
333
+ `docs/stories/` and synced to the **METH** Jira project via
334
+ [`.github/workflows/sync-stories.yml`](.github/workflows/sync-stories.yml).
335
+ Adopter-side stories (product-specific work) file in each adopter's own
336
+ Jira project (e.g. SCRUM for centralized-pipeline-ui).
337
+
213
338
  ## PyPI Publishing
214
339
 
215
340
  The package is published to PyPI automatically via OIDC Trusted Publishers
@@ -234,31 +359,37 @@ to the GitHub repo `whiteout59/methodology-framework`, workflow
234
359
  Version bumps in `pyproject.toml` drive the entire release cycle
235
360
  automatically. The operator's only decision surface is PR review.
236
361
 
237
- ### Normal flow
362
+ ### Primary flow (chained via `workflow_call`)
238
363
 
239
- 1. A PR bumps the `version` field in `pyproject.toml` (e.g. `"0.1.1"` → `"0.1.2"`).
364
+ 1. A PR bumps the `version` field in `pyproject.toml` (e.g. `"0.2.0"` → `"0.2.1"`).
240
365
  2. Reviewer approves and merges the PR to `main`.
241
- 3. The `auto-tag.yml` workflow detects the `pyproject.toml` change, extracts the
242
- version, validates it as stable SemVer (`^[0-9]+\.[0-9]+\.[0-9]+$`), and
243
- creates an annotated tag `v0.1.2`.
244
- 4. The `pypi-release.yml` workflow fires on the new tag and publishes the
245
- package to PyPI via OIDC Trusted Publishers.
366
+ 3. `auto-tag.yml` fires on the `pyproject.toml` change, extracts the version,
367
+ validates it as stable SemVer (`^[0-9]+\.[0-9]+\.[0-9]+$`), and creates an
368
+ annotated tag `v0.2.1`.
369
+ 4. `auto-tag.yml`'s `publish` job invokes `pypi-release.yml` via `workflow_call`,
370
+ passing the version as an input.
371
+ 5. `pypi-release.yml` checks out the tag, builds the package, and publishes to
372
+ PyPI via OIDC Trusted Publishers.
246
373
 
247
- **Operator surface = PR review only.** No manual `git tag` step required.
374
+ **Operator surface = PR review only.** No manual `git tag` step, no manual
375
+ publish trigger. The `workflow_call` chain bypasses GitHub's recursion guard
376
+ that prevents `GITHUB_TOKEN`-authored tag pushes from triggering downstream
377
+ workflows via `on: push: tags:`.
248
378
 
249
- ### Manual fallback
379
+ ### Fallback (operator-pushed tag)
250
380
 
251
381
  If `auto-tag.yml` doesn't fire (workflow disabled, branch protection
252
- blocking the tag push, GitHub Actions outage, etc.), the manual fallback
253
- still works:
382
+ blocking the tag push, GitHub Actions outage, etc.), or the operator needs
383
+ to re-publish a yanked version, the manual fallback still works:
254
384
 
255
385
  ```bash
256
- git tag -a v0.1.2 -m "Release v0.1.2"
257
- git push origin v0.1.2
386
+ git tag -a vX.Y.Z -m "Release vX.Y.Z"
387
+ git push origin vX.Y.Z
258
388
  ```
259
389
 
260
- `pypi-release.yml` doesn't care how the tag arrived — it fires on any
261
- tag matching `v[0-9]+.[0-9]+.[0-9]+`.
390
+ An operator-pushed tag directly triggers `pypi-release.yml` via the
391
+ preserved `on: push: tags: ['v[0-9]+.[0-9]+.[0-9]+']` trigger. This
392
+ path is independent of `auto-tag.yml` and requires no `workflow_call`.
262
393
 
263
394
  ### Pre-release versions
264
395
 
@@ -292,6 +423,20 @@ The caller fires on merged PRs that touch story files, invokes the
292
423
  reusable `populate-story-acus.yml` workflow, and opens a follow-on PR
293
424
  with the populated ACU values.
294
425
 
426
+ ## Contributing
427
+
428
+ Framework evolution stories — new specs, CLI features, workflow improvements —
429
+ are filed as Markdown story files under [`docs/stories/`](docs/stories/).
430
+ See the [directory README](docs/stories/README.md) for the filing convention
431
+ (slug-named directories, frontmatter shape, `depends_on` hygiene). Stories
432
+ sync to the **METH** Jira project via the same sync workflow the framework
433
+ ships to adopters.
434
+
435
+ For the canonical story template and format spec, see
436
+ [`whiteout59/centralized-pipeline-ui/methodology/templates/story.md`](https://github.com/whiteout59/centralized-pipeline-ui/blob/main/methodology/templates/story.md)
437
+ and
438
+ [`whiteout59/centralized-pipeline-ui/methodology/devin-story-format.md`](https://github.com/whiteout59/centralized-pipeline-ui/blob/main/methodology/devin-story-format.md).
439
+
295
440
  ## Development
296
441
 
297
442
  ```bash