Skip to content

fix(backlog): adopt safe artifact write policy (project-runtime-01)#248

Merged
djm81 merged 22 commits intomainfrom
dev
Apr 26, 2026
Merged

fix(backlog): adopt safe artifact write policy (project-runtime-01)#248
djm81 merged 22 commits intomainfrom
dev

Conversation

@djm81
Copy link
Copy Markdown
Contributor

@djm81 djm81 commented Apr 26, 2026

Summary

Adopts ownership-aware write safety for specfact-backlog external baseline files and .specfact config paths, paired with core change profile-04-safe-project-artifact-writes.

Refs:

  • related module migration item/change: OpenSpec project-runtime-01-safe-artifact-write-policy

Scope

  • Bundle source changes under packages/
  • Registry/manifest changes (registry/index.json, packages/*/module-package.yaml)
  • CI/workflow changes (.github/workflows/*)
  • Documentation changes (docs/*, README.md, AGENTS.md)
  • Security/signing changes (scripts/sign-modules.py, scripts/verify-modules-signature.py)

Bundle Impact

  • nold-ai/specfact-backlog: 0.41.17 -> 0.41.21

All other bundles: unchanged.

Changes

  • backlog sync: _prepare_baseline_write now runs before _fetch_current_graph, so an unprotected external baseline file blocks the command before any network call is made. External files outside .specfact require --force-baseline-overwrite; a timestamped backup is written to .specfact/recovery/ automatically.
  • backlog map-fields: Config updates preserve unrelated YAML sections instead of rewriting the whole file; invalid YAML in an existing mapping file exits cleanly rather than overwriting.
  • scripts/check-bundle-imports.py: _is_type_checking_guard now matches only bare TYPE_CHECKING or exactly typing.TYPE_CHECKING, rejecting lookalikes such as settings.TYPE_CHECKING.
  • scripts/pre_commit_code_review.py: Block 2 code review gate now passes --level error so warnings alone do not block commits.
  • Docs: backlog quickstart, delta, overview, custom field mapping, and README updated for first-time users.

Validation Evidence

Required local gates

  • hatch run format
  • hatch run type-check
  • hatch run lint
  • hatch run yaml-lint
  • hatch run check-bundle-imports
  • hatch run contract-test — 654 passed
  • hatch run smart-test — 654 passed

Signature + version integrity (required)

  • hatch run verify-modules-signature --payload-from-filesystem --enforce-version-bump passes (targets dev)
  • Changed bundle versions were bumped when module payloads changed (0.41.170.41.21)
  • Manifests signed by CI on approval for dev

Code review

  • hatch run specfact code review run --level error --json --out .specfact/code-review.changed.json --scope changed0 findings, 0 blocking on changed files
  • Full-repo run: 379 error-level findings, all pre-existing baseline debt unrelated to this change (see openspec/changes/project-runtime-01-safe-artifact-write-policy/TDD_EVIDENCE.md)

CI and Branch Protection

  • PR orchestrator jobs expected:
    • verify-module-signatures
    • sign-modules-on-approval (on approval, same-repo PRs to dev/main only)
    • quality (3.11)
    • quality (3.12)
    • quality (3.13)
  • Branch protection required checks are aligned with the above

Docs / Pages

  • Bundle/module docs updated in this repo (docs/)
  • Pages workflow impact reviewed — no workflow changes
  • Cross-links from specfact-cli docs updated (if applicable) — deferred; paired core PR handles the core-side narrative

Checklist

  • Self-review completed
  • No unrelated files or generated artifacts included
  • Backward-compatibility/rollout notes documented (if needed) — no breaking changes; --force-baseline-overwrite is additive

omit-test and others added 9 commits April 26, 2026 23:26
Integrate core safe-write helper into specfact-backlog sync and add commands
so persistent user-project artifacts are never silently overwritten. Adds
TYPE_CHECKING-aware re-exports for BacklogAdapter and BacklogFilters, fixes
the import boundary checker to skip TYPE_CHECKING blocks, compacts the daily
command signature to meet the LOC gate, and bumps specfact-backlog to 0.41.19.

Also sets --level error on the pre-commit code review gate so the hook fails
only on error-severity findings, not advisory warnings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- check-bundle-imports: traverse orelse branch of TYPE_CHECKING guards so
  runtime imports in else-clauses are still scanned (P1 bug fix)
- commands.py: infer GitHub provider from github_project_id/v2_id/type_field_id
  hints before falling through to ADO in _normalize_map_field_providers (P2)
- sync.py: run _prepare_baseline_write before _fetch_current_graph so the
  command exits early when overwrite is blocked instead of doing a network call
  first
- test_sync_command.py: assert backup file content equals original baseline
- tutorial-backlog-quickstart-demo.md: remove stale .nold-ai config path line
- tasks.md: drop --require-signature from pre-merge gate; add --level error to
  code review command
- TDD_EVIDENCE.md: update version trail to reflect final shipped version 0.41.20
- specfact-backlog: bump to 0.41.20

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Narrow _is_type_checking_guard to only match bare TYPE_CHECKING or
  typing.TYPE_CHECKING, rejecting settings.TYPE_CHECKING and similar
- Re-run code review with --level error per tasks.md requirement and
  record updated timestamps/counts in TDD_EVIDENCE.md (0 error findings
  on changed scope, 379 on full repo baseline debt)
- Bump specfact-backlog to 0.41.21

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rtifact-write-policy

feat(backlog): adopt safe artifact write policy (project-runtime-01)
chore(registry): publish changed modules
@cursor
Copy link
Copy Markdown

cursor Bot commented Apr 26, 2026

PR Summary

Medium Risk
Changes specfact-backlog file-write behavior (baseline backups/overwrite blocking and config/mapping preservation), which can affect sync/map-fields workflows and users’ on-disk state if edge cases exist. Most changes are additive safety checks plus docs/manifest updates, but they touch user-facing CLI behavior.

Overview
Backlog bundle now enforces ownership-aware local writes. backlog sync blocks overwriting an existing baseline file outside .specfact unless --force-baseline-overwrite is provided, and creates a timestamped backup under .specfact/recovery/ before proceeding.

Config/mapping updates are documented as merge-preserving. Docs and OpenSpec artifacts are updated to treat .specfact/ as the canonical home for backlog runtime state, clarify preservation/“fail safe” behavior for .specfact/backlog-config.yaml and .specfact/templates/backlog/field_mappings/ado_custom.yaml, and describe the external-baseline overwrite rule.

Release hygiene updates. Bumps nold-ai/specfact-backlog to 0.41.21 with updated integrity fields, and adjusts the backlog adapter re-export to use a TYPE_CHECKING import guard.

Reviewed by Cursor Bugbot for commit d5e0f68. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 26, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: cfa64224-91c8-42f0-8eeb-4304c1a60a5c

📥 Commits

Reviewing files that changed from the base of the PR and between d5e0f68 and 7764bfd.

⛔ Files ignored due to path filters (2)
  • registry/modules/specfact-backlog-0.41.23.tar.gz is excluded by !**/*.gz
  • registry/modules/specfact-backlog-0.41.24.tar.gz is excluded by !**/*.gz
📒 Files selected for processing (13)
  • docs/guides/custom-field-mapping.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/TDD_EVIDENCE.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/proposal.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/runtime-artifact-write-safety/spec.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/tasks.md
  • packages/specfact-backlog/module-package.yaml
  • packages/specfact-backlog/src/specfact_backlog/backlog/commands.py
  • registry/index.json
  • registry/modules/specfact-backlog-0.41.23.tar.gz.sha256
  • registry/modules/specfact-backlog-0.41.24.tar.gz.sha256
  • registry/signatures/specfact-backlog-0.41.23.tar.sig
  • registry/signatures/specfact-backlog-0.41.24.tar.sig
  • tests/unit/specfact_backlog/test_map_fields_command.py
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: quality (3.11)
  • GitHub Check: quality (3.12)
  • GitHub Check: quality (3.13)
🧰 Additional context used
📓 Path-based instructions (6)
registry/**

⚙️ CodeRabbit configuration file

registry/**: Registry and index consistency: bundle listings, version pins, and compatibility with
published module artifacts.

Files:

  • registry/signatures/specfact-backlog-0.41.24.tar.sig
  • registry/signatures/specfact-backlog-0.41.23.tar.sig
  • registry/modules/specfact-backlog-0.41.23.tar.gz.sha256
  • registry/modules/specfact-backlog-0.41.24.tar.gz.sha256
  • registry/index.json
packages/**/module-package.yaml

⚙️ CodeRabbit configuration file

packages/**/module-package.yaml: Validate metadata: name, version, commands, dependencies, and parity with packaged src.
Call out semver and signing implications when manifests or payloads change.

Files:

  • packages/specfact-backlog/module-package.yaml
openspec/**/*.md

⚙️ CodeRabbit configuration file

openspec/**/*.md: Specification truth: proposal/tasks/spec deltas vs. bundle behavior, CHANGE_ORDER, and
drift vs. shipped modules or docs.

Files:

  • openspec/changes/project-runtime-01-safe-artifact-write-policy/TDD_EVIDENCE.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/runtime-artifact-write-safety/spec.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/tasks.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/proposal.md
docs/**/*.md

⚙️ CodeRabbit configuration file

docs/**/*.md: User-facing and cross-site accuracy: Jekyll front matter, links per documentation-url-contract,
CLI examples matching bundled commands.

Files:

  • docs/guides/custom-field-mapping.md
**/*.{js,ts,tsx,jsx,py,java,cs,go,rb,php,cpp,c,h}

📄 CodeRabbit inference engine (CLAUDE.md)

Preserve the clean-code compliance gate and its category references (naming, kiss, yagni, dry, and solid)

Files:

  • tests/unit/specfact_backlog/test_map_fields_command.py
tests/**/*.py

⚙️ CodeRabbit configuration file

tests/**/*.py: Contract-first and integration tests: migration suites, bundle validation, and flakiness.
Ensure changes to adapters or bridges have targeted coverage.

Files:

  • tests/unit/specfact_backlog/test_map_fields_command.py
🧠 Learnings (11)
📓 Common learnings
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-13T10:38:29.399Z
Learning: When a change is paired with work in specfact-cli, review the paired public change artifacts there before widening scope or redefining shared workflow semantics
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.848Z
Learning: This repository enforces the clean-code review gate through hatch run specfact code review run --json --out .specfact/code-review.json
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.848Z
Learning: Work belongs on feature/*, bugfix/*, hotfix/*, or chore/* branches, normally in a worktree rooted under ../specfact-cli-modules-worktrees/
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-13T10:38:15.855Z
Learning: Adhere to worktree policy, OpenSpec gating, GitHub hierarchy-cache refresh, TDD order, quality gates, versioning, and documentation rules as defined in `docs/agent-rules/`
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.848Z
Learning: Refresh .specfact/backlog/github_hierarchy_cache.md with python scripts/sync_github_hierarchy_cache.py when GitHub hierarchy metadata is missing or stale before parent or blocker work
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.535Z
Learning: Fix SpecFact code review findings, including warnings, unless a rare explicit exception is documented
📚 Learning: 2026-04-02T21:49:07.435Z
Learnt from: djm81
Repo: nold-ai/specfact-cli-modules PR: 136
File: registry/modules/specfact-spec-0.40.17.tar.gz.sha256:1-1
Timestamp: 2026-04-02T21:49:07.435Z
Learning: In nold-ai/specfact-cli-modules, module tarball signature files under registry/signatures/*.tar.sig are produced by the publish-modules GitHub Actions runner during the publish workflow (not committed to the branch). During PR pre-merge review, do not flag missing *.tar.sig files as blockers; treat signatures as publish-time artifacts.

Applied to files:

  • registry/signatures/specfact-backlog-0.41.24.tar.sig
  • registry/signatures/specfact-backlog-0.41.23.tar.sig
📚 Learning: 2026-04-02T21:49:11.371Z
Learnt from: djm81
Repo: nold-ai/specfact-cli-modules PR: 136
File: registry/modules/specfact-spec-0.40.17.tar.gz.sha256:1-1
Timestamp: 2026-04-02T21:49:11.371Z
Learning: In nold-ai/specfact-cli-modules, module tarball signatures (registry/signatures/*.tar.sig) are generated by the `publish-modules` GitHub Actions runner during the publish workflow, not committed locally to the branch. Missing signature files should NOT be flagged as a pre-merge blocker in PRs.

Applied to files:

  • registry/modules/specfact-backlog-0.41.23.tar.gz.sha256
  • registry/modules/specfact-backlog-0.41.24.tar.gz.sha256
  • registry/index.json
  • packages/specfact-backlog/module-package.yaml
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/TDD_EVIDENCE.md
📚 Learning: 2026-04-13T10:38:22.848Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.848Z
Learning: Signed module or manifest changes require version-bump review and verify-modules-signature

Applied to files:

  • packages/specfact-backlog/module-package.yaml
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/TDD_EVIDENCE.md
📚 Learning: 2026-04-13T10:38:43.535Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.535Z
Learning: Perform `spec -> tests -> failing evidence -> code -> passing evidence` in that order for behavior changes

Applied to files:

  • openspec/changes/project-runtime-01-safe-artifact-write-policy/TDD_EVIDENCE.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/tasks.md
📚 Learning: 2026-04-13T10:38:29.399Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-13T10:38:29.399Z
Learning: When a change is paired with work in specfact-cli, review the paired public change artifacts there before widening scope or redefining shared workflow semantics

Applied to files:

  • openspec/changes/project-runtime-01-safe-artifact-write-policy/TDD_EVIDENCE.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/runtime-artifact-write-safety/spec.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/tasks.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/proposal.md
📚 Learning: 2026-04-13T10:38:22.848Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.848Z
Learning: This repository enforces the clean-code review gate through hatch run specfact code review run --json --out .specfact/code-review.json

Applied to files:

  • openspec/changes/project-runtime-01-safe-artifact-write-policy/TDD_EVIDENCE.md
📚 Learning: 2026-04-13T10:38:43.535Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.535Z
Learning: Fix SpecFact code review findings, including warnings, unless a rare explicit exception is documented

Applied to files:

  • openspec/changes/project-runtime-01-safe-artifact-write-policy/TDD_EVIDENCE.md
  • docs/guides/custom-field-mapping.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/runtime-artifact-write-safety/spec.md
📚 Learning: 2026-04-13T10:38:15.855Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-13T10:38:15.855Z
Learning: Adhere to worktree policy, OpenSpec gating, GitHub hierarchy-cache refresh, TDD order, quality gates, versioning, and documentation rules as defined in `docs/agent-rules/`

Applied to files:

  • openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/runtime-artifact-write-safety/spec.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/tasks.md
📚 Learning: 2026-04-13T10:38:22.848Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.848Z
Learning: Work belongs on feature/*, bugfix/*, hotfix/*, or chore/* branches, normally in a worktree rooted under ../specfact-cli-modules-worktrees/

Applied to files:

  • openspec/changes/project-runtime-01-safe-artifact-write-policy/tasks.md
📚 Learning: 2026-04-13T10:38:43.535Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.535Z
Learning: Require public GitHub metadata completeness before implementation when linked issue workflow applies: parent, labels, project assignment, blockers, and blocked-by relationships

Applied to files:

  • openspec/changes/project-runtime-01-safe-artifact-write-policy/tasks.md
🪛 LanguageTool
openspec/changes/project-runtime-01-safe-artifact-write-policy/proposal.md

[style] ~11-~11: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...d generic modules-side abstraction. - NEW: Define .specfact ownership classes...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

🔀 Multi-repo context nold-ai/specfact-cli

nold-ai/specfact-cli

Findings:

  • BacklogAdapter (core contract) is widely consumed across the repo:

    • src/specfact_cli/backlog/adapters/base.py defines BacklogAdapter and is imported/used by adapters and tests (e.g. src/specfact_cli/adapters/github.py, src/specfact_cli/adapters/ado.py, tests/unit/adapters/*). [::nold-ai/specfact-cli::src/specfact_cli/backlog/adapters/base.py]
    • Tests create MagicMock(spec=BacklogAdapter) and assert adapter instances isinstance(..., BacklogAdapter) (tests/unit/commands/test_backlog_daily.py, tests/unit/adapters/*). [::nold-ai/specfact-cli::tests/unit/commands/test_backlog_daily.py] [::nold-ai/specfact-cli::tests/unit/adapters/test_github_backlog_adapter.py]
  • BacklogFilters is heavily used:

    • Declaration and primary use sites: src/specfact_cli/backlog/filters.py and many consumers in adapters and tests (github/ado adapters and numerous unit tests). Changing its import/export semantics affects static typing and many call sites. [::nold-ai/specfact-cli::src/specfact_cli/backlog/filters.py] [::nold-ai/specfact-cli::src/specfact_cli/adapters/github.py] [::nold-ai/specfact-cli::src/specfact_cli/adapters/ado.py] [::nold-ai/specfact-cli::tests/unit/backlog/test_filter_normalization.py]
  • --force-baseline-overwrite / force_baseline_overwrite token:

    • Ripgrep found no other occurrences in the repo beyond the changed sync implementation and its tests (no global callers discovered). This suggests the new flag is local to the backlog sync CLI and tested only by tests in the same package. [::nold-ai/specfact-cli::tests/unit/specfact_backlog/test_sync_command.py] (search returned no other matches)
  • TYPE_CHECKING guards are widely present:

    • Many modules use "if TYPE_CHECKING:" (commands, contracts, analyzers, etc.). The scripts/check-bundle-imports.py change to recognize only bare TYPE_CHECKING/typing.TYPE_CHECKING is relevant because static import-scanning interacts with many files that use TYPE_CHECKING blocks. Tests referencing TYPE_CHECKING exist (tests/unit/test_core_module_isolation.py). [::nold-ai/specfact-cli::src/specfact_cli/commands/sync.py] [::nold-ai/specfact-cli::tests/unit/test_core_module_isolation.py]

Potential impact / reviewers' attention areas (grounded in repo findings):

  • BacklogAdapter / BacklogFilters re-export or conditional TYPE_CHECKING import changes affect static typing and CI import-boundary checks; verify adapters that are expected to satisfy the core BacklogAdapter type remain compatible at runtime and under type-checking. [::nold-ai/specfact-cli::src/specfact_cli/backlog/adapters/base.py] [::nold-ai/specfact-cli::src/specfact_cli/backlog/filters.py]
  • The new --force-baseline-overwrite flag appears additive and only exercised by local tests; ensure consumers/scripts that may call sync (external automation) are updated if they expect prior overwrite behavior. No external callers found in this repo. [::nold-ai/specfact-cli::tests/unit/specfact_backlog/test_sync_command.py]
  • The stricter TYPE_CHECKING detection in the import-check script may change which imports are allowed/flagged in CI — run the bundling/static checks to confirm no unintended imports are now excluded/included. [::nold-ai/specfact-cli::tests/unit/test_core_module_isolation.py]

Conclusion: All relevant consumers and references are inside this repository; no cross-repo references discovered.

🔇 Additional comments (11)
registry/modules/specfact-backlog-0.41.24.tar.gz.sha256 (1)

1-1: Checksum artifact is consistent with the registry pointer.

The 0.41.24 SHA-256 value is well-formed and aligns with the updated backlog module entry.

docs/guides/custom-field-mapping.md (1)

196-197: Safe-failure wording is now correct and policy-aligned.

This phrasing clearly communicates non-mutation behavior for invalid YAML while keeping the command/path context precise.

registry/signatures/specfact-backlog-0.41.24.tar.sig (1)

1-1: Signature artifact aligns with the 0.41.24 integrity metadata.

Good consistency between the versioned signature file and manifest-level signature reference.

registry/modules/specfact-backlog-0.41.23.tar.gz.sha256 (1)

1-1: Versioned checksum artifact is well-formed.

The added 0.41.23 checksum entry is syntactically clean and follows registry artifact conventions.

registry/signatures/specfact-backlog-0.41.23.tar.sig (1)

1-1: Versioned signature artifact format looks correct.

The new 0.41.23 signature file follows expected registry signature structure.

registry/index.json (1)

19-21: Registry latest pointer update is coherent.

latest_version, download_url, and checksum_sha256 are synchronized for nold-ai/specfact-backlog 0.41.24.

packages/specfact-backlog/module-package.yaml (1)

2-2: Manifest version and integrity metadata are in sync with release artifacts.

The 0.41.24 bump and refreshed integrity block are consistent with the registry/index and signature updates.

Also applies to: 30-31

tests/unit/specfact_backlog/test_map_fields_command.py (1)

646-760: Great coverage for ownership-safe merge behavior and fail-safe handling.

The shared ADO setup helper reduces repetition, and the new tests precisely validate preserved user sections plus non-mutation on invalid existing YAML.

openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/runtime-artifact-write-safety/spec.md (1)

3-30: Spec boundary and ownership semantics are correctly tightened.

This requirement/scenario set is consistent with the backlog-first adoption and clearly separates external user-owned writes from .specfact managed writes, including merge-preserve and fail-safe behavior.

openspec/changes/project-runtime-01-safe-artifact-write-policy/proposal.md (1)

9-31: Scope and cross-boundary contract language looks correct.

The proposal now cleanly documents backlog-scoped adoption and preserves the adapter boundary with the paired core contract for sanctioned external paths only.

openspec/changes/project-runtime-01-safe-artifact-write-policy/tasks.md (1)

22-26: Verification/governance checklist is now aligned and actionable.

Gate order, signature verification constraints, and error-level review execution are documented in a merge-ready sequence.


📝 Walkthrough

PR #248: Safe Artifact Write Policy Adoption for specfact-backlog

Bundle & Command Surface

Behavioral changes to backlog module runtime:

  • sync command gains --force-baseline-overwrite flag (bool, default False) to explicitly permit external baseline file replacement

    • New pre-fetch safety check: _prepare_baseline_write() runs before _fetch_current_graph(), detecting external baseline files (outside .specfact/) and raising typer.Exit(1) unless flag is set
    • External baselines receiving --force-baseline-overwrite trigger timestamped backup creation in .specfact/recovery/ using sanitized filename pattern ({safe_name}.{YYYYMMDDTHHmmss.ffffffZ}.{suffix}.bak)
    • Internal .specfact/backlog-baseline.json writes proceed without safety prompts (treated as fully-owned managed state)
  • map-fields command (backlog bundle)

    • Now preserves unrelated top-level YAML keys when updating .specfact/backlog-config.yaml and .specfact/templates/backlog/field_mappings/ado_custom.yaml
    • Safe failure mode: invalid YAML in existing config causes exit with non-zero code and leaves file unchanged (no overwrites)

Module-to-CLI API surface:

  • Continues using existing specfact_cli contracts: AdapterRegistry.get_adapter(), BacklogItem, BacklogGraph, BacklogGraphBuilder
  • Schema extensions unchanged: project_bundle.backlog_core.backlog_graph and project_metadata.backlog_core.backlog_config
  • No breaking changes to command signatures or exported model shapes

Module Versions & Integrity

  • Version: 0.41.17 → 0.41.24

    • Intermediate releases (0.41.21, 0.41.23) tracked in registry with individual checksums and signatures
  • Manifest updates:

    • packages/specfact-backlog/module-package.yaml: version field and integrity.{checksum,signature} replaced with new values
    • registry/index.json: entry for nold-ai/specfact-backlog updated to latest_version: 0.41.24 with corresponding download_url and checksum_sha256
    • Registry artifact checksums and signatures added for each released version (.sha256 and .tar.sig files)

Import & Type-Checking Alignment

  • Conditional type-checking imports introduced:

    • BacklogFilters (in backlog/filters.py) and BacklogAdapter (in backlog/adapters/interface.py) now use if TYPE_CHECKING: for static imports, with runtime dynamic loading via import_module()
    • No signature or shape changes; only import resolution method shifts
  • Cross-bundle import validation tightened:

    • scripts/check-bundle-imports.py now properly recognizes if TYPE_CHECKING: guard blocks and excludes their contents from boundary-violation reports
    • Type-checking matcher is strict: only bare TYPE_CHECKING or typing.TYPE_CHECKING accepted (rejects partial matches or unrelated names)
    • Enables cleaner type-checking-only imports without false positive boundary violations

CI & Pre-commit Gate Changes

  • scripts/pre_commit_code_review.py: passes --level error flag to specfact code review run invocation
    • Constrains gate findings to error-level only; warnings no longer block commits
    • JSON report and gate exit-code behavior preserved

Validation & Contract Tests

  • TDD evidence records:
    • Unit test runs for map_fields and sync behaviors (preservation, safe failure, forced overwrite with backup)
    • Contract tests (654 passed) and smart tests (654 passed)
    • SpecFact code review run on changed files: 0 findings at error level
    • verify-modules-signature runs with enforced version bump verification

Documentation Updates

  • File location contracts migrated from .nold-ai/specfact-backlog-config.yaml.specfact/backlog-config.yaml across all docs
  • Ownership model clarified: .specfact/ artifacts (config, baseline, plans) are SpecFact-managed and subject to merge/preserve behavior; external user-provided baselines require explicit --force-baseline-overwrite flag
  • New TDD evidence documentation and updated design/proposal specs anchoring scope to backlog bundle and sanctioned external artifacts
  • Custom field mapping preservation behavior documented in docs/guides/custom-field-mapping.md

Deferred Changes

  • CI/workflow integration and module-signing scripts not fully updated (noted as out of scope for this PR)
  • Broader generic runtime safe-write framework deferred pending core API expansion

Walkthrough

This PR narrows the safe-artifact-write policy to treat .specfact/ as SpecFact-managed while external files are user-owned, updates docs to reference .specfact/backlog-* paths, adds --force-baseline-overwrite with timestamped backups under .specfact/recovery/ to the sync command, gates type-only imports with TYPE_CHECKING, tweaks pre-commit SpecFact invocation to --level error, adds tests, and bumps the specfact-backlog package and registry entries (to 0.41.24).

Changes

Cohort / File(s) Summary
Docs & Guides
README.md, docs/bundles/backlog/overview.md, docs/bundles/backlog/delta.md, docs/getting-started/tutorial-backlog-quickstart-demo.md, docs/guides/custom-field-mapping.md
Restructure README; standardize backlog config/baseline locations to .specfact/*; document ownership semantics and merge/preserve behavior and safe-failure rules.
OpenSpec / Design
openspec/changes/project-runtime-01-safe-artifact-write-policy/...
Refines safe-write policy scope to .specfact ownership model; narrows adopter paths to backlog-related files; updates tasks, proposal, design, specs, and TDD evidence.
CLI: sync command
packages/specfact-backlog/src/specfact_backlog/backlog_core/commands/sync.py
Adds --force-baseline-overwrite option; if external baseline exists and flag not set, CLI aborts with message; if set, creates sanitized timestamped backup under .specfact/recovery/ and proceeds to overwrite.
Type-checking import guards
packages/specfact-backlog/src/specfact_backlog/backlog/adapters/interface.py, packages/specfact-backlog/src/specfact_backlog/backlog/filters.py
Change runtime import resolution to preserve dynamic behavior while importing concrete types under if TYPE_CHECKING: for static analysis; exported symbols unchanged.
Import-check script
scripts/check-bundle-imports.py
Exclude imports inside if TYPE_CHECKING: / typing.TYPE_CHECKING blocks from import-collection to avoid false positives.
Pre-commit gate
scripts/pre_commit_code_review.py
Passes --level error to SpecFact code-review invocation to limit findings processed to error-level while preserving JSON output and exit behavior.
Tests
tests/unit/specfact_backlog/test_map_fields_command.py, tests/unit/specfact_backlog/test_sync_command.py, tests/unit/specfact_backlog/test_refine_adapter_contract.py
Add/adjust tests covering map-fields preservation and invalid YAML safety; sync backup/force behavior; and adapter contract invocation pattern.
Package & Registry
packages/specfact-backlog/module-package.yaml, registry/index.json, registry/modules/specfact-backlog-*.sha256, registry/signatures/specfact-backlog-*.tar.sig
Bump specfact-backlog package version and refresh integrity checksum/signature files and registry entries to reference the new release artifacts (notably 0.41.24).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related issues

Possibly related PRs

Suggested labels

module, documentation

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'fix(backlog): adopt safe artifact write policy (project-runtime-01)' follows Conventional Commits format with a clear 'fix' prefix, includes the affected component, and accurately describes the main change.
Description check ✅ Passed The PR description follows the template structure with all major sections completed: Summary with refs, Scope checkboxes, Bundle Impact, Changes, Validation Evidence with local gates, signature verification, code review results, CI/Branch Protection confirmation, Docs updates, and final Checklist all checked and filled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Comment @coderabbitai help to get the list of available commands and usage tips.

@djm81 djm81 self-assigned this Apr 26, 2026
@djm81 djm81 added bug Something isn't working enhancement New feature or request codebase Specfact codebase related topic labels Apr 26, 2026
@djm81 djm81 moved this from Todo to In Progress in SpecFact CLI Apr 26, 2026
@djm81 djm81 linked an issue Apr 26, 2026 that may be closed by this pull request
4 tasks
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6d6523ab53

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/specfact-backlog/src/specfact_backlog/backlog/commands.py
Comment thread packages/specfact-backlog/src/specfact_backlog/backlog/commands.py Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/unit/specfact_backlog/test_map_fields_command.py (1)

646-847: 🧹 Nitpick | 🔵 Trivial

Consider extracting shared map-fields test scaffolding.

Line 646 onward repeats near-identical payload stubs, fake_get branching, and CLI invocation arguments across multiple tests. A small helper/fixture would reduce drift and keep each test focused on its contract assertion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/specfact_backlog/test_map_fields_command.py` around lines 646 -
847, The three map-fields tests repeat identical payloads, fake_get logic and
the runner.invoke arguments; extract a shared helper (e.g., a function or pytest
fixture like prepare_map_fields or make_map_fields_test_context) that sets up
fields_payload, work_item_types_payload, work_item_type_fields_payload,
registers the fake_get (referencing the fake_get branching used in the tests),
and returns the common CLI args list and any paths (mapping_path/config_dir)
needed by each test; then update
test_map_fields_preserves_unrelated_backlog_config_sections,
test_map_fields_preserves_unrelated_custom_mapping_sections, and
test_map_fields_fails_safe_when_custom_mapping_file_is_invalid to call that
helper, reuse the returned args with runner.invoke(backlog_app, args), and only
keep the assertions and the test-specific file setup/teardown in each test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/guides/custom-field-mapping.md`:
- Around line 196-197: Update the user-facing sentence that reads "If the file
is not a valid YAML mapping, the command fails safe and leaves the file
unchanged." to use the correct phrasing "fails safely" so it reads "If the file
is not a valid YAML mapping, the command fails safely and leaves the file
unchanged."; ensure the change is applied in the same sentence that references
the CLI command `specfact backlog map-fields` and the path
`.specfact/templates/backlog/field_mappings/ado_custom.yaml`.

In `@openspec/changes/project-runtime-01-safe-artifact-write-policy/proposal.md`:
- Line 17: Add a blank line after the markdown subheadings "### New
Capabilities" and "### Modified Capabilities" so list items follow the headings
on their own paragraph (fix MD022); locate the headings in proposal.md and
insert a single empty line immediately after each of the two headings to ensure
proper Markdown linting.

In
`@openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/runtime-artifact-write-safety/spec.md`:
- Line 3: Several Markdown headings in the spec (e.g., "Requirement: Bundle
runtime commands SHALL distinguish sanctioned external artifacts from
SpecFact-managed artifacts" and the other similar headings referenced) are
missing the required blank line after the heading; add a single blank line
immediately following each heading so the document complies with MD022 (apply
the same fix to the other headings noted in the comment).

In `@openspec/changes/project-runtime-01-safe-artifact-write-policy/tasks.md`:
- Line 26: Complete checklist item 4.5 by opening the modules PR to the dev
branch, add a clear cross-link to the paired core PR that contains the
external-path contract (reference the core PR number/URL in the PR description),
and add a short "deferred follow-up" note stating whether a broader generic
runtime safe-write change is required and who/which core work item will track it
so merge readiness governance is satisfied.

In
`@openspec/changes/project-runtime-01-safe-artifact-write-policy/TDD_EVIDENCE.md`:
- Around line 25-33: Update the TDD_EVIDENCE.md entry to include the final
signing and verification commands and timestamps for the shipped backlog version
0.41.21: run the same two commands shown (the sign script: `hatch run python
scripts/sign-modules.py --allow-unsigned --payload-from-filesystem
packages/specfact-backlog/module-package.yaml` and the verifier: `hatch run
verify-modules-signature --payload-from-filesystem --enforce-version-bump`),
capture their exact timestamps and outcomes (e.g., "Result: passed (Verified X
module manifest(s).)" or any error text) and append them in the same
bullet-format used for 0.41.20 so the file records both sign and verify evidence
for version 0.41.21 and matches the actual payload in
packages/specfact-backlog/module-package.yaml.

---

Outside diff comments:
In `@tests/unit/specfact_backlog/test_map_fields_command.py`:
- Around line 646-847: The three map-fields tests repeat identical payloads,
fake_get logic and the runner.invoke arguments; extract a shared helper (e.g., a
function or pytest fixture like prepare_map_fields or
make_map_fields_test_context) that sets up fields_payload,
work_item_types_payload, work_item_type_fields_payload, registers the fake_get
(referencing the fake_get branching used in the tests), and returns the common
CLI args list and any paths (mapping_path/config_dir) needed by each test; then
update test_map_fields_preserves_unrelated_backlog_config_sections,
test_map_fields_preserves_unrelated_custom_mapping_sections, and
test_map_fields_fails_safe_when_custom_mapping_file_is_invalid to call that
helper, reuse the returned args with runner.invoke(backlog_app, args), and only
keep the assertions and the test-specific file setup/teardown in each test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6de4b792-aaab-4c00-8d9a-f3a89b722047

📥 Commits

Reviewing files that changed from the base of the PR and between a5f24e7 and d5e0f68.

⛔ Files ignored due to path filters (1)
  • registry/modules/specfact-backlog-0.41.21.tar.gz is excluded by !**/*.gz
📒 Files selected for processing (25)
  • README.md
  • docs/bundles/backlog/delta.md
  • docs/bundles/backlog/overview.md
  • docs/getting-started/tutorial-backlog-quickstart-demo.md
  • docs/guides/custom-field-mapping.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/TDD_EVIDENCE.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/design.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/proposal.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/backlog-add/spec.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/backlog-sync/spec.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/runtime-artifact-write-safety/spec.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/tasks.md
  • packages/specfact-backlog/module-package.yaml
  • packages/specfact-backlog/src/specfact_backlog/backlog/adapters/interface.py
  • packages/specfact-backlog/src/specfact_backlog/backlog/commands.py
  • packages/specfact-backlog/src/specfact_backlog/backlog/filters.py
  • packages/specfact-backlog/src/specfact_backlog/backlog_core/commands/sync.py
  • registry/index.json
  • registry/modules/specfact-backlog-0.41.21.tar.gz.sha256
  • registry/signatures/specfact-backlog-0.41.21.tar.sig
  • scripts/check-bundle-imports.py
  • scripts/pre_commit_code_review.py
  • tests/unit/specfact_backlog/test_map_fields_command.py
  • tests/unit/specfact_backlog/test_refine_adapter_contract.py
  • tests/unit/specfact_backlog/test_sync_command.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (8)
registry/**

⚙️ CodeRabbit configuration file

registry/**: Registry and index consistency: bundle listings, version pins, and compatibility with
published module artifacts.

Files:

  • registry/modules/specfact-backlog-0.41.21.tar.gz.sha256
  • registry/signatures/specfact-backlog-0.41.21.tar.sig
  • registry/index.json
**/*.{js,ts,tsx,jsx,py,java,cs,go,rb,php,cpp,c,h}

📄 CodeRabbit inference engine (CLAUDE.md)

Preserve the clean-code compliance gate and its category references (naming, kiss, yagni, dry, and solid)

Files:

  • scripts/pre_commit_code_review.py
  • packages/specfact-backlog/src/specfact_backlog/backlog/adapters/interface.py
  • scripts/check-bundle-imports.py
  • tests/unit/specfact_backlog/test_refine_adapter_contract.py
  • packages/specfact-backlog/src/specfact_backlog/backlog/filters.py
  • tests/unit/specfact_backlog/test_sync_command.py
  • tests/unit/specfact_backlog/test_map_fields_command.py
  • packages/specfact-backlog/src/specfact_backlog/backlog_core/commands/sync.py
scripts/**/*.py

⚙️ CodeRabbit configuration file

scripts/**/*.py: Deterministic tooling: signing, publishing, docs generation; subprocess and path safety.

Files:

  • scripts/pre_commit_code_review.py
  • scripts/check-bundle-imports.py
packages/**/src/**/*.py

⚙️ CodeRabbit configuration file

packages/**/src/**/*.py: Focus on adapter and bridge patterns: imports from specfact_cli (models, runtime, validators),
Typer/Rich command surfaces, and clear boundaries so core upgrades do not silently break bundles.
Flag breaking assumptions about registry loading, lazy imports, and environment/mode behavior.

Files:

  • packages/specfact-backlog/src/specfact_backlog/backlog/adapters/interface.py
  • packages/specfact-backlog/src/specfact_backlog/backlog/filters.py
  • packages/specfact-backlog/src/specfact_backlog/backlog_core/commands/sync.py
openspec/**/*.md

⚙️ CodeRabbit configuration file

openspec/**/*.md: Specification truth: proposal/tasks/spec deltas vs. bundle behavior, CHANGE_ORDER, and
drift vs. shipped modules or docs.

Files:

  • openspec/changes/project-runtime-01-safe-artifact-write-policy/TDD_EVIDENCE.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/backlog-sync/spec.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/backlog-add/spec.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/runtime-artifact-write-safety/spec.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/proposal.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/tasks.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/design.md
packages/**/module-package.yaml

⚙️ CodeRabbit configuration file

packages/**/module-package.yaml: Validate metadata: name, version, commands, dependencies, and parity with packaged src.
Call out semver and signing implications when manifests or payloads change.

Files:

  • packages/specfact-backlog/module-package.yaml
tests/**/*.py

⚙️ CodeRabbit configuration file

tests/**/*.py: Contract-first and integration tests: migration suites, bundle validation, and flakiness.
Ensure changes to adapters or bridges have targeted coverage.

Files:

  • tests/unit/specfact_backlog/test_refine_adapter_contract.py
  • tests/unit/specfact_backlog/test_sync_command.py
  • tests/unit/specfact_backlog/test_map_fields_command.py
docs/**/*.md

⚙️ CodeRabbit configuration file

docs/**/*.md: User-facing and cross-site accuracy: Jekyll front matter, links per documentation-url-contract,
CLI examples matching bundled commands.

Files:

  • docs/bundles/backlog/overview.md
  • docs/getting-started/tutorial-backlog-quickstart-demo.md
  • docs/guides/custom-field-mapping.md
  • docs/bundles/backlog/delta.md
🧠 Learnings (15)
📓 Common learnings
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-13T10:38:29.399Z
Learning: When a change is paired with work in specfact-cli, review the paired public change artifacts there before widening scope or redefining shared workflow semantics
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-13T10:38:15.855Z
Learning: Adhere to worktree policy, OpenSpec gating, GitHub hierarchy-cache refresh, TDD order, quality gates, versioning, and documentation rules as defined in `docs/agent-rules/`
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.848Z
Learning: This repository enforces the clean-code review gate through hatch run specfact code review run --json --out .specfact/code-review.json
📚 Learning: 2026-04-02T21:49:11.371Z
Learnt from: djm81
Repo: nold-ai/specfact-cli-modules PR: 136
File: registry/modules/specfact-spec-0.40.17.tar.gz.sha256:1-1
Timestamp: 2026-04-02T21:49:11.371Z
Learning: In nold-ai/specfact-cli-modules, module tarball signatures (registry/signatures/*.tar.sig) are generated by the `publish-modules` GitHub Actions runner during the publish workflow, not committed locally to the branch. Missing signature files should NOT be flagged as a pre-merge blocker in PRs.

Applied to files:

  • registry/modules/specfact-backlog-0.41.21.tar.gz.sha256
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/TDD_EVIDENCE.md
  • packages/specfact-backlog/module-package.yaml
  • registry/index.json
  • README.md
📚 Learning: 2026-04-02T21:49:07.435Z
Learnt from: djm81
Repo: nold-ai/specfact-cli-modules PR: 136
File: registry/modules/specfact-spec-0.40.17.tar.gz.sha256:1-1
Timestamp: 2026-04-02T21:49:07.435Z
Learning: In nold-ai/specfact-cli-modules, module tarball signature files under registry/signatures/*.tar.sig are produced by the publish-modules GitHub Actions runner during the publish workflow (not committed to the branch). During PR pre-merge review, do not flag missing *.tar.sig files as blockers; treat signatures as publish-time artifacts.

Applied to files:

  • registry/signatures/specfact-backlog-0.41.21.tar.sig
📚 Learning: 2026-04-13T10:38:22.848Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.848Z
Learning: This repository enforces the clean-code review gate through hatch run specfact code review run --json --out .specfact/code-review.json

Applied to files:

  • scripts/pre_commit_code_review.py
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/TDD_EVIDENCE.md
  • README.md
📚 Learning: 2026-04-13T10:38:43.535Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.535Z
Learning: Fix SpecFact code review findings, including warnings, unless a rare explicit exception is documented

Applied to files:

  • scripts/pre_commit_code_review.py
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/TDD_EVIDENCE.md
📚 Learning: 2026-04-13T10:38:43.535Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.535Z
Learning: Treat the clean-code compliance gate as mandatory: the review surface enforces `naming`, `kiss`, `yagni`, `dry`, and `solid` categories and blocks regressions

Applied to files:

  • scripts/pre_commit_code_review.py
📚 Learning: 2026-04-13T10:38:29.399Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-13T10:38:29.399Z
Learning: When a change is paired with work in specfact-cli, review the paired public change artifacts there before widening scope or redefining shared workflow semantics

Applied to files:

  • scripts/pre_commit_code_review.py
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/TDD_EVIDENCE.md
  • docs/bundles/backlog/overview.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/backlog-sync/spec.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/backlog-add/spec.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/runtime-artifact-write-safety/spec.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/proposal.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/tasks.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/design.md
📚 Learning: 2026-04-13T10:38:43.535Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.535Z
Learning: Perform `spec -> tests -> failing evidence -> code -> passing evidence` in that order for behavior changes

Applied to files:

  • openspec/changes/project-runtime-01-safe-artifact-write-policy/TDD_EVIDENCE.md
  • openspec/changes/project-runtime-01-safe-artifact-write-policy/tasks.md
📚 Learning: 2026-04-13T10:38:22.848Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.848Z
Learning: Signed module or manifest changes require version-bump review and verify-modules-signature

Applied to files:

  • packages/specfact-backlog/module-package.yaml
  • README.md
📚 Learning: 2026-04-13T10:38:43.535Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.535Z
Learning: Enforce module signatures and version bumps when signed module assets or manifests are affected

Applied to files:

  • packages/specfact-backlog/module-package.yaml
  • README.md
📚 Learning: 2026-04-13T10:38:22.848Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.848Z
Learning: Refresh .specfact/backlog/github_hierarchy_cache.md with python scripts/sync_github_hierarchy_cache.py when GitHub hierarchy metadata is missing or stale before parent or blocker work

Applied to files:

  • tests/unit/specfact_backlog/test_sync_command.py
  • docs/bundles/backlog/delta.md
📚 Learning: 2026-04-13T10:38:43.535Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.535Z
Learning: If GitHub hierarchy metadata is needed and `.specfact/backlog/github_hierarchy_cache.md` is missing or stale, refresh it with `python scripts/sync_github_hierarchy_cache.py`

Applied to files:

  • docs/bundles/backlog/delta.md
📚 Learning: 2026-04-13T10:38:15.855Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-13T10:38:15.855Z
Learning: Adhere to worktree policy, OpenSpec gating, GitHub hierarchy-cache refresh, TDD order, quality gates, versioning, and documentation rules as defined in `docs/agent-rules/`

Applied to files:

  • openspec/changes/project-runtime-01-safe-artifact-write-policy/tasks.md
  • README.md
📚 Learning: 2026-04-13T10:38:22.848Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.848Z
Learning: Work belongs on feature/*, bugfix/*, hotfix/*, or chore/* branches, normally in a worktree rooted under ../specfact-cli-modules-worktrees/

Applied to files:

  • openspec/changes/project-runtime-01-safe-artifact-write-policy/tasks.md
  • README.md
📚 Learning: 2026-04-13T10:38:29.399Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-13T10:38:29.399Z
Learning: Treat canonical rule docs (docs/agent-rules/INDEX.md) as the source of truth for worktree policy, OpenSpec gating, GitHub completeness checks, TDD order, quality gates, versioning, and documentation rules

Applied to files:

  • README.md
🪛 LanguageTool
openspec/changes/project-runtime-01-safe-artifact-write-policy/proposal.md

[style] ~11-~11: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...d generic modules-side abstraction. - NEW: Define .specfact ownership classes...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

openspec/changes/project-runtime-01-safe-artifact-write-policy/design.md

[style] ~3-~3: Specify a number, remove phrase, use “a few”, or use “some”
Context: ...artifacts under .specfact/, with only a small number of sanctioned external touchpoints outside...

(SMALL_NUMBER_OF)

🪛 markdownlint-cli2 (0.22.1)
openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/runtime-artifact-write-safety/spec.md

[warning] 3-3: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 6-6: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 11-11: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 16-16: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 19-19: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 25-25: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

openspec/changes/project-runtime-01-safe-artifact-write-policy/proposal.md

[warning] 17-17: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 20-20: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🔀 Multi-repo context nold-ai/specfact-cli

[::nold-ai/specfact-cli::]

  • packages/specfact-backlog/src/specfact_backlog/backlog_core/commands/sync.py
    • Implements new --force-baseline-overwrite flag, pre-write checks, and timestamped backup behavior for external baseline files. Tests exercise both failure (no force) and backup+overwrite (with force). Relevant consumer: CLI sync flow. [::nold-ai/specfact-cli::packages/specfact-backlog/src/specfact_backlog/backlog_core/commands/sync.py]
  • packages/specfact-backlog/src/specfact_backlog/backlog/adapters/interface.py
    • Changed to conditional TYPE_CHECKING import/re-export of BacklogAdapter; affects static typing and how the symbol is resolved at runtime vs type-check time. Many adapters and tests reference the BacklogAdapter contract. [::nold-ai/specfact-cli::packages/specfact-backlog/src/specfact_backlog/backlog/adapters/interface.py]
  • packages/specfact-backlog/src/specfact_backlog/backlog/filters.py
    • Conditional TYPE_CHECKING import of BacklogFilters; BacklogFilters is widely used by adapters and commands (fetch_backlog_items signatures). Changing import/gating can affect type-checking and static-analysis tooling. [::nold-ai/specfact-cli::packages/specfact-backlog/src/specfact_backlog/backlog/filters.py]
  • scripts/check-bundle-imports.py
    • Logic updated to ignore imports inside TYPE_CHECKING/typing.TYPE_CHECKING guards; impacts static import-boundary scanning used in packaging/CI. Verify scanner still treats intended imports correctly. [::nold-ai/specfact-cli::scripts/check-bundle-imports.py]
  • scripts/pre_commit_code_review.py
    • Now invokes specfact code-review with --level error; changes pre-commit gate behavior and what findings block commits/PRs. [::nold-ai/specfact-cli::scripts/pre_commit_code_review.py]
  • Packaging / registry
    • packages/specfact-backlog/module-package.yaml bumped 0.41.17 → 0.41.21; registry/index.json, checksum, and signature updated to reference specfact-backlog-0.41.21 artifact. Consumers: any module installer/publish pipeline. [::nold-ai/specfact-cli::packages/specfact-backlog/module-package.yaml] [::nold-ai/specfact-cli::registry/index.json] [::nold-ai/specfact-cli::registry/modules/specfact-backlog-0.41.21.tar.gz.sha256] [::nold-ai/specfact-cli::registry/signatures/specfact-backlog-0.41.21.tar.sig]
  • Tests exercising changed behavior
    • tests/unit/specfact_backlog/test_sync_command.py — verifies force/backup behavior for external baseline files. [::nold-ai/specfact-cli::tests/unit/specfact_backlog/test_sync_command.py]
    • tests/unit/specfact_backlog/test_map_fields_command.py — verifies map-fields preserves unrelated YAML sections and fails safely on malformed YAML. [::nold-ai/specfact-cli::tests/unit/specfact_backlog/test_map_fields_command.py]
    • tests/unit/specfact_backlog/test_refine_adapter_contract.py — updated to pass adapter context and BacklogFilters to refined fetch call. [::nold-ai/specfact-cli::tests/unit/specfact_backlog/test_refine_adapter_contract.py]

Notes / Risk surface

  • BacklogAdapter and BacklogFilters are core contracts used across adapters/commands/tests in this repo; the TYPE_CHECKING conditional re-exports and the stricter TYPE_CHECKING detection in scripts/check-bundle-imports.py affect type checking and static-analysis tooling. Confirm that runtime import resolution remains correct and static scanners (CI) align with the new guard parsing.
  • The new sync behavior is additive (requires explicit --force to overwrite external baseline) but changes command ordering (pre-write check before network fetch). Consumers that invoked sync expecting overwrite-on-write may need explicit flag use; tests already cover intended behavior.

No external repositories were present/queried; all relevant consumers and artifacts are inside nold-ai/specfact-cli.

🔇 Additional comments (16)
scripts/check-bundle-imports.py (1)

82-110: TYPE_CHECKING-aware import scan update looks correct.

Line 98 cleanly skips type-check-only guarded imports while still traversing else nodes, preserving runtime boundary enforcement.

packages/specfact-backlog/src/specfact_backlog/backlog/filters.py (1)

9-13: Adapter boundary re-export pattern is solid.

Lines 9-13 keep runtime resolution behavior intact while exposing the symbol cleanly for type-checking flows.

packages/specfact-backlog/src/specfact_backlog/backlog/adapters/interface.py (1)

9-13: Core adapter contract re-export remains safe and consistent.

Lines 9-13 preserve the runtime contract while improving static typing ergonomics for adapter consumers.

tests/unit/specfact_backlog/test_refine_adapter_contract.py (1)

46-58: Contract-level test update is aligned with current fetch API usage.

Lines 46-58 correctly exercise _fetch_backlog_items via _AdapterContext plus BacklogFilters, which is the expected adapter boundary.

scripts/pre_commit_code_review.py (1)

114-115: --level error invocation is valid and consistent with the gated CLI contract.

This flag pair is supported by the review command and keeps the pre-commit call deterministic.

packages/specfact-backlog/module-package.yaml (1)

2-2: Module manifest bump and integrity refresh look coherent.

Version and integrity fields were updated together, matching expected signed-manifest workflow for a bundle release.

Also applies to: 30-31

registry/index.json (1)

19-21: Registry entry update is consistent with the backlog bundle release bump.

latest_version, artifact path, and checksum move in lockstep for nold-ai/specfact-backlog.

docs/getting-started/tutorial-backlog-quickstart-demo.md (1)

51-51: Path corrections are accurate and improve quickstart reliability.

The updated config references now match backlog command behavior under .specfact/.

Also applies to: 69-69

docs/bundles/backlog/delta.md (1)

34-34: Delta baseline guidance now correctly reflects sync ownership rules.

The default path and external-overwrite/backup behavior are documented clearly and match runtime behavior.

Also applies to: 42-42

docs/bundles/backlog/overview.md (1)

59-67: Ownership model section is clear and implementation-aligned.

This accurately documents managed vs user-owned backlog artifacts and the external baseline overwrite guard.

openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/backlog-add/spec.md (1)

5-22: Spec requirement framing is tight and testable.

The scenarios clearly enforce subtree-only updates and preservation of unrelated .specfact config state.

packages/specfact-backlog/src/specfact_backlog/backlog_core/commands/sync.py (1)

34-76: Safety gate and recovery-backup flow are correctly implemented.

The external overwrite guard, explicit --force-baseline-overwrite, and pre-fetch enforcement (before Line 201) match the intended ownership boundary behavior.

Based on learnings, paired-core integration should stay scoped to sanctioned external artifacts; this implementation preserves that scope.

Also applies to: 179-201

openspec/changes/project-runtime-01-safe-artifact-write-policy/specs/backlog-sync/spec.md (1)

5-20: Spec update is aligned with runtime behavior.

The managed .specfact vs external-target split and non-silent-overwrite requirement are clear and consistent with the sync command changes.

README.md (1)

38-65: Gate and signing guidance refresh looks good.

The --level error governance update and the clarified signature/versioning workflow improve contributor-facing accuracy and usability.

Also applies to: 66-87

openspec/changes/project-runtime-01-safe-artifact-write-policy/design.md (1)

26-79: Design boundary and rollout strategy are well-scoped.

The decision set cleanly separates sanctioned external-path contract reuse from .specfact ownership semantics and keeps first adoption backlog-focused.

Based on learnings, paired-core workflow semantics should remain scoped and not be widened without matching public artifacts; this design follows that constraint.

tests/unit/specfact_backlog/test_sync_command.py (1)

14-47: Targeted sync safety coverage is solid.

These tests correctly pin both critical behaviors: refusal without force and overwrite-with-backup integrity when force is provided.

Also applies to: 49-85

Comment thread docs/guides/custom-field-mapping.md Outdated
Comment thread openspec/changes/project-runtime-01-safe-artifact-write-policy/tasks.md Outdated
omit-test and others added 8 commits April 27, 2026 00:50
…wn providers

- When both github and ado are selected, print the GitHub informational
  message then proceed with ADO instead of silently skipping GitHub
- Unknown --provider values (e.g. typos) now fail fast with an explicit
  error instead of silently falling back to ADO
- Bump specfact-backlog to 0.41.22

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- custom-field-mapping.md: "fails safe" → "fails safely" (grammar)
- proposal.md: add blank lines after ### headings (MD022)
- spec.md: add blank lines after requirement headings (MD022)
- tasks.md: mark 4.5 done, add PR cross-links and deferred follow-up note
- TDD_EVIDENCE.md: add sign + verify entries for version 0.41.21
- test_map_fields_command.py: extract _setup_ado_map_fields helper to
  eliminate repeated payloads/fake_get/args across three tests
- Bump specfact-backlog to 0.41.23

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
chore(modules): auto-sign module manifests
chore(modules): auto-sign module manifests
github-actions Bot and others added 4 commits April 26, 2026 23:02
@djm81 djm81 merged commit 0ea9f11 into main Apr 26, 2026
27 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in SpecFact CLI Apr 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working codebase Specfact codebase related topic enhancement New feature or request

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Change] Runtime adoption of safe artifact write policy

1 participant