Skip to content

feat(bundles): first-party bugfix and assess bundles with bundled workflows - #4504

Open
markuswondrak wants to merge 3 commits into
github:mainfrom
markuswondrak:feat/4495-firstparty-bugfix-assess-bundles
Open

feat(bundles): first-party bugfix and assess bundles with bundled workflows#4504
markuswondrak wants to merge 3 commits into
github:mainfrom
markuswondrak:feat/4495-firstparty-bugfix-assess-bundles

Conversation

@markuswondrak

Copy link
Copy Markdown
Contributor

Summary

Implements #4495.

Adds two first-party bundles, each pairing its extension with a bundled workflow, following the layering agreed in #4461 (workflows live in the workflow layer, bundles compose them — no new contribution types):

  • bugfixbug extension + bugfix workflow: speckit.bug.assess → human review gate (reject aborts) → speckit.bug.fixspeckit.bug.test; inputs: report, slug
  • assessassess extension + assess workflow: intake → research → define → shape → decide → verdict review gate (workflow stops there; the /speckit.specify handoff stays manual); inputs: idea, slug

What's included

  • workflows/bugfix/workflow.yml and workflows/assess/workflow.yml, both registered in workflows/catalog.json (bundled: true) and force-included in the wheel's core_pack alongside speckit. Nothing is auto-installed at init.
  • bundles/bugfix/ and bundles/assess/ manifests (pinned versions, role developer) plus bundle READMEs.
  • bundles/catalog.json — repo-shipped first-party catalog, both entries verified: true.
  • builtin://default catalog wiring: resolves from bundles/catalog.json online and from the packaged wheel snapshot offline (mirrors the community catalog pattern). The previously empty stub is replaced by explicit URL/snapshot maps.
  • specify bundle add as an alias for specify bundle install.
  • Docs: docs/reference/bundles.md (first-party bundles + catalog sources), workflows/README.md (layout).

Acceptance criteria mapping

  • validate_workflow passes for both workflow YAMLs; steps/gates/inputs match the schema — tests/workflows/test_bundled_bugfix_assess_workflows.py
  • workflows/catalog.json entries match the bundled YAMLs' ids/versions/urls; contract test mirrors test_wheel_bundled_presets.pytests/contract/test_wheel_bundled_workflows.py and tests/contract/test_firstparty_bundle_catalog_consistency.py
  • specify bundle validate --path bundles/{bugfix,assess} --offline passes with zero unresolved references
  • specify bundle add bugfix|assess installs extension + workflow in a fresh project; workflow info shows the expected step graph (verified end-to-end with a locally simulated post-merge catalog, since the raw.githubusercontent URLs only resolve after merge)
  • specify bundle remove uninstalls only contributed components — an independently installed extension survives (FR-022, verified end-to-end)
  • ✅ Catalog pins match shipped extension/workflow versions — test_firstparty_manifest_pins_match_shipped_versions (drift-catching verified via mutation)
  • ✅ Docs updated
  • ✅ Existing behavior unchanged: ~2,000 relevant tests green (contract, unit, integration, workflows suites + test_workflows.py)

