Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
129 commits
Select commit Hold shift + click to select a range
700c360
perf: optimize startup performance with metadata tracking and update …
djm81 Jan 27, 2026
4b167dd
Merge branch 'main' into dev
djm81 Jan 27, 2026
e4782ea
fix: add missing ADO field mappings and assignee display (#145)
djm81 Jan 27, 2026
a2f6ac7
Merge branch 'main' into dev
djm81 Jan 27, 2026
c74a773
fix: mitigate code scanning vulnerabilities (#148)
djm81 Jan 27, 2026
af030dc
fix: detect GitHub remotes using ssh:// and git:// URLs
djm81 Jan 27, 2026
db827a0
chore: bump version to 0.26.9 and update changelog
djm81 Jan 27, 2026
1ade334
Merge branch 'main' into dev
djm81 Jan 27, 2026
5c1cb41
fix: compare GitHub SSH hostnames case-insensitively
djm81 Jan 27, 2026
68cc345
Merge branch 'main' into dev
djm81 Jan 27, 2026
dfeb7ca
Add openspec and workflow commands for transparency
djm81 Jan 27, 2026
9e1f22d
Add specs from openspec
djm81 Jan 27, 2026
115e402
Remove aisp change which wasn't implemented
djm81 Jan 27, 2026
2675361
Fix openspec gitignore pattern
djm81 Jan 27, 2026
573fb7b
Update gitignore
djm81 Jan 27, 2026
907501e
Update contribution standards to use openspec for SDD
djm81 Jan 27, 2026
568000c
Merge branch 'main' into dev
djm81 Jan 27, 2026
fe082f6
Migrate to new opsx openspec commands
djm81 Jan 27, 2026
036afbe
Migrate workflow and openspec config
djm81 Jan 28, 2026
5a1493f
fix: bump version to 0.26.10 for PyPI publish
djm81 Jan 28, 2026
da606a1
Update version and changelog
djm81 Jan 28, 2026
608f317
Add canonical user-friendly workitem url for ado workitems
djm81 Jan 28, 2026
719256c
Update to support OSPX
djm81 Jan 28, 2026
1f94d7c
Merge branch 'main' into dev
djm81 Jan 28, 2026
bbf730a
feat(backlog): implement refine --import-from-tmp and fix type-check …
djm81 Jan 28, 2026
080743a
Merge branch 'main' into dev
djm81 Jan 28, 2026
5ab46a5
Merge branch 'main' into dev
djm81 Jan 28, 2026
1cdfc66
feat: debug logs under ~/.specfact/logs and release 0.26.13 (#159)
djm81 Jan 29, 2026
6bd9d7f
Potential fix for pull request finding 'Empty except'
djm81 Jan 29, 2026
d7d194b
Fix unused variable review
djm81 Jan 29, 2026
39563fc
Fix unused variable review
djm81 Jan 29, 2026
d15485a
Fix type and test errors
djm81 Jan 29, 2026
6c9c9b9
Merge branch 'main' into dev
djm81 Jan 29, 2026
bd9b96a
Finalize change
djm81 Jan 29, 2026
c7e4546
Change for debug logs archived
djm81 Jan 29, 2026
09e8040
Merge branch 'main' into dev
djm81 Jan 29, 2026
642e1a9
fix: improve ADO backlog refine error logging and user-facing error U…
djm81 Jan 29, 2026
64365db
Merge branch 'main' into dev
djm81 Jan 29, 2026
0d0abba
feat: backlog refine --ignore-refined and --id, startup docs (fixes #…
djm81 Jan 30, 2026
aad02cd
Add change proposals for full scrum support
djm81 Jan 30, 2026
a3c3fb4
Merge branch 'main' into dev
djm81 Jan 30, 2026
1f054c5
Add support for systematic, structured issue creation with copilot help
djm81 Jan 30, 2026
899b9c2
feat(backlog): daily standup defaults, iteration/sprint, unassigned i…
djm81 Feb 3, 2026
b596766
Issue 179 resolution (#180)
djm81 Feb 3, 2026
bb7214f
Merge branch 'main' into dev
djm81 Feb 3, 2026
61a820c
fix(backlog): address CodeQL/Codex PR 181 findings
djm81 Feb 3, 2026
10fee30
Update openspec enforcement rules
djm81 Feb 3, 2026
8e770dc
Structure openspec changes
djm81 Feb 3, 2026
5782860
Fix ruff finding
djm81 Feb 3, 2026
05c592d
Fix linter issues with StrEnum and parameters
djm81 Feb 3, 2026
f7e3d0f
Fix tests and depcreation warnings
djm81 Feb 3, 2026
15d710b
Improve sync script
djm81 Feb 3, 2026
b223161
Merge branch 'main' into dev
djm81 Feb 3, 2026
870db6a
Add change for modular command registry
djm81 Feb 3, 2026
5404c18
Fix review finding on dev sync script
djm81 Feb 3, 2026
e4650dd
Update modular change proposal
djm81 Feb 4, 2026
c44013e
feat: CLI modular command registry and lazy load (arch-01) (#196)
djm81 Feb 4, 2026
542183c
docs: document CLI modules design; sync version and cleanup
djm81 Feb 4, 2026
c4b10d8
Archive modular change and specs
djm81 Feb 4, 2026
a7a83c2
Merge branch 'main' into dev
djm81 Feb 4, 2026
2faf547
Merge branch 'dev' of https://github.com/nold-ai/specfact-cli into dev
djm81 Feb 4, 2026
b5d2680
Fix banner display on help screen
djm81 Feb 4, 2026
077ff3f
Improve action runner on main
djm81 Feb 4, 2026
7567149
Merge branch 'main' into dev
djm81 Feb 4, 2026
8a0a38f
Setup claude skills and instructions
djm81 Feb 5, 2026
336efb5
feat: module package separation for command implementations (#200)
djm81 Feb 6, 2026
ad023f5
Merge branch 'main' into dev
djm81 Feb 6, 2026
8b4adcb
fix: address CodeQL and Codex review findings from PR #201
djm81 Feb 6, 2026
b44ce9c
Merge branch 'main' into dev
djm81 Feb 6, 2026
a6b9d32
feat: module lifecycle management, init split, and interactive module…
djm81 Feb 6, 2026
de89bba
archived change for module improvements
djm81 Feb 6, 2026
b4edcfb
Merge branch 'main' into dev
djm81 Feb 6, 2026
bc71080
fix: address review feedback in init and boundary tests
djm81 Feb 6, 2026
e5d7002
Fix test setup for tmpfiles
djm81 Feb 6, 2026
c97080b
Merge branch 'main' into dev
djm81 Feb 6, 2026
46b1357
docs: add openspec change arch-05 bridge registry (#210)
djm81 Feb 8, 2026
20410a6
docs: add openspec change arch-06 manifest security (#211)
djm81 Feb 8, 2026
04aba4b
feat: Core Contracts and Module Interface Formalization (#209)
djm81 Feb 8, 2026
0f492f6
Update specs and archive arch-04 change
djm81 Feb 8, 2026
7656d7c
Fix changelog format
djm81 Feb 8, 2026
b826fb6
docs: align arch-05 scope with protocol migration cleanup (#212)
djm81 Feb 8, 2026
c8ec9bb
docs: add OpenSpec changes for module marketplace phases
djm81 Feb 9, 2026
b6e1fe1
feat: apply arch-05 bridge registry implementation (#216)
djm81 Feb 10, 2026
f10e14e
Archive arch-05 change after implementation
djm81 Feb 10, 2026
285a9ff
Merge branch 'main' into dev
djm81 Feb 10, 2026
5075d0c
fix: address post-merge review findings and restore lazy registration
djm81 Feb 10, 2026
31e6924
fix: refresh project console per invocation in tests
djm81 Feb 10, 2026
d7ca6af
fix: detect runtime interface protocol ops in source scan
djm81 Feb 10, 2026
0e5463f
fix: harden project console refresh and protocol source scan
djm81 Feb 10, 2026
57c729b
fix: refresh import command console for each invocation
djm81 Feb 10, 2026
e270e09
fix: resolve type-check errors and harden protocol scanning
djm81 Feb 10, 2026
7cc1c48
fix: stabilize module protocol scan and project console lifecycle
djm81 Feb 10, 2026
5996a1d
Merge branch 'main' into dev
djm81 Feb 10, 2026
81527a5
Refine pending changes for new modular ecosystem and marketplace inte…
djm81 Feb 10, 2026
6fd151a
fix: update stale spec-delta paths in tasks.md after change renames
djm81 Feb 10, 2026
22640fa
docs: rewrite CHANGE_ORDER.md for module-scoped changes and full depe…
djm81 Feb 10, 2026
e7d69d6
Merge branch 'main' into dev
djm81 Feb 10, 2026
9a7f9f6
feat(backlog): daily/refine comment context, interactive standup post…
djm81 Feb 11, 2026
e61d56b
fix(backlog): satisfy interactive daily adapter typing
djm81 Feb 11, 2026
fff65e9
fix(backlog): bypass default daily limit for issue-window flags
djm81 Feb 11, 2026
b2a8ab5
Merge branch 'main' into dev
djm81 Feb 11, 2026
88ea93c
fix: parse backlog refine writeback fields and refactor refine comman…
djm81 Feb 12, 2026
f3c5759
fix: avoid raw label fallback when description block is missing
djm81 Feb 12, 2026
f9f2fcc
Merge branch 'main' into dev
djm81 Feb 12, 2026
1870cfe
fix: harden backlog refine prompt scaffold and mixed-format parsing (…
djm81 Feb 12, 2026
16db526
Finish change
djm81 Feb 12, 2026
a3e8ff2
chore: bump version to 0.30.4 and update changelog
djm81 Feb 12, 2026
1bdcbc9
Merge branch 'main' into dev
djm81 Feb 12, 2026
998ab59
Add MEMORY.md for claude code
djm81 Feb 12, 2026
bedf75c
Archive backlog writeback field split change
djm81 Feb 12, 2026
6e66806
Archived flask support sidecar change
djm81 Feb 12, 2026
7d6c550
feat: add backlog-core module — dependency analysis and command suite…
djm81 Feb 13, 2026
4d1f950
Merge branch 'main' into dev
djm81 Feb 13, 2026
47ea3f4
fix(backlog-core): remove unused module io contract global
djm81 Feb 13, 2026
2509412
Fixed conflict
djm81 Feb 14, 2026
d8d17a5
fix: rename LICENSE.md to LICENSE for GitHub license detection (#233)
djm81 Feb 14, 2026
100c94f
fix: restore standard Apache 2.0 license text for GitHub detection (#…
djm81 Feb 14, 2026
002cf19
Merge branch 'main' into dev
djm81 Feb 14, 2026
ee0b766
Add openspec changes for architecture level enhancement
djm81 Feb 15, 2026
540c96a
Merge branch 'dev' of https://github.com/nold-ai/specfact-cli into dev
djm81 Feb 15, 2026
ea430ab
Merge branch 'main' into dev
djm81 Feb 15, 2026
6dc73ca
Merge branch 'main' into dev
djm81 Feb 16, 2026
d621e91
Merge branch 'dev' of https://github.com/nold-ai/specfact-cli into dev
djm81 Feb 16, 2026
1b06427
feat(ci): attach test and repro log artifacts to PR orchestrator runs…
djm81 Feb 16, 2026
0bc52a5
feat: enhanced module manifest security and integrity (arch-06) (#263)
djm81 Feb 16, 2026
3f09ee7
feat: Schema Extension System for Modular ProjectBundle Extensions (a…
djm81 Feb 16, 2026
e959e61
Merge branch 'main' into dev
djm81 Feb 16, 2026
ba08744
Fix codeql findings
djm81 Feb 16, 2026
a3a3b6a
Merge branch 'dev' of https://github.com/nold-ai/specfact-cli into dev
djm81 Feb 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/sign-modules.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
# Sign module manifests for integrity (arch-06). Outputs checksums for manifest integrity fields.
name: Sign Modules

on:
workflow_dispatch: {}
push:
branches: [main]
paths:
- "src/specfact_cli/modules/**/module-package.yaml"
- "modules/**/module-package.yaml"

jobs:
sign:
name: Sign module manifests
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Sign module manifests
run: |
for f in $(find . -name 'module-package.yaml' -not -path './.git/*' 2>/dev/null | head -20); do
if [ -f "scripts/sign-module.sh" ]; then
bash scripts/sign-module.sh "$f" || true
fi
done
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,6 @@ harness_contracts.py
# semgrep artifacts
lang.json
Language.ml
Language.mli
Language.mli

.artifacts
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,28 @@ All notable changes to this project will be documented in this file.

---

## [0.32.0] - 2026-02-16

### Added

- **Enhanced module manifest security and integrity** (arch-06, fixes [#208](https://github.com/nold-ai/specfact-cli/issues/208))
- Publisher and integrity metadata in `module-package.yaml` (`publisher`, `integrity.checksum`, optional `integrity.signature`).
- Versioned dependency entries (`module_dependencies_versioned`, `pip_dependencies_versioned`) with name and version specifier.
- `crypto_validator`: checksum verification (sha256/sha384/sha512) and optional signature verification.
- Registration-time trust checks: manifest checksum verified before module load; failed trust skips that module only.
- `SPECFACT_ALLOW_UNSIGNED` and `allow_unsigned` parameter for explicit opt-in when using unsigned modules.
- Signing automation: `scripts/sign-module.sh` and `.github/workflows/sign-modules.yml` for checksum generation.
- Documentation: `docs/reference/module-security.md` and architecture updates for module trust and integrity lifecycle.

- **Schema extension system** (arch-07, Resolves [#213](https://github.com/nold-ai/specfact-cli/issues/213))
- `extensions` dict field on `Feature` and `ProjectBundle` with namespace-prefixed keys (e.g. `backlog.ado_work_item_id`).
- Type-safe `get_extension(module_name, field, default=None)` and `set_extension(module_name, field, value)` with contract enforcement.
- Optional `schema_extensions` in `module-package.yaml` to declare target model, field, type_hint, and description.
- `ExtensionRegistry` for collision detection and introspection; module registration loads and validates schema extensions.
- Guide: [Extending ProjectBundle](https://docs.specfact.io/guides/extending-projectbundle/).

---

## [0.31.1] - 2026-02-16

### Added
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ Contract-first module architecture highlights:
- Registration tracks protocol operation coverage and schema compatibility metadata.
- Bridge registry support allows module manifests to declare `service_bridges` converters (for example ADO/Jira/Linear/GitHub) loaded at lifecycle startup without direct core-to-module imports.
- Protocol reporting classifies modules from effective runtime interfaces with a single aggregate summary (`Full/Partial/Legacy`).
- Module manifests support publisher and integrity metadata (arch-06) with optional checksum and signature verification at registration time.

Why this matters:

Expand Down
3 changes: 3 additions & 0 deletions docs/_layouts/default.html
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ <h2 class="docs-sidebar-title">
<li><a href="{{ '/guides/command-chains/' | relative_url }}">Command Chains</a></li>
<li><a href="{{ '/guides/agile-scrum-workflows/' | relative_url }}">Agile/Scrum Workflows</a></li>
<li><a href="{{ '/guides/creating-custom-bridges/' | relative_url }}">Creating Custom Bridges</a></li>
<li><a href="{{ '/guides/extending-projectbundle/' | relative_url }}">Extending ProjectBundle</a></li>
<li><a href="{{ '/guides/using-module-security-and-extensions/' | relative_url }}">Using Module Security and Extensions</a></li>
<li><a href="{{ '/brownfield-engineer/' | relative_url }}">Working With Existing Code</a></li>
<li><a href="{{ '/brownfield-journey/' | relative_url }}">Existing Code Journey</a></li>
<li><a href="{{ '/guides/sidecar-validation/' | relative_url }}">Sidecar Validation</a></li>
Expand Down Expand Up @@ -174,6 +176,7 @@ <h2 class="docs-sidebar-title">
<li><a href="{{ '/directory-structure/' | relative_url }}">Directory Structure</a></li>
<li><a href="{{ '/reference/projectbundle-schema/' | relative_url }}">ProjectBundle Schema</a></li>
<li><a href="{{ '/reference/module-contracts/' | relative_url }}">Module Contracts</a></li>
<li><a href="{{ '/reference/module-security/' | relative_url }}">Module Security</a></li>
<li><a href="{{ '/reference/bridge-registry/' | relative_url }}">Bridge Registry</a></li>
<li><a href="{{ '/guides/integrations-overview/' | relative_url }}">Integrations Overview</a></li>
</ul>
Expand Down
82 changes: 82 additions & 0 deletions docs/guides/extending-projectbundle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
layout: default
title: Extending ProjectBundle
permalink: /guides/extending-projectbundle/
description: Add namespaced custom fields to Feature and ProjectBundle without modifying core models.
---

# Extending ProjectBundle

Modules can extend `Feature` and `ProjectBundle` with custom metadata using the **schema extension system** (arch-07). Extensions use namespace-prefixed keys so multiple modules can store data without conflicts.

## Overview

- **`extensions`** – A dict on `Feature` and `ProjectBundle` that stores module-specific data under keys like `backlog.ado_work_item_id` or `sync.last_sync_timestamp`.
- **`get_extension(module_name, field, default=None)`** – Read a value.
- **`set_extension(module_name, field, value)`** – Write a value.
- **`schema_extensions`** – Optional declaration in `module-package.yaml` so the CLI can validate and introspect which fields a module uses.

## Using Extensions in Code

```python
from specfact_cli.models.plan import Feature
from specfact_cli.models.project import ProjectBundle

# On a Feature (e.g. from a bundle)
feature.set_extension("backlog", "ado_work_item_id", "123456")
value = feature.get_extension("backlog", "ado_work_item_id") # "123456"
missing = feature.get_extension("backlog", "missing", default="default") # "default"

# On a ProjectBundle
bundle.set_extension("sync", "last_sync_timestamp", "2025-01-15T12:00:00Z")
ts = bundle.get_extension("sync", "last_sync_timestamp")
```

**Rules:**

- `module_name`: lowercase, alphanumeric plus underscores/hyphens, **no dots** (e.g. `backlog`, `sync`).
- `field`: lowercase, alphanumeric plus underscores (e.g. `ado_work_item_id`).
- Keys are stored as `module_name.field` (e.g. `backlog.ado_work_item_id`).

## Declaring Extensions in the Manifest

In `module-package.yaml` you can declare which extensions your module uses so the CLI can detect collisions and support introspection:

```yaml
name: backlog
version: "0.1.0"
commands: [backlog]

schema_extensions:
- target: Feature
field: ado_work_item_id
type_hint: str
description: Azure DevOps work item ID for sync
- target: Feature
field: jira_issue_key
type_hint: str
description: Jira issue key when using Jira adapter
- target: ProjectBundle
field: last_sync_timestamp
type_hint: str
description: ISO timestamp of last sync
```

- **target** – `Feature` or `ProjectBundle`.
- **field** – Snake_case field name (must match `[a-z][a-z0-9_]*`).
- **type_hint** – Documentation only (e.g. `str`, `int`).
- **description** – Human-readable description.

If two modules declare the same `(target, field)` (e.g. both declare `Feature.ado_work_item_id`), the second module’s schema extensions are skipped and an error is logged.

## Best Practices

- Use a single logical namespace per module (the module name).
- Prefer short, clear field names (`ado_work_item_id`, `last_sync_timestamp`).
- Document extensions in `schema_extensions` so other tools and docs can introspect them.
- Do not rely on extension values for core behavior; keep them as optional metadata.

## Backward Compatibility

- Existing bundles and features without an `extensions` field load with `extensions = {}`.
- Modules that omit `schema_extensions` load and run normally; no extensions are registered for them.
147 changes: 147 additions & 0 deletions docs/guides/using-module-security-and-extensions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
---
layout: default
title: Using Module Security and Schema Extensions
permalink: /guides/using-module-security-and-extensions/
description: How to use arch-06 (module security) and arch-07 (schema extensions) from CLI commands and as a module author.
nav_order: 22
---

# Using Module Security and Schema Extensions

With **arch-06** (manifest security) and **arch-07** (schema extension system) in place, you can use verified modules and store module-specific metadata on bundles and features. This guide shows how to utilize these features from the CLI and in your own modules.

## Quick reference

| Capability | What it does | Where to read more |
|------------|--------------|--------------------|
| **arch-06** | Publisher + integrity (checksum/signature) on module manifests; versioned dependencies | [Module Security](/reference/module-security/) |
| **arch-07** | `extensions` dict on Feature/ProjectBundle; `get_extension`/`set_extension`; `schema_extensions` in manifest | [Extending ProjectBundle](/guides/extending-projectbundle/) |

---

## Using arch-06 (module security)

### As a CLI user (consuming modules)

- **Verified modules**: When you run any command that loads modules (e.g. `specfact backlog ...`, `specfact project ...`), the registry discovers modules and, when a module has `integrity.checksum` in its `module-package.yaml`, verifies the manifest checksum before registering. If verification fails, that module is skipped and a warning is logged; other modules still load.
- **Unsigned modules**: Modules without `integrity` metadata are allowed by default (backward compatible). To document explicit opt-in in strict environments, set:
```bash
export SPECFACT_ALLOW_UNSIGNED=1
```
- **Versioned dependencies**: Manifests can declare `module_dependencies_versioned` and `pip_dependencies_versioned` (each entry: `name`, `version_specifier`) for install-time resolution. You don’t need to do anything special; the installer uses these when present.

You don’t run a separate “verify” command; verification happens automatically at module registration when the CLI starts.

### As a module author (publishing a module)

1. **Add publisher and integrity to `module-package.yaml`** (optional but recommended):

```yaml
name: my-module
version: "0.1.0"
commands: [my-group]

publisher:
name: "Your Name or Org"
email: "contact@example.com"

integrity:
checksum: "sha256:<hex>" # Required for verification
signature: "<base64>" # Optional; requires trusted key on consumer side
```

2. **Generate the checksum** using the bundled script:

```bash
./scripts/sign-module.sh path/to/module-package.yaml
# Output: sha256:<hex>
# Add that value to integrity.checksum in the manifest
```

3. **CI**: Use `.github/workflows/sign-modules.yml` (or equivalent) to produce or validate checksums when manifest files change.

4. **Versioned dependencies** (optional):

```yaml
module_dependencies_versioned:
- name: backlog-core
version_specifier: ">=0.2.0"
pip_dependencies_versioned:
- name: requests
version_specifier: ">=2.28.0"
```

Details: [Module Security](/reference/module-security/).

---

## Using arch-07 (schema extensions)

### As a CLI user (running commands that use extensions)

Several commands already read or write extension data on `ProjectBundle` (and its manifest). You use them as usual; extensions are persisted with the bundle.

- **Link a backlog provider** (writes `backlog_core.backlog_config` on project metadata):
```bash
specfact project link-backlog --bundle my-bundle --adapter github --project-id my-org/my-repo
```
- **Health check and other project commands** read that same extension to resolve adapter/project/template:
```bash
specfact project health-check --bundle my-bundle
```

Any command that loads a bundle (e.g. `specfact plan ...`, `specfact sync ...`, `specfact spec ...`) loads the full bundle including `extensions`; round-trip save keeps extension data. So you don’t need a special “extensions” command to benefit from them—they’re part of the bundle.

**Introspecting registered extensions (programmatic):** There is no `specfact extensions list` CLI yet. From Python you can call:

```python
from specfact_cli.registry.extension_registry import get_extension_registry
all_exts = get_extension_registry().list_all() # dict: module_name -> list of SchemaExtension
```

### As a module author (using extensions in your commands)

1. **Declare extensions** in `module-package.yaml` so the CLI can validate and avoid collisions:

```yaml
schema_extensions:
- target: Feature
field: my_custom_id
type_hint: str
description: My module’s external ID for this feature
- target: ProjectBundle
field: last_sync_ts
type_hint: str
description: ISO timestamp of last sync
```

2. **In your command code**, when you have a `ProjectBundle` or `Feature` (e.g. from `load_bundle_with_progress` or from a plan bundle):

```python
from specfact_cli.models.plan import Feature
from specfact_cli.models.project import ProjectBundle

# On a Feature
feature.set_extension("my_module", "my_custom_id", "EXT-123")
value = feature.get_extension("my_module", "my_custom_id") # "EXT-123"
missing = feature.get_extension("my_module", "other", default="n/a") # "n/a"

# On ProjectBundle (e.g. bundle.manifest.project_metadata or bundle itself)
bundle.set_extension("my_module", "last_sync_ts", "2026-02-16T12:00:00Z")
ts = bundle.get_extension("my_module", "last_sync_ts")
```

3. **Naming rules**: `module_name`: lowercase, alphanumeric + underscores/hyphens, **no dots**. `field`: lowercase, alphanumeric + underscores. Keys are stored as `module_name.field` (e.g. `my_module.my_custom_id`).

4. **Project metadata**: The built-in `project link-backlog` command uses **project_metadata** (on the bundle manifest), which also supports `get_extension`/`set_extension` with the same `module_name.field` convention (e.g. `backlog_core.backlog_config`). Use the same pattern for your module’s config stored on the project.

Full API and examples: [Extending ProjectBundle](/guides/extending-projectbundle/).

---

## Summary

- **arch-06**: Use `scripts/sign-module.sh` and `integrity`/`publisher` in manifests; consumers get automatic checksum verification at registration; set `SPECFACT_ALLOW_UNSIGNED=1` if you explicitly allow unsigned modules.
- **arch-07**: Use `get_extension`/`set_extension` on Feature and ProjectBundle in your module code; declare `schema_extensions` in `module-package.yaml`; use existing commands like `specfact project link-backlog` and `specfact project health-check` to see extensions in action.

For deeper reference: [Module Security](/reference/module-security/), [Extending ProjectBundle](/guides/extending-projectbundle/), [Architecture](/reference/architecture/).
8 changes: 8 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ Why this matters:
- Interfaces and contracts keep feature development isolated and safer to iterate.
- Pending OpenSpec-driven module changes can land incrementally with lower migration risk.

**Module security and extensions:**

- **[Using Module Security and Extensions](guides/using-module-security-and-extensions.md)** - How to use verified modules (arch-06) and schema extensions (arch-07) from the CLI and as a module author
- **[Extending ProjectBundle](guides/extending-projectbundle.md)** - Declare and use namespaced extension fields on Feature/ProjectBundle
- **[Module Security](reference/module-security.md)** - Publisher, integrity (checksum/signature), and versioned dependencies

## 📚 Documentation

### Guides
Expand All @@ -89,6 +95,8 @@ Why this matters:
- **[Backlog Dependency Analysis](guides/backlog-dependency-analysis.md)** - Analyze critical path, cycles, orphans, and dependency impact from backlog graph data
- **[Backlog Delta Commands](guides/backlog-delta-commands.md)** - Track backlog graph changes under `specfact backlog delta`
- **[Project DevOps Flow](guides/project-devops-flow.md)** - Run plan/develop/review/release/monitor stage actions from one command surface
- **[Extending ProjectBundle](guides/extending-projectbundle.md)** - Add namespaced custom fields to Feature/ProjectBundle (arch-07)
- **[Using Module Security and Extensions](guides/using-module-security-and-extensions.md)** - Use arch-06 (module security) and arch-07 (schema extensions) from CLI and as a module author
- **[Sidecar Validation](guides/sidecar-validation.md)** 🆕 - Validate external codebases without modifying source
- **[UX Features](guides/ux-features.md)** - Progressive disclosure, context detection, intelligent suggestions
- **[Use Cases](guides/use-cases.md)** - Real-world scenarios and workflows
Expand Down
10 changes: 10 additions & 0 deletions docs/reference/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ SpecFact CLI implements a **contract-driven development** framework through thre
- Invalid bridge declarations are non-fatal and skipped with warnings.
- Protocol compliance reporting uses effective runtime interface detection and logs one aggregate summary line.

## Schema Extension System

`arch-07-schema-extension-system` lets modules extend `Feature` and `ProjectBundle` with namespaced custom fields without changing core models.

- **Extensions field**: `Feature` and `ProjectBundle` have an `extensions: dict[str, Any]` field (default empty dict). Keys use the form `module_name.field` (e.g. `backlog.ado_work_item_id`).
- **Accessors**: `get_extension(module_name, field, default=None)` and `set_extension(module_name, field, value)` enforce namespace format and type safety via contracts.
- **Manifest**: Optional `schema_extensions` in `module-package.yaml` declare target model, field name, type hint, and description. Lifecycle loads these and registers them in a global extension registry.
- **Collision detection**: If two modules declare the same (target, field), the second registration is rejected and an error is logged; module command registration continues.
- See [Extending ProjectBundle](/guides/extending-projectbundle/) for usage and best practices.

## Module System Foundation

SpecFact is transitioning from hard-wired command wiring to a module-first architecture.
Expand Down
Loading
Loading