Out of scope (tracked in #4495)

Fully offline bundle install --offline — the bundle manifest still resolves via its catalog download_url (documented in docs/reference/bundles.md). Hosting of bundle artifacts resolves via the repository URLs, consistent with the community catalog.

AI Disclosure

This PR was authored with AI assistance. The implementation, tests, and review verification were generated by opencode (model: glm-5.3) acting autonomously under direction from @markuswondrak, who specified the task, reviewed the findings, and approved submission. The commit carries the corresponding Assisted-by: trailer.

… workflows

Implements github#4495.

Two first-party bundles pairing the bug and assess extensions with
orchestrated, resumable pipelines:

- workflows/bugfix: bug assess -> human review gate -> bug fix -> bug test
- workflows/assess: intake -> research -> define -> shape -> decide -> verdict
  review gate (specify handoff stays manual)

Both workflows are registered in workflows/catalog.json (bundled: true) and
force-included in the wheel's core_pack like speckit. The bundles live in
bundles/{bugfix,assess} and are listed in a new repo-shipped first-party
catalog bundles/catalog.json (verified: true).

The reserved builtin://default catalog source now resolves from that catalog —
online from the repository, offline from the packaged wheel snapshot — so
`specify bundle add bugfix|assess` resolves by id. Also adds `bundle add` as an
alias for `bundle install`.

Tests: workflow validation and structure guards, wheel force-include contract
(mirrors test_wheel_bundled_presets.py), first-party catalog/manifest/pin
consistency, and workflows/catalog.json <-> workflow.yml id/version/url
consistency.

Assisted-by: opencode (model: glm-5.3, autonomous)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Bundled workflow installation still accesses the network in offline local-bundle flows, and key workflow and alias contracts lack complete regression coverage.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds first-party bugfix and assess bundles that compose existing extensions with new bundled workflows.

Changes:

  • Adds, catalogs, and packages both workflows and bundle manifests.
  • Wires online and offline first-party catalog discovery.
  • Adds the bundle add alias, documentation, and contract tests.
File summaries
File Description
workflows/README.md Documents bundled workflow layout.
workflows/catalog.json Registers bundled workflows.
workflows/bugfix/workflow.yml Defines the bug-fix pipeline.
workflows/assess/workflow.yml Defines the assessment pipeline.
tests/workflows/test_bundled_bugfix_assess_workflows.py Tests workflow structure.
tests/unit/test_bundler_adapters.py Tests first-party catalog loading.
tests/integration/test_bundler_offline.py Tests offline catalog discovery.
tests/contract/test_wheel_bundled_workflows.py Verifies wheel inclusion.
tests/contract/test_firstparty_bundle_catalog_consistency.py Guards catalog and version consistency.
tests/contract/test_bundle_cli.py Updates catalog-aware CLI tests.
src/specify_cli/commands/bundle/__init__.py Adds the bundle add alias.
src/specify_cli/bundler/services/adapters.py Resolves first-party catalog sources.
pyproject.toml Packages catalogs and workflows.
docs/reference/bundles.md Documents first-party bundles.
bundles/catalog.json Defines the first-party bundle catalog.
bundles/bugfix/README.md Documents the bugfix bundle.
bundles/bugfix/bundle.yml Composes bug extension and workflow.
bundles/assess/README.md Documents the assess bundle.
bundles/assess/bundle.yml Composes assess extension and workflow.
Review details

Suppressed comments (2)

tests/workflows/test_bundled_bugfix_assess_workflows.py:57

  • This check accepts either primary input for both workflows, so bugfix could expose idea instead of report (or vice versa) and still pass. Parameterize the expected primary input per workflow and verify that it is required.
@pytest.mark.parametrize("workflow_id", ["bugfix", "assess"])
def test_bundled_workflow_has_required_inputs(workflow_id: str) -> None:
    definition = _load_workflow(workflow_id)
    assert "report" in definition.inputs or "idea" in definition.inputs

tests/workflows/test_bundled_bugfix_assess_workflows.py:38

  • As with the bugfix test, step IDs alone allow the assessment workflow to dispatch the wrong command or omit its slug/idea bindings without failing CI. Assert the command sequence and input arguments that define this pipeline.
    step_ids = [step["id"] for step in definition.steps]
  • Files reviewed: 19/19 changed files
  • Comments generated: 3
  • Review effort level: Balanced

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread pyproject.toml
Comment thread src/specify_cli/commands/bundle/__init__.py
Comment thread tests/workflows/test_bundled_bugfix_assess_workflows.py Outdated
Install bundled workflow components from their packaged workflow.yml instead
of falling through to the network-backed workflow catalog. Validate the bundled
workflow ID and the bundle's pinned version before delegating to the local
workflow install path.

Add coverage for offline first-party bundle installs, bundle add alias
execution, version pin rejection, and command/input workflow contracts.

Assisted-by: opencode (model: glm-5.3, autonomous)
Copilot AI review requested due to automatic review settings September 10, 2026 05:26
@markuswondrak

Copy link
Copy Markdown
Contributor Author

Posted on behalf of @markuswondrak by opencode (model: glm-5.3).

Addressed the Copilot review in commit 8a65f542:

  • Bundled workflow components now install from their packaged workflow.yml, validate their declared ID, and enforce the bundle version pin before using the established local workflow-install path. bundle install <local-manifest> --offline now succeeds for the full bugfix and assess bundles without catalog access.
  • Added bundle add help and installation-parity coverage.
  • Strengthened workflow contracts to assert every dispatched command, argument binding, integration binding, and each workflow's own required inputs.
  • Updated the offline-install documentation to distinguish local manifests from catalog-discovered bundle IDs.

Verification: 996 passed across contract/unit/integration/workflows; 983 passed, 1 skipped in tests/test_workflows.py.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The primary catalog-by-ID fresh-project flow lacks automated coverage, and several documentation and assertion-message issues remain.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (3)

Previously missed (3) — in code that hasn't changed since the last review.

bundles/assess/README.md:38

  • This sentence incorrectly implies both components are removed whenever no other bundle depends on them. An independently installed component is intentionally not attributed to this bundle and survives removal even with no other bundle dependency.
    bundles/bugfix/README.md:36
  • This sentence incorrectly implies both components are removed whenever no other bundle depends on them. An independently installed component is intentionally not attributed to this bundle and survives removal even with no other bundle dependency.
    tests/contract/test_firstparty_bundle_catalog_consistency.py:108
  • The second string is a separate no-op expression because the assertion message is not parenthesized, so failures end at “does not point at the” and omit the actionable expected location. Parenthesize the complete message.
  • Files reviewed: 21/21 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread tests/contract/test_bundle_cli.py
@mnriem mnriem added the triage-nice-to-have Verdict: evidence-backed fix or greenlit feature — land after review label Sep 10, 2026
@mnriem

mnriem commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

Thanks @markuswondrak — the shape here matches what we agreed in #4461, so I'm happy with the direction. Before I do the full architecture review of the builtin://default catalog + offline wheel-snapshot resolution and trigger CI, a few things to close out from the review:

  1. Cover the primary by-ID flow. The current contract test uses a local directory inside an already-created .specify project, so it bypasses catalog-ID resolution/download and fresh-project init — the advertised specify bundle add assess path could regress while it stays green. Please add a test from an empty directory that mocks the first-party catalog/manifest HTTP responses, invokes bundle add assess (and bugfix) by ID, and verifies the install.

  2. bundles/assess/README.md:38 and bundles/bugfix/README.md:36 — the wording implies both components are removed whenever no other bundle depends on them; an independently installed component isn't attributed to the bundle and should survive removal. Please correct.

  3. tests/contract/test_firstparty_bundle_catalog_consistency.py:108 — the assertion message isn't parenthesized, so the second line is a no-op and failures omit the expected location. Wrap the full message.

Once those are in, re-request a Copilot review and I'll take the architectural pass and kick off CI.

@mnriem mnriem added the author-awaiting Waiting on author response label Sep 10, 2026
- Correct README wording for bundle remove behavior (FR-022).
- Parenthesize full assertion message in first-party catalog consistency test.
- Add contract coverage for `bundle add <id>` from an empty directory,
  mocking first-party catalog/manifest HTTP responses and verifying
  fresh-project init plus bundled extension + workflow installation.

Assisted-by: opencode (model: kimi-k2.7-code, supervised)
Copilot AI review requested due to automatic review settings September 10, 2026 15:44
@markuswondrak

Copy link
Copy Markdown
Contributor Author

Posted on behalf of @markuswondrak by opencode (model: kimi-k2.7-code).

Addressed the remaining review findings in commit 9164b1c:

  • Added test_bundle_add_by_id_initializes_empty_project_from_firstparty_catalog, parametrized for bugfix and assess, that runs bundle add <id> from an empty directory while mocking the first-party catalog and manifest HTTP responses, and verifies fresh-project initialization plus extension + workflow installation.
  • Corrected the "Remove" wording in bundles/bugfix/README.md and bundles/assess/README.md to clarify that independently installed components survive bundle removal (FR-022).
  • Parenthesized the full assertion message in tests/contract/test_firstparty_bundle_catalog_consistency.py:104-108.

Verification: tests/unit (528 passed), tests/contract tests/integration tests/workflows tests/test_workflows.py (1453 passed, 1 skipped).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The change spans catalog resolution, packaging, offline installation, and workflow execution, warranting final human validation despite broad test coverage.

Review details
  • Files reviewed: 21/21 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@mnriem

mnriem commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

Thanks @markuswondrak — verified all four are addressed, including the empty-dir by-ID test and the online/offline builtin://default resolution coverage. Threads are clear. This is on me now: triggering CI and doing the full read of the catalog-resolution / packaging / offline path.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Both bundle READMEs show run commands that omit required inputs and therefore fail immediately.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 21/21 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread bundles/assess/README.md
Comment on lines +26 to +30
```bash
specify workflow run assess
```

You will be prompted for an idea and a slug. The slug is used as the working directory under `.specify/assessments/<slug>/` for all artifacts.
Comment thread bundles/bugfix/README.md
Comment on lines +24 to +28
```bash
specify workflow run bugfix
```

You will be prompted for a bug report and a slug. The slug is used as the working directory under `.specify/bugs/<slug>/` for all artifacts.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author-awaiting Waiting on author response triage-nice-to-have Verdict: evidence-backed fix or greenlit feature — land after review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants