ai: Add spec kit agent governance extension and related files (#5568)

This commit is contained in:
James Rich
2026-05-21 12:56:20 -07:00
committed by GitHub
parent a871dad7c1
commit c32d370f6a
36 changed files with 1856 additions and 146 deletions

View File

@@ -0,0 +1,48 @@
---
description: Generate or update the active agent governance file
---
<!-- Extension: agent-governance -->
<!-- Config: .specify/extensions/agent-governance/ -->
# Agent Governance Generate/Update
## Input
$ARGUMENTS
## Output
- Active agent platform governance file.
- Managed `SPECKIT GOVERNANCE` section.
- `.specify/memory/agent-governance.md`: internal cache.
## Procedure
1. Require `.specify/`.
2. Resolve target:
- `.specify/init-options.json` `context_file`
- `.specify/integration.json` `default_integration` or `integration`
- `AGENTS.md`
3. Create internal cache when missing.
4. Generate target file when missing.
5. Update only the managed section when target exists.
6. Use existing managed section as refresh source.
7. Distill detected repository areas into action rules.
- depth: 2
- include hidden and cache directories
8. Preserve content outside managed markers.
9. Preserve managed markers verbatim.
10. Run:
```bash
uv run python .specify/extensions/agent-governance/scripts/refresh_agent_governance.py
```
## Report
- target governance file
- generated or updated
- review target
- internal cache status
- captured evidence when cache is created

View File

@@ -29,20 +29,22 @@ The branch name must match one of these patterns:
1. **Sequential**: `^[0-9]{3,}-` (e.g., `001-feature-name`, `042-fix-bug`, `1000-big-feature`)
2. **Timestamp**: `^[0-9]{8}-[0-9]{6}-` (e.g., `20260319-143022-feature-name`)
3. **Conventional prefix**: `^(feat|fix|chore|docs|build|ci|refactor|test|deps)/` (e.g., `feat/add-node-filter`, `fix/ble-reconnect`)
## Execution
If on a feature branch (matches either pattern):
- Output: `✓ On feature branch: <branch-name>`
- Check if the corresponding spec directory exists under `specs/`:
- For sequential/timestamp branches, check if the corresponding spec directory exists under `specs/`:
- For sequential branches, look for `specs/<prefix>-*` where prefix matches the numeric portion
- For timestamp branches, look for `specs/<prefix>-*` where prefix matches the `YYYYMMDD-HHMMSS` portion
- For conventional prefix branches, skip spec directory lookup (not spec-driven)
- If spec directory exists: `✓ Spec directory found: <path>`
- If spec directory missing: `⚠ No spec directory found for prefix <prefix>`
If NOT on a feature branch:
- Output: `✗ Not on a feature branch. Current branch: <branch-name>`
- Output: `Feature branches should be named like: 001-feature-name or 20260319-143022-feature-name`
- Output: `Feature branches should be named like: 001-feature-name, feat/feature-name, or 20260319-143022-feature-name`
## Graceful Degradation

View File

@@ -1,6 +1,6 @@
# Meshtastic Android — Copilot Instructions
> **Full rules**: `AGENTS.md` is the source of truth. This file is a compact quick-reference for build commands and task naming. For architecture, conventions, and workflow details, consult `AGENTS.md` and the `.skills/` playbooks listed at the bottom.
> **Full rules**: `AGENTS.md` is the source of truth. This file is a compact quick-reference for build commands and task naming. For architecture, conventions, and workflow details, consult `AGENTS.md` and the `.skills/` playbooks.
## Build, Test & Lint
@@ -46,33 +46,14 @@ KMP modules have different task names than pure-Android modules. Using the wrong
## Quick Reference
- **Architecture**: KMP project (Android, Desktop, iOS). Business logic in `commonMain`; platform shells (`androidApp/`, `desktopApp/`) wire DI and host UI. See `AGENTS.md` and `.skills/kmp-architecture/`.
- **Architecture**: KMP project (Android, Desktop, iOS). Business logic in `commonMain`; platform shells (`androidApp/`, `desktopApp/`) wire DI and host UI.
- **Flavors**: `fdroid` (OSS) / `google` (Maps + DataDog). Only one installable at a time (different signing keys).
- **Verify before push**: Run `./gradlew spotlessApply detekt assembleDebug test allTests`, then confirm CI with `gh pr checks <PR>`.
- **Strings**: `stringResource(Res.string.key)` — run `python3 scripts/sort-strings.py` after adding strings.
- **Icons**: `MeshtasticIcons` (from `core/ui/icon/`), not `material.icons.Icons`.
- **Error handling**: `safeCatching {}` (not `runCatching {}`) in coroutine code.
- **Dispatchers**: `org.meshtastic.core.common.util.ioDispatcher`, not `Dispatchers.IO`.
- **Navigation**: `MeshtasticNavDisplay` + `NavigationBackHandler` (not Android `BackHandler`).
- **Protos**: `core/proto/` is a read-only git submodule. Never modify proto files.
- **Branches**: Must start with `feat/`, `fix/`, `chore/`, `docs/`, `build/`, `ci/`, `refactor/`, `test/`, `deps/`, or a numeric spec prefix. Always branch off `origin/main`.
> See `AGENTS.md` for full rules (verify before push, branch naming, protos, coding conventions).
> Contextual `.github/instructions/` files enforce conventions scoped to relevant source sets.
<!-- SPECKIT START -->
## Active Plan
- **Feature**: Reorder Bottom Navigation Tab Labels
- **Plan**: `specs/20260520-153412-nav-tab-labels/plan.md`
- **Branch**: `jamesarich/issue-5543-alignment-reorder-bottom-navigation-tab-91d55d`
For additional context about technologies to be used, project structure,
shell commands, and other important information, read the current plan
<!-- SPECKIT END -->
## Deeper Guidance
Consult `.skills/` for detailed playbooks:
- `.skills/project-overview/` — Full codebase map and bootstrap
- `.skills/kmp-architecture/` — Source-set rules, expect/actual
- `.skills/compose-ui/` — Adaptive UI, string resources
- `.skills/navigation-and-di/` — Nav 3 & Koin patterns
- `.skills/testing-ci/` — CI architecture, verification matrix
- `.skills/implement-feature/` — Feature development workflow
- `.skills/code-review/` — PR hygiene checklist
- `.skills/speckit/` — Spec Kit SDD workflow, slash commands, constitution

View File

@@ -0,0 +1,3 @@
---
agent: speckit.agent-governance.refresh
---

View File

@@ -1,4 +1,5 @@
installed: []
installed:
- agent-governance
settings:
auto_execute_hooks: true
hooks:
@@ -82,6 +83,13 @@ hooks:
prompt: Commit constitution changes?
description: Auto-commit after constitution update
condition: null
- extension: agent-governance
command: speckit.agent-governance.refresh
enabled: true
optional: true
prompt: Refresh agent governance after constitution changes?
description: Generates the active agent platform governance file
condition: null
after_specify:
- extension: git
command: speckit.git.commit
@@ -106,6 +114,13 @@ hooks:
prompt: Commit plan changes?
description: Auto-commit after implementation planning
condition: null
- extension: agent-governance
command: speckit.agent-governance.refresh
enabled: true
optional: true
prompt: Refresh agent governance after planning?
description: Keeps the active agent platform governance file aligned
condition: null
after_tasks:
- extension: git
command: speckit.git.commit
@@ -114,6 +129,13 @@ hooks:
prompt: Commit task changes?
description: Auto-commit after task generation
condition: null
- extension: agent-governance
command: speckit.agent-governance.refresh
enabled: true
optional: true
prompt: Refresh agent governance after task generation?
description: Keeps the active agent platform governance file aligned
condition: null
after_implement:
- extension: git
command: speckit.git.commit

View File

@@ -1,4 +1,4 @@
{
"cached_at": "2026-05-09T17:19:49.660998+00:00",
"cached_at": "2026-05-21T18:06:13.258618+00:00",
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.json"
}

View File

@@ -108,6 +108,23 @@
},
"registered_skills": [],
"installed_at": "2026-05-09T00:25:20.640435+00:00"
},
"agent-governance": {
"version": "1.2.0",
"source": "local",
"manifest_hash": "sha256:99b9bb818d30379426ffd15e31660bf7e762eb90d1cca22ebcd4dd27b78f94a2",
"enabled": false,
"priority": 10,
"registered_commands": {
"copilot": [
"speckit.agent-governance.refresh"
],
"opencode": [
"speckit.agent-governance.refresh"
]
},
"registered_skills": [],
"installed_at": "2026-05-21T18:07:24.505929+00:00"
}
}
}
}

View File

@@ -0,0 +1,7 @@
__pycache__/
*.pyc
.pytest_cache/
.DS_Store
.venv/
dist/
*.zip

View File

@@ -0,0 +1,40 @@
# Changelog
## Unreleased
## [1.2.0] - 2026-05-19
### Changed
- Initialize the missing governance evidence cache from repository evidence instead of copying the bundled template verbatim.
- Document captured repository evidence and manifest-backed commands in the initial governance evidence cache.
- Clarify that the extension generates active agent platform repository governance files from Spec Kit metadata.
- Simplify command semantics to one generate/update command: missing target governance files are generated, existing target governance files are updated.
- Include repository evidence and development commands in generated agent platform governance files.
- Add `uv`/`pytest` development configuration so the repository test suite has a reproducible runner.
- Treat the generated active agent platform section as the repository governance SSOT and `.specify/memory/agent-governance.md` as a first-run evidence cache.
- Preserve reviewed governance content from an existing active generated section during refresh instead of re-reading rules from the memory cache.
- Clarify that users review only the resolved active agent governance file; no separate memory review or second refresh is required.
- Distill detected repository areas into generated action rules with depth limited to two directory levels, including hidden and cache directories.
- Add generic directory responsibility governance without platform or project examples.
- Tighten governance template wording to preserve managed markers, scope broad linked-file updates, and limit skill-spec field requirements to repository-local skills.
## [1.1.0] - 2026-05-15
### Changed
- Decoupled the agent governance domain from specific project-governance source files.
- Updated generated projections to describe project governance as an independent domain.
### Added
- Tests for template and projection domain boundaries.
## [1.0.0] - 2026-05-14
### Added
- Initial `speckit.agent-governance.refresh` command.
- Agent governance memory template.
- Python helper to project managed governance sections into active agent context files.
- Optional hooks after constitution, plan, and tasks workflows.

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 bigben
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,58 @@
# Spec Kit Agent Governance
Generate the active agent platform governance SSOT section.
## Output
- Active target file from Spec Kit integration metadata.
- Managed `SPECKIT GOVERNANCE` section.
## Scope
- Generate missing target governance file.
- Update existing target governance file.
- Distill detected repository areas into action rules.
- Analyze repository areas to depth 2 only.
- Include hidden and cache directories in repository area governance.
- Enforce one primary responsibility per directory.
- Preserve user-authored content outside managed markers.
- Preserve managed markers verbatim.
- Keep `.specify/memory/agent-governance.md` internal.
- Review only the active target file.
## Install
```bash
specify extension add agent-governance --from https://github.com/bigsmartben/spec-kit-agent-governance/archive/refs/tags/v1.2.0.zip
```
Local development:
```bash
specify extension add --dev /path/to/spec-kit-agent-governance
```
## Run
```text
/speckit.agent-governance.refresh
```
Helper:
```bash
uv run python .specify/extensions/agent-governance/scripts/refresh_agent_governance.py
```
## Files
- `extension.yml`
- `commands/speckit.agent-governance.refresh.md`
- `scripts/refresh_agent_governance.py`
- `templates/agent-governance-template.md`
## Verify
```bash
uv run pytest -q
```

View File

@@ -0,0 +1,45 @@
---
description: "Generate or update the active agent governance file"
---
# Agent Governance Generate/Update
## Input
$ARGUMENTS
## Output
- Active agent platform governance file.
- Managed `SPECKIT GOVERNANCE` section.
- `.specify/memory/agent-governance.md`: internal cache.
## Procedure
1. Require `.specify/`.
2. Resolve target:
- `.specify/init-options.json` `context_file`
- `.specify/integration.json` `default_integration` or `integration`
- `AGENTS.md`
3. Create internal cache when missing.
4. Generate target file when missing.
5. Update only the managed section when target exists.
6. Use existing managed section as refresh source.
7. Distill detected repository areas into action rules.
- depth: 2
- include hidden and cache directories
8. Preserve content outside managed markers.
9. Preserve managed markers verbatim.
10. Run:
```bash
uv run python .specify/extensions/agent-governance/scripts/refresh_agent_governance.py
```
## Report
- target governance file
- generated or updated
- review target
- internal cache status
- captured evidence when cache is created

View File

@@ -0,0 +1,46 @@
schema_version: "1.0"
extension:
id: agent-governance
name: "Agent Governance"
version: "1.2.0"
description: "Generate agent-platform repository governance files from Spec Kit metadata"
author: "bigben"
repository: "https://github.com/bigsmartben/spec-kit-agent-governance"
homepage: "https://github.com/bigsmartben/spec-kit-agent-governance"
license: "MIT"
requires:
speckit_version: ">=0.8.0"
tools:
- name: "uv"
required: true
provides:
commands:
- name: "speckit.agent-governance.refresh"
file: "commands/speckit.agent-governance.refresh.md"
description: "Generate or update the active agent platform governance file"
hooks:
after_constitution:
command: "speckit.agent-governance.refresh"
optional: true
prompt: "Refresh agent governance after constitution changes?"
description: "Generates the active agent platform governance file"
after_plan:
command: "speckit.agent-governance.refresh"
optional: true
prompt: "Refresh agent governance after planning?"
description: "Keeps the active agent platform governance file aligned"
after_tasks:
command: "speckit.agent-governance.refresh"
optional: true
prompt: "Refresh agent governance after task generation?"
description: "Keeps the active agent platform governance file aligned"
tags:
- "governance"
- "agents"
- "memory"
- "context"

View File

@@ -0,0 +1,656 @@
#!/usr/bin/env python3
"""Generate or refresh Spec Kit agent platform governance for the current project."""
from __future__ import annotations
import json
import re
import sys
from pathlib import Path
from typing import Any
MEMORY_PATH = Path(".specify/memory/agent-governance.md")
TEMPLATE_PATH = Path(".specify/extensions/agent-governance/templates/agent-governance-template.md")
INTEGRATION_JSON = Path(".specify/integration.json")
INIT_OPTIONS_JSON = Path(".specify/init-options.json")
MARKER_START = "<!-- SPECKIT GOVERNANCE START -->"
MARKER_END = "<!-- SPECKIT GOVERNANCE END -->"
CONTEXT_FILES = {
"agy": "AGENTS.md",
"amp": "AGENTS.md",
"auggie": ".augment/rules/specify-rules.md",
"bob": "AGENTS.md",
"claude": "CLAUDE.md",
"codebuddy": "CODEBUDDY.md",
"codex": "AGENTS.md",
"copilot": ".github/copilot-instructions.md",
"cursor-agent": ".cursor/rules/specify-rules.mdc",
"devin": "AGENTS.md",
"forge": "AGENTS.md",
"gemini": "GEMINI.md",
"generic": "AGENTS.md",
"goose": "AGENTS.md",
"iflow": "IFLOW.md",
"junie": ".junie/AGENTS.md",
"kilocode": ".kilocode/rules/specify-rules.md",
"kimi": "KIMI.md",
"kiro-cli": "AGENTS.md",
"lingma": ".lingma/rules/specify-rules.md",
"opencode": "AGENTS.md",
"pi": "AGENTS.md",
"qodercli": "QODER.md",
"qwen": "QWEN.md",
"roo": ".roo/rules/specify-rules.md",
"shai": "SHAI.md",
"tabnine": "TABNINE.md",
"trae": ".trae/rules/project_rules.md",
"vibe": "AGENTS.md",
"windsurf": ".windsurf/rules/specify-rules.md",
}
def main() -> int:
root = Path.cwd()
if not (root / ".specify").is_dir():
print("Error: .specify/ not found. Run from a Spec Kit project root.", file=sys.stderr)
return 1
state = read_json(root / INTEGRATION_JSON)
init_options = read_json(root / INIT_OPTIONS_JSON)
created_memory = ensure_memory(root)
target = resolve_target(root, state, init_options)
projection = render_projection(root, target, state, created_memory)
evidence_summary = repository_evidence_summary(root, state, init_options) if created_memory else ""
action = write_projection(target, projection)
remove_stale_sections(root, target, init_options, state)
print(f"Target governance file: {rel(root, target)}")
print(f"Governance file: {action}")
print(f"Review target: {rel(root, target)}")
print(f"Internal initialization cache: {MEMORY_PATH.as_posix()} ({'created' if created_memory else 'existing'})")
if created_memory:
print(f"Repository evidence: {evidence_summary}")
return 0
def ensure_memory(root: Path) -> bool:
memory = root / MEMORY_PATH
if memory.exists():
return False
template = root / TEMPLATE_PATH
if not template.exists():
raise SystemExit(f"Error: template not found: {TEMPLATE_PATH.as_posix()}")
memory.parent.mkdir(parents=True, exist_ok=True)
memory.write_text(render_initial_memory(root, template.read_text(encoding="utf-8-sig")), encoding="utf-8")
return True
def render_initial_memory(root: Path, template: str) -> str:
content = normalize_newlines(template)
state = read_json(root / INTEGRATION_JSON)
init_options = read_json(root / INIT_OPTIONS_JSON)
content = replace_sync_report(content, root, state)
evidence = "\n".join(
[
"## Repository Evidence",
"",
*repository_evidence_lines(root, state, init_options),
"",
"## Repository Areas",
"",
*repository_area_lines(root),
"",
"## Development Commands",
"",
*development_command_lines(root),
"",
]
)
marker = "\n## Scope\n"
if marker in content:
content = content.replace(marker, f"\n{evidence}{marker}", 1)
else:
content = content.rstrip() + "\n\n" + evidence
return content
def replace_sync_report(content: str, root: Path, state: dict[str, Any]) -> str:
report = "\n".join(
[
"<!--",
"Sync Impact Report",
f"- Active Integration: {default_integration(state) or 'unknown'}",
f"- Installed Integrations: {', '.join(installed_integrations(state)) or 'none'}",
f"- Skills Scanned: {len(scan_skills(root))}",
f"- MCP Config Files Scanned: {', '.join(scan_mcp_configs(root)) or 'none'}",
f"- Extension Config Status: .specify/extensions.yml ({extensions_status(root)})",
"- Sections Changed: initialized repository evidence and development commands",
"- Flow: generate missing target governance files; update existing target governance files",
"-->",
]
)
pattern = re.compile(r"<!--\nSync Impact Report\n.*?\n-->", re.DOTALL)
if pattern.search(content):
return pattern.sub(report, content, count=1)
return content
def repository_evidence_summary(root: Path, state: dict[str, Any], init_options: dict[str, Any]) -> str:
evidence = repository_evidence_lines(root, state, init_options)
detected = [line for line in evidence if "none detected" not in line and "`unknown`" not in line]
return "; ".join(line.removeprefix("- ") for line in detected) or "none detected"
def repository_evidence_lines(root: Path, state: dict[str, Any], init_options: dict[str, Any]) -> list[str]:
lines = [
evidence_line("README", existing_paths(root, ["README.md", "README.markdown", "README.txt"])),
evidence_line(
"Package manifest",
existing_paths(root, ["package.json", "pyproject.toml", "Cargo.toml", "go.mod", "Gemfile", "pom.xml", "build.gradle", "build.gradle.kts"]),
),
evidence_line(
"Lockfiles",
existing_paths(root, ["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "uv.lock", "poetry.lock", "Cargo.lock", "go.sum", "Gemfile.lock"]),
),
evidence_line("Task runners", existing_paths(root, ["Makefile", "Taskfile.yml", "Taskfile.yaml", "justfile"])),
evidence_line("CI workflows", directory_files(root, ".github/workflows")),
evidence_line("Source paths", existing_dirs(root, ["src", "app", "lib", "scripts", "commands", "templates"])),
evidence_line("Test paths", existing_dirs(root, ["test", "tests", "spec", "specs"])),
evidence_line("Repository areas", repository_area_paths(root)),
evidence_line("Existing agent context files", existing_context_files(root, init_options, state)),
evidence_line("Repository-local skills", scan_skills(root)),
evidence_line("MCP configs", scan_mcp_configs(root)),
f"- Active integration: `{default_integration(state) or 'unknown'}`",
f"- Resolved context file: `{rel(root, resolve_target(root, state, init_options))}`",
]
return lines
def evidence_line(label: str, values: list[str]) -> str:
return f"- {label}: {format_values(values)}"
def format_values(values: list[str]) -> str:
return ", ".join(f"`{value}`" for value in values) if values else "none detected"
def existing_paths(root: Path, names: list[str]) -> list[str]:
return [name for name in names if (root / name).is_file()]
def existing_dirs(root: Path, names: list[str]) -> list[str]:
return [f"{name}/" for name in names if (root / name).is_dir()]
def directory_files(root: Path, directory: str) -> list[str]:
base = root / directory
if not base.is_dir():
return []
return sorted(rel(root, path) for path in base.iterdir() if path.is_file())
def repository_area_lines(root: Path) -> list[str]:
lines = []
for area in repository_area_paths(root):
if "/" in area.rstrip("/"):
parent = area.rstrip("/").split("/", 1)[0] + "/"
lines.append(f"- `{area}`: change with parent area `{parent}`.")
else:
lines.append(f"- `{area}`: review before changing linked areas.")
return lines or ["- none detected"]
def repository_area_paths(root: Path) -> list[str]:
areas: list[str] = []
for path in sorted(root.iterdir()):
if not path.is_dir():
continue
areas.append(f"{path.name}/")
for child in sorted(path.iterdir()):
if child.is_dir():
areas.append(f"{path.name}/{child.name}/")
return areas
def existing_context_files(root: Path, init_options: dict[str, Any], state: dict[str, Any]) -> list[str]:
paths: set[Path] = {root / "AGENTS.md"}
for value in CONTEXT_FILES.values():
target = safe_project_path(root, value)
if target is not None:
paths.add(target)
init_target = safe_project_path(root, init_options.get("context_file"))
if init_target is not None:
paths.add(init_target)
resolved = resolve_target(root, state, init_options)
paths.add(resolved)
return sorted(rel(root, path) for path in paths if path.exists())
def development_command_lines(root: Path) -> list[str]:
commands = package_script_lines(root)
if commands:
commands.append("- manifest commands over ad hoc equivalents")
return commands
return ["- none detected"]
def package_script_lines(root: Path) -> list[str]:
package_json = root / "package.json"
data = read_json(package_json)
scripts = data.get("scripts")
if not isinstance(scripts, dict):
return []
result: list[str] = []
for name in sorted(scripts):
value = scripts[name]
if not isinstance(value, str) or not value.strip():
continue
command = f"npm {name}" if name in {"start", "stop", "test", "restart"} else f"npm run {name}"
result.append(f"- `{command}` -> `{value.strip()}`")
return result
def read_json(path: Path) -> dict[str, Any]:
if not path.exists():
return {}
try:
data = json.loads(path.read_text(encoding="utf-8"))
except (json.JSONDecodeError, OSError, UnicodeDecodeError):
return {}
return data if isinstance(data, dict) else {}
def resolve_target(root: Path, state: dict[str, Any], init_options: dict[str, Any]) -> Path:
for value in (
init_options.get("context_file"),
CONTEXT_FILES.get(default_integration(state) or ""),
"AGENTS.md",
):
target = safe_project_path(root, value)
if target is not None:
return target
return root / "AGENTS.md"
def safe_project_path(root: Path, value: Any) -> Path | None:
if not isinstance(value, str) or not value.strip():
return None
raw = Path(value.strip())
candidate = raw if raw.is_absolute() else root / raw
try:
candidate.resolve(strict=False).relative_to(root.resolve())
except (OSError, ValueError):
return None
return candidate
def default_integration(state: dict[str, Any]) -> str | None:
for key in ("default_integration", "integration"):
value = state.get(key)
if isinstance(value, str) and value.strip():
return value.strip()
installed = state.get("installed_integrations")
if isinstance(installed, list):
for value in installed:
if isinstance(value, str) and value.strip():
return value.strip()
return None
def installed_integrations(state: dict[str, Any]) -> list[str]:
seen: set[str] = set()
values = state.get("installed_integrations")
if not isinstance(values, list):
values = []
default = default_integration(state)
ordered = ([default] if default else []) + values
result: list[str] = []
for value in ordered:
if not isinstance(value, str) or not value.strip():
continue
clean = value.strip()
if clean not in seen:
seen.add(clean)
result.append(clean)
return result
def render_projection(root: Path, target: Path, state: dict[str, Any], created_memory: bool) -> str:
source_text, source_label = governance_source(root, target)
default_key = default_integration(state) or "unknown"
installed = installed_integrations(state)
style = projection_style(target)
lines = [
MARKER_START,
"## Repository Governance",
"- SSOT: this managed section.",
f"- Target: {rel(root, target)}",
f"- Active integration: {default_key}",
f"- Refresh source: {source_label}",
f"- Cache: {MEMORY_PATH.as_posix()} ({'created' if created_memory else 'present'})",
"",
"## Scope",
"- agent collaboration rules",
"- tool and MCP permissions",
"- write boundaries",
"- skill invocation contracts",
"- project governance: external",
"",
"## Context",
f"- Installed integrations: {', '.join(installed) if installed else 'none'}",
f"- Skills: {', '.join(scan_skills(root)) or 'none'}",
f"- MCP configs: {', '.join(scan_mcp_configs(root)) or 'none'}",
f"- Extensions config: .specify/extensions.yml ({extensions_status(root)})",
"",
"## Repository Evidence",
*section_or_default(source_text, ["## Repository Evidence"], repository_evidence_default()),
"",
"## Repository Areas",
*section_or_default(source_text, ["## Repository Areas"], repository_areas_default()),
"",
"## Directory Governance",
*section_or_default(source_text, ["## Directory Governance"], directory_governance_default()),
"",
"## Development Commands",
*section_or_default(source_text, ["## Development Commands"], development_commands_default()),
"",
"## Authority",
"1. Current user instruction",
"2. Active `SPECKIT GOVERNANCE` section",
"3. User-authored repository instructions for agent behavior",
"4. Skill-local `SKILL.md`",
"5. Tool and MCP defaults",
"",
"## Repository Workflow",
"- Read: Repository Evidence",
"- Run: Development Commands",
"- Scope: active task only",
"- Preserve: user-authored edits",
"- Protected files: implementation, CI, MCP config, secrets, permissions, tool settings",
"- Protected-file writes: explicit user request only",
"- External writes: authorized target and action only",
"- Handoff: changed files, commands, validation, risks",
"",
"## Write Boundaries",
*section_or_default(source_text, ["## Write Boundaries"], write_boundary_default(style)),
"",
"## MCP And External Tools",
*section_or_default(source_text, ["## MCP And External Tools", "## MCP And External Tool Policy", "## MCP Policy"], mcp_default(style)),
"",
"## Skills",
*section_or_default(source_text, ["## Skills", "## Skill Usage Policy", "## Skill Contract"], skill_default(style)),
"",
"## Handoff",
*section_or_default(source_text, ["## Handoff", "## Required Handoff Report", "## Validation"], handoff_default(style)),
MARKER_END,
"",
]
return "\n".join(lines)
def write_projection(target: Path, projection: str) -> str:
existed = target.exists()
existing = target.read_text(encoding="utf-8-sig") if target.exists() else ""
updated = upsert_section(existing, projection)
if target.suffix == ".mdc":
updated = ensure_mdc_frontmatter(updated)
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text(normalize_newlines(updated), encoding="utf-8")
return "updated" if existed else "generated"
def upsert_section(content: str, projection: str) -> str:
start = content.find(MARKER_START)
end = content.find(MARKER_END, start if start != -1 else 0)
if start != -1 and end != -1 and end > start:
end += len(MARKER_END)
if end < len(content) and content[end] == "\r":
end += 1
if end < len(content) and content[end] == "\n":
end += 1
return content[:start] + projection + content[end:]
if content and not content.endswith("\n"):
content += "\n"
return content + ("\n" if content else "") + projection
def remove_stale_sections(root: Path, active: Path, init_options: dict[str, Any], state: dict[str, Any]) -> None:
paths = {root / "AGENTS.md"}
for value in CONTEXT_FILES.values():
target = safe_project_path(root, value)
if target is not None:
paths.add(target)
init_target = safe_project_path(root, init_options.get("context_file"))
if init_target is not None:
paths.add(init_target)
for path in paths:
if same_path(path, active):
continue
remove_section(path)
def remove_section(path: Path) -> None:
if not path.exists():
return
content = path.read_text(encoding="utf-8-sig")
start = content.find(MARKER_START)
end = content.find(MARKER_END, start if start != -1 else 0)
if start == -1 or end == -1 or end <= start:
return
removal_end = end + len(MARKER_END)
if removal_end < len(content) and content[removal_end] == "\r":
removal_end += 1
if removal_end < len(content) and content[removal_end] == "\n":
removal_end += 1
removal_start = start
if removal_start > 1 and content[removal_start - 1] == "\n" and content[removal_start - 2] == "\n":
removal_start -= 1
updated = normalize_newlines(content[:removal_start] + content[removal_end:])
if not updated.strip() or (path.suffix == ".mdc" and re.match(r"^---\n.*?\n---\s*$", updated, re.DOTALL)):
path.unlink()
else:
path.write_text(updated, encoding="utf-8")
def governance_source(root: Path, target: Path) -> tuple[str, str]:
managed = extract_managed_section(target)
if managed:
return managed, "active generated section"
memory = root / MEMORY_PATH
try:
return normalize_newlines(memory.read_text(encoding="utf-8-sig")), "initialization cache"
except (OSError, UnicodeDecodeError):
return "", "built-in defaults"
def section_or_default(source_text: str, headings: list[str], default: list[str]) -> list[str]:
for heading in headings:
section = extract_section_from_text(source_text, heading)
if section:
return section
return default
def repository_evidence_default() -> list[str]:
return ["- none captured"]
def repository_areas_default() -> list[str]:
return ["- none detected"]
def directory_governance_default() -> list[str]:
return [
"- Responsibility: one primary purpose per directory.",
"- Depth: 2.",
"- Coverage: include visible, hidden, generated, cache, config/env, tool, and agent directories.",
"- Mixed concerns: follow existing repo convention or split responsibility.",
"- Change impact: review linked code, tests, docs, config/env, data, assets, generated files, and tool outputs; update only when in scope and authorized.",
]
def development_commands_default() -> list[str]:
return ["- none recorded"]
def extract_section(path: Path, heading: str) -> list[str]:
try:
return extract_section_from_text(path.read_text(encoding="utf-8-sig"), heading)
except (OSError, UnicodeDecodeError):
return []
def extract_managed_section(path: Path) -> str:
try:
content = normalize_newlines(path.read_text(encoding="utf-8-sig"))
except (OSError, UnicodeDecodeError):
return ""
start = content.find(MARKER_START)
end = content.find(MARKER_END, start if start != -1 else 0)
if start == -1 or end == -1 or end <= start:
return ""
return content[start + len(MARKER_START) : end]
def extract_section_from_text(text: str, heading: str) -> list[str]:
lines = normalize_newlines(text).splitlines()
capture = False
result: list[str] = []
for line in lines:
if line.strip() == heading:
capture = True
continue
if capture and line.startswith("## "):
break
if capture and line.strip():
result.append(line)
return result
def projection_style(path: Path) -> str:
rel_path = path.as_posix()
if rel_path.endswith(".github/copilot-instructions.md"):
return "copilot"
if path.suffix == ".mdc" or "/rules/" in rel_path:
return "rule"
return "agent"
def style_lead(style: str) -> str:
if style == "copilot":
return "Use these as concise Copilot custom instructions for this repository."
if style == "rule":
return "Apply these repository rules before planning, editing, or using tools."
return "Follow these repository instructions when working in this project."
def write_boundary_default(style: str) -> list[str]:
if style == "rule":
return [
"- Stay inside the active task scope.",
"- Preserve user-authored edits.",
"- Preserve managed markers verbatim: `<!-- SPECKIT GOVERNANCE START -->` and `<!-- SPECKIT GOVERNANCE END -->`.",
]
return [
"- Keep edits inside the active task scope and preserve user changes.",
"- Preserve managed markers verbatim: `<!-- SPECKIT GOVERNANCE START -->` and `<!-- SPECKIT GOVERNANCE END -->`.",
]
def mcp_default(style: str) -> list[str]:
return ["- Read-only unless the user authorizes mutation.", "- External writes: target, action, expected effect."]
def skill_default(style: str) -> list[str]:
return [
"- Use active skill `SKILL.md`.",
"- Write scope: declared skill paths only.",
"- Repository-local skill specs should declare purpose, trigger, allowed read paths, allowed write paths, forbidden paths, outputs, and validation command.",
]
def handoff_default(style: str) -> list[str]:
return ["- changed files", "- commands run", "- validation result", "- unresolved risks"]
def scan_feature_specs(root: Path) -> str:
specs = root / "specs"
if not specs.is_dir():
return "none"
entries = []
for feature in sorted(path for path in specs.iterdir() if path.is_dir()):
statuses = [f"{name}:{'present' if (feature / name).exists() else 'missing'}" for name in ("spec.md", "plan.md", "tasks.md")]
entries.append(f"{rel(root, feature)} ({', '.join(statuses)})")
return ", ".join(entries) if entries else "none"
def scan_skills(root: Path) -> list[str]:
return sorted(rel(root, path) for path in root.rglob("SKILL.md") if not ignored(path))
def scan_mcp_configs(root: Path) -> list[str]:
names = {".mcp.json", "mcp.json", "mcp.yml", "mcp.yaml", "mcp.config.json"}
return sorted(
rel(root, path)
for path in root.rglob("*")
if path.is_file() and not ignored(path) and (path.name in names or "mcp" in path.name.lower())
)
def ignored(path: Path) -> bool:
return any(part in {".git", "__pycache__", ".venv", "node_modules"} for part in path.parts)
def extensions_status(root: Path) -> str:
path = root / ".specify/extensions.yml"
if not path.exists():
return "missing"
return "present"
def exists(root: Path, value: str) -> str:
return "present" if (root / value).exists() else "missing"
def ensure_mdc_frontmatter(content: str) -> str:
stripped = content.lstrip()
if not stripped.startswith("---"):
return "---\nalwaysApply: true\n---\n\n" + content
match = re.match(r"^(---[ \t]*\n)(.*?)(\n---[ \t]*)(\n|$)(.*)", stripped, re.DOTALL)
if not match:
return "---\nalwaysApply: true\n---\n\n" + content
opening, frontmatter, closing, sep, rest = match.groups()
if re.search(r"(?m)^[ \t]*alwaysApply[ \t]*:[ \t]*true[ \t]*$", frontmatter):
return content
if re.search(r"(?m)^[ \t]*alwaysApply[ \t]*:", frontmatter):
frontmatter = re.sub(r"(?m)^([ \t]*)alwaysApply[ \t]*:.*$", r"\1alwaysApply: true", frontmatter, count=1)
elif frontmatter.strip():
frontmatter += "\nalwaysApply: true"
else:
frontmatter = "alwaysApply: true"
return f"{opening}{frontmatter}{closing}{sep}{rest}"
def same_path(left: Path, right: Path) -> bool:
try:
return left.resolve(strict=False) == right.resolve(strict=False)
except OSError:
return left.absolute() == right.absolute()
def rel(root: Path, path: Path) -> str:
try:
return path.relative_to(root).as_posix()
except ValueError:
return path.as_posix()
def normalize_newlines(content: str) -> str:
return content.replace("\r\n", "\n").replace("\r", "\n")
if __name__ == "__main__":
raise SystemExit(main())

View File

@@ -0,0 +1,53 @@
# Agent Governance Cache
<!--
Sync Impact Report
-->
## Final Output
- active agent platform governance file
- managed `SPECKIT GOVERNANCE` section
- cache: internal
## Directory Governance
- Responsibility: one primary purpose per directory.
- Depth: 2.
- Coverage: include visible, hidden, generated, cache, config/env, tool, and agent directories.
- Mixed concerns: follow existing repo convention or split responsibility.
- Change impact: review linked code, tests, docs, config/env, data, assets, generated files, and tool outputs; update only when in scope and authorized.
## Scope
- agent collaboration rules
- tool and MCP permissions
- write boundaries
- skill invocation contracts
- project governance: external
## Write Boundaries
- Scope: active task only
- Preserve: user-authored edits
- Preserve managed markers verbatim: `<!-- SPECKIT GOVERNANCE START -->` and `<!-- SPECKIT GOVERNANCE END -->`
- Protected files: implementation, CI, MCP config, secrets, permissions, tool settings
- Protected-file writes: explicit user request only
## Skill Contract
- Repository-local skill specs should declare purpose, trigger, allowed read paths, allowed write paths, forbidden paths, outputs, and validation command.
## MCP Policy
- Default: read-only
- Mutation: explicit user intent
- External writes: target, action, result
- Secrets: never log, never write
## Validation
- changed files
- commands run
- tests/validation result
- unresolved risks

View File

0
.specify/extensions/verify/scripts/bash/load-config.sh Normal file → Executable file
View File

View File

@@ -1,9 +1,9 @@
{
"ai": "opencode",
"ai": "copilot",
"branch_numbering": "timestamp",
"context_file": "AGENTS.md",
"context_file": ".github/copilot-instructions.md",
"here": true,
"integration": "opencode",
"integration": "copilot",
"script": "sh",
"speckit_version": "0.8.8.dev0"
}

View File

@@ -1,15 +1,15 @@
{
"version": "0.8.8.dev0",
"version": "0.8.13",
"integration_state_schema": 1,
"installed_integrations": [
"opencode"
"copilot"
],
"integration_settings": {
"opencode": {
"copilot": {
"script": "sh",
"invoke_separator": "."
}
},
"integration": "opencode",
"default_integration": "opencode"
"integration": "copilot",
"default_integration": "copilot"
}

View File

@@ -1,7 +1,7 @@
{
"integration": "copilot",
"version": "0.8.8.dev0",
"installed_at": "2026-05-07T18:49:21.970795+00:00",
"version": "0.8.13",
"installed_at": "2026-05-21T18:50:11.969212+00:00",
"files": {
".github/agents/speckit.analyze.agent.md": "699032fdd49afe31d23c7191f3fe7bcb1d14b081fbc94c2287e6ba3a57574fda",
".github/agents/speckit.checklist.agent.md": "d7d691689fe45427c868dcf18ade4df500f0c742a6c91923fefba405d6466dde",

View File

@@ -1,16 +0,0 @@
{
"integration": "opencode",
"version": "0.8.8.dev0",
"installed_at": "2026-05-07T18:50:21.381460+00:00",
"files": {
".opencode/command/speckit.analyze.md": "699032fdd49afe31d23c7191f3fe7bcb1d14b081fbc94c2287e6ba3a57574fda",
".opencode/command/speckit.checklist.md": "d7d691689fe45427c868dcf18ade4df500f0c742a6c91923fefba405d6466dde",
".opencode/command/speckit.clarify.md": "0cc766dcc5cab233ccdf3bc4cfb5759a6d7d1e13e29f611083046f818f5812bb",
".opencode/command/speckit.constitution.md": "58d35eb026f56bb7364d91b8b0382d5dd1249ded6c1449a2b69546693afb85f7",
".opencode/command/speckit.implement.md": "2acb475f761e5b65319c4e71847bd07b88c933b45da7be45e7801271f64fcd4d",
".opencode/command/speckit.plan.md": "5b1e9c9b5a26a1877fe3b655a9350562cf5ee88788f9030e6b8a9dc1de88b347",
".opencode/command/speckit.specify.md": "c7b1ab7ceafc42607e86dd6c0dab0b5cb74462a93a3cdd3b5e7173468cc88bdf",
".opencode/command/speckit.tasks.md": "6b42e295fb67082392b4b62febf297c73655ea67cc9379cd5df80468e920cb4c",
".opencode/command/speckit.taskstoissues.md": "e84794f7a839126defb364ca815352c5c2b2d20db2d6da399fa53e4ddbb7b3ee"
}
}

View File

@@ -1,6 +1,6 @@
{
"integration": "speckit",
"version": "0.8.8.dev0",
"version": "0.8.13",
"installed_at": "2026-05-07T18:46:46.194118+00:00",
"files": {
".specify/scripts/bash/common.sh": "dd638316259e699fd466542c77ef16af5eb198efe0447c081f86b890db414ba8",
@@ -10,8 +10,8 @@
".specify/scripts/bash/create-new-feature.sh": "bcf4964ca0c6c78717bb42d9e66b8c7e5ee82779cd96afc5aa7b08b75abe5790",
".specify/templates/constitution-template.md": "ce7549540fa45543cca797a150201d868e64495fdff39dc38246fb17bd4024b3",
".specify/templates/checklist-template.md": "312eee8291dfa984b21f95ddd0ca778e7a1f0b3a64bfc470d79762a3e3f5d7b8",
".specify/templates/tasks-template.md": "5da92ac1fbf5be2f9018a5064497995bf3592761ccb6b3951503c63d851297e8",
".specify/templates/spec-template.md": "785dc50d856dd92d6515eca0761e16dce0c9ba0a3cd07154fd33eae77932422a",
".specify/templates/plan-template.md": "873e84b226fe3d24afe28046931b20db9bbb9210366428dc958a515349ed6e68"
".specify/templates/tasks-template.md": "c731575d8099b3f871861186fbd1a592b51b2ba57fb99e1a0dab439ff6d5608f",
".specify/templates/spec-template.md": "3945437fc35cd30a5b2bf7beea680337c3516826d3efa5a6b92c4a7eca1ba28e",
".specify/templates/plan-template.md": "3fdc12da2eb157def636948c157bfb638b265e70b2e3246a0e09c8d5db710e91"
}
}

View File

@@ -0,0 +1,84 @@
# Agent Governance Cache
<!--
Sync Impact Report
-->
## Final Output
- active agent platform governance file
- managed `SPECKIT GOVERNANCE` section
- cache: internal
## Directory Governance
- Responsibility: one primary purpose per directory.
- Depth: 2.
- Coverage: include visible, hidden, generated, cache, config/env, tool, and agent directories.
- Mixed concerns: follow existing repo convention or split responsibility.
- Change impact: review linked code, tests, docs, config/env, data, assets, generated files, and tool outputs; update only when in scope and authorized.
## Repository Evidence
- README: `README.md`
- Package manifest: `Gemfile`, `build.gradle.kts`
- Lockfiles: `Gemfile.lock`
- Task runners: none detected
- CI workflows: `.github/workflows/create-or-promote-release.yml`, `.github/workflows/dependency-submission.yml`, `.github/workflows/docs-deploy.yml`, `.github/workflows/docs-governance.yml`, `.github/workflows/docs-release.yml`, `.github/workflows/main-check.yml`, `.github/workflows/merge-queue.yml`, `.github/workflows/models_issue_triage.yml`, `.github/workflows/models_pr_triage.yml`, `.github/workflows/moderate.yml`, `.github/workflows/post-release-cleanup.yml`, `.github/workflows/pr_enforce_labels.yml`, `.github/workflows/promote.yml`, `.github/workflows/publish-core.yml`, `.github/workflows/pull-request-target.yml`, `.github/workflows/pull-request.yml`, `.github/workflows/release.yml`, `.github/workflows/reusable-check.yml`, `.github/workflows/scheduled-updates.yml`, `.github/workflows/stale.yml`, `.github/workflows/sync-android-docs.yml`, `.github/workflows/update-changelog.yml`
- Source paths: `app/`, `scripts/`
- Test paths: `specs/`
- Repository areas: (see "Repository Areas" section below for top-level listing)
- Existing agent context files: `.github/copilot-instructions.md`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`
- Repository-local skills: `.agent_refs/mqttastic-client-kmp/.github/skills/mqtt-kmp/SKILL.md`, `.skills/ci-cost-control/SKILL.md`, `.skills/code-review/SKILL.md`, `.skills/compose-ui/SKILL.md`, `.skills/design-standards/SKILL.md`, `.skills/implement-feature/SKILL.md`, `.skills/kmp-architecture/SKILL.md`, `.skills/navigation-and-di/SKILL.md`, `.skills/new-branch/SKILL.md`, `.skills/project-overview/SKILL.md`, `.skills/speckit/SKILL.md`, `.skills/testing-ci/SKILL.md`
- MCP configs: `.agent_refs/firmware/src/modules/Telemetry/Sensor/MCP9808Sensor.cpp`, `.agent_refs/firmware/src/modules/Telemetry/Sensor/MCP9808Sensor.h`, `androidApp/build/intermediates/incremental/googleDebug-mergeJavaRes/zip-cache/ut0r9CiGRq6mCprTK2blRg==`, `app/build/intermediates/incremental/fdroidDebug-mergeJavaRes/zip-cache/mcpnRT6ZHkD92YpTv5y52w==`, `app/build/intermediates/incremental/googleDebug-mergeJavaRes/zip-cache/mcpnRT6ZHkD92YpTv5y52w==`, `app/build/intermediates/incremental/googleDebug-mergeJavaRes/zip-cache/ut0r9CiGRq6mCprTK2blRg==`
- Active integration: `copilot`
- Resolved context file: `AGENTS.md`
## Repository Areas
**Policy**: Subdirectories inherit parent area governance rules. When modifying a subdirectory,
review the parent area's context for impact. Top-level directories require review before
changing linked areas; child directories change with their parent.
**Top-level areas requiring review**: `.agent_memory/`, `.agent_plans/`, `.agent_refs/`,
`.github/`, `.specify/`, `androidApp/`, `app/`, `build-logic/`, `config/`, `core/`,
`desktop/`, `desktopApp/`, `docs/`, `docs-site/`, `fastlane/`, `feature/`, `gradle/`,
`ios/`, `iosApp/`, `offline-repository/`, `screenshot-tests/`, `scripts/`, `specs/`
## Development Commands
- none detected
## Scope
- agent collaboration rules
- tool and MCP permissions
- write boundaries
- skill invocation contracts
- project governance: external
## Write Boundaries
- Scope: active task only
- Preserve: user-authored edits
- Preserve managed markers verbatim: `<!-- SPECKIT GOVERNANCE START -->` and `<!-- SPECKIT GOVERNANCE END -->`
- Protected files: implementation, CI, MCP config, secrets, permissions, tool settings
- Protected-file writes: explicit user request only
## Skill Contract
- Repository-local skill specs should declare purpose, trigger, allowed read paths, allowed write paths, forbidden paths, outputs, and validation command.
## MCP Policy
- Default: read-only
- Mutation: explicit user intent
- External writes: target, action, result
- Secrets: never log, never write
## Validation
- changed files
- commands run
- tests/validation result
- unresolved risks

View File

@@ -1,17 +1,14 @@
<!--
SYNC IMPACT REPORT
==================
Version change: 1.2.0 → 1.3.0
Version change: 1.3.1 → 1.3.2
Modified principles:
- VI. Verify Before Push → renumbered to VII.
Added sections:
- VI. Documentation Freshness (new principle requiring last_updated frontmatter,
blocking staleness check, link validation, coverage checks, freshness warnings)
- IVII: Rationale blocks compressed into HTML comments (no semantic change)
Modified sections: None.
Added sections: None.
Removed sections: None.
Templates requiring updates:
- .specify/templates/checklist-template.md — Add CHK006 for documentation freshness
- .specify/templates/plan-template.md — Constitution Check VII for docs freshness
Follow-up TODOs: Update AGENTS.md with docs governance reference.
Templates requiring updates: None (no principle renumbering).
Follow-up TODOs: None.
-->
# Meshtastic Android (KMP) Constitution
@@ -28,9 +25,7 @@ MUST be used in place of JVM/Android-specific APIs:
- MUST NOT import `java.*` or `android.*` in any `commonMain` module.
- Platform-specific implementations belong in `androidMain`/`desktopMain` actual
declarations only.
- Rationale: The project goal is multi-platform parity (Android, Desktop, iOS). Framework
bleed in `commonMain` breaks compilability on non-Android targets and undermines the
entire decoupling effort.
<!-- Rationale: Multi-platform parity (Android, Desktop, iOS). Framework bleed in commonMain breaks compilability on non-Android targets. -->
### II. Zero Lint Tolerance
@@ -39,8 +34,7 @@ All code contributions MUST pass static analysis before merge:
- `./gradlew spotlessApply` MUST be run and `spotlessCheck` MUST pass with no violations.
- `detekt` MUST pass with no new violations introduced.
- A task or PR is considered incomplete if either check fails.
- Rationale: Consistent code style and static analysis gates prevent technical debt
accumulation and catch bugs that tests alone miss.
<!-- Rationale: Consistent code style and static analysis gates prevent technical debt accumulation. -->
### III. Compose Multiplatform UI
@@ -51,8 +45,7 @@ All UI MUST use JetBrains Compose Multiplatform, not Android-only Jetpack Compos
- Floats MUST be pre-formatted using `NumberFormatter.format()` before display in any
composable.
- UI MUST compile and render correctly on all supported targets (Android, Compose Desktop).
- Rationale: Compose Multiplatform ensures UI consistency across platforms and enforces the
project's multi-platform architecture goal.
<!-- Rationale: Compose Multiplatform ensures UI consistency across platforms. -->
### IV. Privacy First
@@ -65,8 +58,7 @@ times:
circumstances.
- `core/proto` is a read-only upstream submodule (`meshtastic/protobufs`). MUST NOT modify
`.proto` files directly; proto changes require an upstream issue labeled `upstream`.
- Rationale: Meshtastic users rely on the mesh for private, off-grid communications. Data
leaks could endanger users in sensitive or adversarial deployments.
<!-- Rationale: Meshtastic users rely on the mesh for private, off-grid communications. Data leaks could endanger users in sensitive deployments. -->
### V. Design Standards Compliance
@@ -74,8 +66,8 @@ All user-facing UI MUST conform to the Meshtastic Client Design Standards:
- The canonical reference lives at:
`https://raw.githubusercontent.com/meshtastic/design/refs/heads/master/standards/meshtastic_design_standards_latest.md`
- New screens and significant UI changes MUST be reviewed against the design standards
before merge.
- New screens and significant UI changes (any screen with ≥3 composables or a new
navigation destination) MUST be reviewed against the design standards before merge.
- Deviations from the design standards require explicit justification in the PR description
with a rationale for why the standard cannot or should not be followed.
- Features that affect multiple platforms (messaging, settings, telemetry, etc.) MUST
@@ -84,9 +76,7 @@ All user-facing UI MUST conform to the Meshtastic Client Design Standards:
or create one using the `TEMPLATE.md` in that directory before writing the
Android implementation spec. Platform-specific-only features (e.g., Android widget,
Wear OS tile) may mark the `Cross-Platform Spec` field as N/A with justification.
- Rationale: Consistent cross-platform UX across Android, iOS, and other clients ensures
users have a predictable experience regardless of platform. The design standards are
maintained collaboratively across all Meshtastic client teams.
<!-- Rationale: Consistent cross-platform UX ensures users have a predictable experience regardless of platform. -->
### VI. Documentation Freshness
@@ -118,9 +108,7 @@ Governance rules:
- Image references MUST use root-relative paths (`/assets/screenshots/filename.png`) so
they resolve correctly in both Jekyll and the in-app renderer. The sync script rewrites
these to Docusaurus paths automatically.
- Rationale: Documentation that drifts from the implementation misleads users, increases
support burden, and undermines the in-app help experience. Three distinct consumers
means a single source change must be verified across all delivery channels.
<!-- Rationale: Documentation drift misleads users and increases support burden. Three distinct consumers means changes must be verified across all delivery channels. -->
### VII. Verify Before Push
@@ -131,26 +119,15 @@ Local verification MUST complete successfully before any `git push`:
- After pushing, CI status MUST be confirmed via `gh pr checks <PR>` or
`gh run list --branch <branch> --limit 5`. Phrases like "CI should be green" are
explicitly prohibited.
- Rationale: CI has failed repeatedly due to skipped local checks. Verification is a hard
gate, not an optimistic assumption.
<!-- Rationale: Verification is a hard gate, not an optimistic assumption. Skipped local checks are the leading cause of CI failures. -->
## Development Workflow
The following workflow steps are non-negotiable for all contributors and agents:
- **Bootstrap First**: The mandatory bootstrap steps in `.skills/project-overview/SKILL.md`
MUST be executed before any build operation in a new session.
- **Baseline Verification**: Before any PR is opened or pushed, run:
`./gradlew spotlessApply spotlessCheck detekt assembleDebug test allTests`
- **String Resources**: After adding any string resource, run
`python3 scripts/sort-strings.py` to maintain alphabetical organization and regenerate
`strings-index.txt`. Consult `strings-index.txt` before reading large string files.
- **Memory Persistence**: `.agent_memory/session_context.md` MUST be updated at the end of
every agent session or major task to preserve context across sessions.
- **Plan Before Execution**: Complex refactors MUST have a plan written in `.agent_plans/`
(git-ignored) before execution begins.
- **Context Discipline**: Agents MUST NOT read binary files (PNG, MP3, etc.) or vacuum the
entire codebase for localized fixes. Limit context reads to relevant modules.
Non-negotiable workflow steps are defined in `AGENTS.md` `<process_essentials>`. Key
requirements: bootstrap before build, baseline verification before push, sort-strings after
adding resources, update `.agent_memory/session_context.md` per session, plan complex
refactors (touching ≥3 modules or >200 LOC changed) in `.agent_plans/`, limit context
reads to relevant modules.
## Architecture Constraints
@@ -170,12 +147,27 @@ The following module boundaries and technology choices are fixed for this projec
- **Language & Toolchain**: Kotlin 2.3+ targeting JDK 21. Java source files MUST NOT be
introduced in KMP modules.
## Operational Standards
The following coding standards are enforced by contextual instruction files
(`.github/instructions/`) scoped to relevant source sets. They are acknowledged by this
constitution but defined and maintained in their respective files:
- `safeCatching {}` over `runCatching {}` in coroutine/suspend contexts
- `org.meshtastic.core.common.util.ioDispatcher` over `Dispatchers.IO`
- `MeshtasticIcons` (from `core/ui/icon/`) over `material.icons.Icons`
- `MetricFormatter` for display strings (temperature, voltage, percent, signal)
- `stringResource(Res.string.key)` with `python3 scripts/sort-strings.py` after additions
- `kotlinx.coroutines.CancellationException` (not `kotlin.coroutines.cancellation.*`)
- Branch naming: `feat/`, `fix/`, `chore/`, `docs/`, `build/`, `ci/`, `refactor/`,
`test/`, `deps/`, or numeric spec prefix; always off `origin/main`
## Governance
This constitution supersedes all other practices, coding guidelines, and agent instructions.
`AGENTS.md` is the authoritative source of truth. The files
`.github/copilot-instructions.md`, `CLAUDE.md`, and `GEMINI.md` MUST redirect to
`AGENTS.md` and MUST NOT diverge from it.
This constitution is the canonical governance document and supersedes all other practices,
coding guidelines, and agent instructions. `AGENTS.md` is the agent-facing operational
summary derived from this constitution. The files `.github/copilot-instructions.md`,
`CLAUDE.md`, and `GEMINI.md` MUST redirect to `AGENTS.md` and MUST NOT diverge from it.
**Amendment Procedure**:
1. Propose the amendment with rationale and a migration plan in a PR description.
@@ -197,4 +189,4 @@ This constitution supersedes all other practices, coding guidelines, and agent i
Constitution Check confirming all seven principles were evaluated. Complexity violations
require explicit justification in the Complexity Tracking table of the plan document.
**Version**: 1.3.0 | **Ratified**: 2026-05-07 | **Last Amended**: 2026-05-13
**Version**: 1.3.2 | **Ratified**: 2026-05-07 | **Last Amended**: 2026-05-21

View File

@@ -0,0 +1,4 @@
{
"cached_at": "2026-05-21T18:52:11.605092+00:00",
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/presets/catalog.community.json"
}

View File

@@ -0,0 +1,577 @@
{
"schema_version": "1.0",
"updated_at": "2026-05-05T10:00:00Z",
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/presets/catalog.community.json",
"presets": {
"a11y-governance": {
"name": "A11Y Governance",
"id": "a11y-governance",
"version": "0.2.0",
"description": "Adds accessibility, bilingual DE/EN delivery, CEFR-B2 readability, and inclusive-content governance to Spec Kit.",
"author": "Thorsten Hindermann",
"repository": "https://github.com/hindermath/spec-kit-preset-a11y-governance",
"download_url": "https://github.com/hindermath/spec-kit-preset-a11y-governance/archive/refs/tags/v0.2.0.zip",
"homepage": "https://github.com/hindermath/spec-kit-preset-a11y-governance",
"documentation": "https://github.com/hindermath/spec-kit-preset-a11y-governance/blob/main/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.8.0"
},
"provides": {
"templates": 9,
"commands": 3
},
"tags": [
"a11y",
"accessibility",
"bilingual",
"wcag",
"inclusion"
],
"created_at": "2026-04-27T00:00:00Z",
"updated_at": "2026-04-27T00:00:00Z"
},
"agent-parity-governance": {
"name": "Agent Parity Governance",
"id": "agent-parity-governance",
"version": "0.1.0",
"description": "Keeps shared AI-agent guidance aligned across a project-defined set of agent instruction surfaces.",
"author": "Thorsten Hindermann",
"repository": "https://github.com/hindermath/spec-kit-preset-agent-parity-governance",
"download_url": "https://github.com/hindermath/spec-kit-preset-agent-parity-governance/archive/refs/tags/v0.1.0.zip",
"homepage": "https://github.com/hindermath/spec-kit-preset-agent-parity-governance",
"documentation": "https://github.com/hindermath/spec-kit-preset-agent-parity-governance/blob/main/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.8.0"
},
"provides": {
"templates": 6,
"commands": 3
},
"tags": [
"agents",
"governance",
"parity",
"agent-guidance",
"multi-agent"
],
"created_at": "2026-04-27T00:00:00Z",
"updated_at": "2026-04-27T00:00:00Z"
},
"aide-in-place": {
"name": "AIDE In-Place Migration",
"id": "aide-in-place",
"version": "1.0.0",
"description": "Adapts the AIDE workflow for in-place technology migrations (X \u2192 Y pattern). Overrides vision, roadmap, progress, and work item commands with migration-specific guidance.",
"author": "mnriem",
"repository": "https://github.com/mnriem/spec-kit-presets",
"download_url": "https://github.com/mnriem/spec-kit-presets/releases/download/aide-in-place-v1.0.0/aide-in-place.zip",
"homepage": "https://github.com/mnriem/spec-kit-presets",
"documentation": "https://github.com/mnriem/spec-kit-presets/blob/main/aide-in-place/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.2.0",
"extensions": [
"aide"
]
},
"provides": {
"templates": 2,
"commands": 8
},
"tags": [
"migration",
"in-place",
"brownfield",
"aide"
]
},
"architecture-governance": {
"name": "Architecture Governance",
"id": "architecture-governance",
"version": "0.2.0",
"description": "Adds secure architecture governance, threat modeling, STRIDE/CAPEC, Zero Trust, S-ADRs, and OWASP SAMM to Spec Kit.",
"author": "Thorsten Hindermann",
"repository": "https://github.com/hindermath/spec-kit-preset-architecture-governance",
"download_url": "https://github.com/hindermath/spec-kit-preset-architecture-governance/archive/refs/tags/v0.2.0.zip",
"homepage": "https://github.com/hindermath/spec-kit-preset-architecture-governance",
"documentation": "https://github.com/hindermath/spec-kit-preset-architecture-governance/blob/main/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.8.0"
},
"provides": {
"templates": 11,
"commands": 3
},
"tags": [
"architecture",
"governance",
"threat-modeling",
"stride",
"zero-trust"
],
"created_at": "2026-04-27T00:00:00Z",
"updated_at": "2026-04-27T00:00:00Z"
},
"canon-core": {
"name": "Canon Core",
"id": "canon-core",
"version": "0.1.0",
"description": "Adapts original Spec Kit workflow to work together with Canon extension.",
"author": "Maxim Stupakov",
"download_url": "https://github.com/maximiliamus/spec-kit-canon/releases/download/v0.1.0/spec-kit-canon-core-v0.1.0.zip",
"repository": "https://github.com/maximiliamus/spec-kit-canon",
"homepage": "https://github.com/maximiliamus/spec-kit-canon",
"documentation": "https://github.com/maximiliamus/spec-kit-canon/blob/master/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.4.3"
},
"provides": {
"templates": 2,
"commands": 8
},
"tags": [
"baseline",
"canon",
"spec-first"
]
},
"claude-ask-questions": {
"name": "Claude AskUserQuestion",
"id": "claude-ask-questions",
"version": "1.0.0",
"description": "Upgrades /speckit.clarify and /speckit.checklist on Claude Code from Markdown-table prompts to the native AskUserQuestion picker, with a recommended option and reasoning on every question.",
"author": "0xrafasec",
"repository": "https://github.com/0xrafasec/spec-kit-preset-claude-ask-questions",
"download_url": "https://github.com/0xrafasec/spec-kit-preset-claude-ask-questions/archive/refs/tags/v1.0.0.zip",
"homepage": "https://github.com/0xrafasec/spec-kit-preset-claude-ask-questions",
"documentation": "https://github.com/0xrafasec/spec-kit-preset-claude-ask-questions/blob/main/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.6.0"
},
"provides": {
"templates": 0,
"commands": 2
},
"tags": [
"claude",
"ask-user-question",
"clarify",
"checklist"
],
"created_at": "2026-04-13T00:00:00Z",
"updated_at": "2026-04-13T00:00:00Z"
},
"cross-platform-governance": {
"name": "Cross-Platform Governance",
"id": "cross-platform-governance",
"version": "0.1.0",
"description": "Adds Bash and PowerShell parity, dry-run/WhatIf parity, man-page expectations, and Verb-Noun Cmdlet discipline.",
"author": "Thorsten Hindermann",
"repository": "https://github.com/hindermath/spec-kit-preset-cross-platform-governance",
"download_url": "https://github.com/hindermath/spec-kit-preset-cross-platform-governance/archive/refs/tags/v0.1.0.zip",
"homepage": "https://github.com/hindermath/spec-kit-preset-cross-platform-governance",
"documentation": "https://github.com/hindermath/spec-kit-preset-cross-platform-governance/blob/main/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.8.0"
},
"provides": {
"templates": 8,
"commands": 3
},
"tags": [
"cross-platform",
"bash",
"powershell",
"man-page",
"cmdlet"
],
"created_at": "2026-04-27T00:00:00Z",
"updated_at": "2026-04-27T00:00:00Z"
},
"explicit-task-dependencies": {
"name": "Explicit Task Dependencies",
"id": "explicit-task-dependencies",
"version": "1.0.0",
"description": "Adds explicit (depends on T###) dependency declarations and an Execution Wave DAG to tasks.md for dependency-resolved parallel scheduling",
"author": "Quratulain-bilal",
"repository": "https://github.com/Quratulain-bilal/spec-kit-preset-explicit-task-dependencies",
"download_url": "https://github.com/Quratulain-bilal/spec-kit-preset-explicit-task-dependencies/archive/refs/tags/v1.0.0.zip",
"homepage": "https://github.com/Quratulain-bilal/spec-kit-preset-explicit-task-dependencies",
"documentation": "https://github.com/Quratulain-bilal/spec-kit-preset-explicit-task-dependencies/blob/main/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.4.0"
},
"provides": {
"templates": 1,
"commands": 1
},
"tags": [
"dependencies",
"parallel",
"scheduling",
"wave-dag"
]
},
"fiction-book-writing": {
"name": "Fiction Book Writing",
"id": "fiction-book-writing",
"version": "1.7.0",
"description": "Spec-Driven Development for novel and long-form fiction. 27 AI commands from idea to submission: story bible governance, 9 POV modes, all major plot structure frameworks, scene-by-scene drafting with quality gates, audiobook pipeline (SSML/ElevenLabs), cover design, sensitivity review, pacing and prose statistics, and pandoc-based export to DOCX/EPUB/LaTeX. Two style modes: author voice sample extraction or humanized-AI prose with 5 craft profiles. 12 languages supported. Support for offline semantic search.",
"author": "Andreas Daumann",
"repository": "https://github.com/adaumann/speckit-preset-fiction-book-writing",
"download_url": "https://github.com/adaumann/speckit-preset-fiction-book-writing/archive/refs/tags/v1.7.0.zip",
"homepage": "https://github.com/adaumann/speckit-preset-fiction-book-writing",
"documentation": "https://github.com/adaumann/speckit-preset-fiction-book-writing/blob/main/fiction-book-writing/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.5.0"
},
"provides": {
"templates": 22,
"commands": 27,
"scripts": 2
},
"tags": [
"writing",
"novel",
"fiction",
"storytelling",
"creative-writing",
"kdp",
"multi-pov",
"export",
"book",
"brainstorming",
"roleplay",
"audiobook",
"language-support"
],
"created_at": "2026-04-09T08:00:00Z",
"updated_at": "2026-04-27T08:00:00Z"
},
"game-narrative-writing": {
"name": "Game Narrative Writing",
"id": "game-narrative-writing",
"version": "1.0.0",
"description": "Spec-Driven Development for interactive game-narrative pre-production in video games. Authors write in a portable generic format, Twine/Sugarcube (.twee) or Ink (.ink). Covers choice-IF, visual novels, and branching dialogue. Supports Tier 1 mechanic hooks (flag, counter, inventory, timer, trust, currency, npc_state, ending_condition), multi-ending design, series carry-over variable registry, and NPC-focused character architecture.",
"author": "Andreas Daumann",
"repository": "https://github.com/adaumann/speckit-preset-game-narrative-writing",
"download_url": "https://github.com/adaumann/speckit-preset-game-narrative-writing/archive/refs/tags/v1.0.0.zip",
"homepage": "https://github.com/adaumann/speckit-preset-game-narrative-writing",
"documentation": "https://github.com/adaumann/speckit-preset-game-narrative-writing/blob/main/game-narrative-writing/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.5.0"
},
"provides": {
"templates": 22,
"commands": 36,
"scripts": 2
},
"tags": [
"game-writing",
"interactive-fiction",
"twine",
"ink",
"renpy",
"point-and-click",
"branching-narrative",
"choice-if",
"visual-novel",
"mechanic-hooks",
"game-narrative",
"export",
"series"
],
"created_at": "2026-05-05T08:00:00Z",
"updated_at": "2026-05-05T08:00:00Z"
},
"isaqb-architecture-governance": {
"name": "iSAQB Architecture Governance",
"id": "isaqb-architecture-governance",
"version": "0.1.0",
"description": "Adds general iSAQB/CPSA-F and arc42 architecture governance, including views, quality scenarios, ADRs, risks, and technical debt.",
"author": "Thorsten Hindermann",
"repository": "https://github.com/hindermath/spec-kit-preset-isaqb-architecture-governance",
"download_url": "https://github.com/hindermath/spec-kit-preset-isaqb-architecture-governance/archive/refs/tags/v0.1.0.zip",
"homepage": "https://github.com/hindermath/spec-kit-preset-isaqb-architecture-governance",
"documentation": "https://github.com/hindermath/spec-kit-preset-isaqb-architecture-governance/blob/main/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.8.0"
},
"provides": {
"templates": 13,
"commands": 3
},
"tags": [
"architecture",
"governance",
"isaqb",
"arc42",
"adr"
],
"created_at": "2026-04-27T00:00:00Z",
"updated_at": "2026-04-27T00:00:00Z"
},
"jira": {
"name": "Jira Issue Tracking",
"id": "jira",
"version": "1.0.0",
"description": "Overrides speckit.taskstoissues to create Jira epics, stories, and tasks instead of GitHub Issues via Atlassian MCP tools.",
"author": "luno",
"repository": "https://github.com/luno/spec-kit-preset-jira",
"download_url": "https://github.com/luno/spec-kit-preset-jira/archive/refs/tags/v1.0.0.zip",
"homepage": "https://github.com/luno/spec-kit-preset-jira",
"documentation": "https://github.com/luno/spec-kit-preset-jira/blob/main/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.1.0"
},
"provides": {
"templates": 0,
"commands": 1
},
"tags": [
"jira",
"atlassian",
"issue-tracking",
"preset"
],
"created_at": "2026-04-15T00:00:00Z",
"updated_at": "2026-04-15T00:00:00Z"
},
"mde": {
"name": "Model Driven Engineering",
"id": "mde",
"version": "0.5.1",
"description": "Focuses on streamlined commands, app repository support, cross-spec support, and capability-aware project memory for model-driven engineering workflows.",
"author": "Ralph Hanna",
"repository": "https://github.com/AI-MDE/spec-kit-preset-mde",
"download_url": "https://github.com/AI-MDE/spec-kit-preset-mde/archive/refs/tags/v0.5.1.zip",
"homepage": "https://github.com/AI-MDE/spec-kit-preset-mde",
"documentation": "https://github.com/AI-MDE/spec-kit-preset-mde/blob/main/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.1.0",
"extensions": [
"mde"
]
},
"provides": {
"templates": 6,
"commands": 11
},
"tags": [
"model-driven-engineering",
"software-lifecycle",
"business-analysis",
"business-application",
"multi-layered-architecture"
],
"created_at": "2026-05-08T00:00:00Z",
"updated_at": "2026-05-08T00:00:00Z"
},
"multi-repo-branching": {
"name": "Multi-Repo Branching",
"id": "multi-repo-branching",
"version": "1.0.0",
"description": "Coordinates feature branch creation across multiple git repositories (independent repos and submodules) during plan and tasks phases.",
"author": "sakitA",
"repository": "https://github.com/sakitA/spec-kit-preset-multi-repo-branching",
"download_url": "https://github.com/sakitA/spec-kit-preset-multi-repo-branching/archive/refs/tags/v1.0.0.zip",
"homepage": "https://github.com/sakitA/spec-kit-preset-multi-repo-branching",
"documentation": "https://github.com/sakitA/spec-kit-preset-multi-repo-branching/blob/master/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.4.0"
},
"provides": {
"templates": 0,
"commands": 2
},
"tags": [
"multi-repo-branching",
"multi-module",
"submodules",
"monorepo"
],
"created_at": "2026-04-09T00:00:00Z",
"updated_at": "2026-04-09T00:00:00Z"
},
"pirate": {
"name": "Pirate Speak (Full)",
"id": "pirate",
"version": "1.0.0",
"description": "Arrr! Transforms all Spec Kit output into pirate speak. Specs, plans, and tasks be written fer scallywags.",
"author": "mnriem",
"repository": "https://github.com/mnriem/spec-kit-presets",
"download_url": "https://github.com/mnriem/spec-kit-presets/releases/download/pirate-v1.0.0/pirate.zip",
"homepage": "https://github.com/mnriem/spec-kit-presets",
"documentation": "https://github.com/mnriem/spec-kit-presets/blob/main/pirate/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.1.0"
},
"provides": {
"templates": 6,
"commands": 9
},
"tags": [
"pirate",
"theme",
"fun",
"experimental"
]
},
"screenwriting": {
"name": "Screenwriting",
"id": "screenwriting",
"version": "1.0.0",
"description": "Spec-Driven Development for screenwriting/scriptwriting/tutorials: feature films, television (pilot, episode, limited series), and stage plays. Adapts the Spec Kit workflow to screenplay craft \u2014 slug lines, action lines, act breaks, beat sheets, and industry-standard pitch documents replace prose fiction conventions. Supports three-act, Save the Cat, TV pilot, network episode, cable/streaming episode, and stage-play structural frameworks.",
"author": "Andreas Daumann",
"repository": "https://github.com/adaumann/speckit-preset-screenwriting",
"download_url": "https://github.com/adaumann/speckit-preset-screenwriting/archive/refs/tags/v1.0.0.zip",
"homepage": "https://github.com/adaumann/speckit-preset-screenwriting",
"documentation": "https://github.com/adaumann/speckit-preset-screenwriting/blob/main/screenwriting/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.5.0"
},
"provides": {
"templates": 26,
"commands": 32,
"scripts": 1
},
"tags": [
"writing",
"screenplay",
"scriptwriting",
"film",
"tv",
"fountain",
"fountain-format",
"beat-sheet",
"teleplay",
"drama",
"comedy",
"storytelling",
"tutorial",
"education"
],
"created_at": "2026-04-23T08:00:00Z",
"updated_at": "2026-04-23T08:00:00Z"
},
"security-governance": {
"name": "Security Governance",
"id": "security-governance",
"version": "0.2.0",
"description": "Adds secure development governance, MSL preference, ASVS verification, supply-chain transparency, and EU CRA awareness.",
"author": "Thorsten Hindermann",
"repository": "https://github.com/hindermath/spec-kit-preset-security-governance",
"download_url": "https://github.com/hindermath/spec-kit-preset-security-governance/archive/refs/tags/v0.2.0.zip",
"homepage": "https://github.com/hindermath/spec-kit-preset-security-governance",
"documentation": "https://github.com/hindermath/spec-kit-preset-security-governance/blob/main/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.8.0"
},
"provides": {
"templates": 12,
"commands": 3
},
"tags": [
"security",
"governance",
"msl",
"asvs",
"supply-chain"
],
"created_at": "2026-04-27T00:00:00Z",
"updated_at": "2026-04-27T00:00:00Z"
},
"spec2cloud": {
"name": "Spec2Cloud",
"id": "spec2cloud",
"version": "1.1.0",
"description": "Spec-driven workflow tuned for shipping to Azure: spec \u2192 plan \u2192 tasks \u2192 implement \u2192 deploy.",
"author": "Azure Samples",
"repository": "https://github.com/Azure-Samples/Spec2Cloud",
"download_url": "https://github.com/Azure-Samples/Spec2Cloud/releases/download/spec-kit-spec2cloud-v1.1.0/preset.zip",
"homepage": "https://aka.ms/spec2cloud",
"documentation": "https://github.com/Azure-Samples/Spec2Cloud/blob/main/spec-kit/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.1.0"
},
"provides": {
"templates": 5,
"commands": 8
},
"tags": [
"azure",
"spec2cloud",
"workflow",
"deployment"
],
"created_at": "2026-04-30T00:00:00Z",
"updated_at": "2026-04-30T00:00:00Z"
},
"toc-navigation": {
"name": "Table of Contents Navigation",
"id": "toc-navigation",
"version": "1.0.0",
"description": "Adds a navigable Table of Contents to generated spec.md, plan.md, and tasks.md documents",
"author": "Quratulain-bilal",
"repository": "https://github.com/Quratulain-bilal/spec-kit-preset-toc-navigation",
"download_url": "https://github.com/Quratulain-bilal/spec-kit-preset-toc-navigation/archive/refs/tags/v1.0.0.zip",
"homepage": "https://github.com/Quratulain-bilal/spec-kit-preset-toc-navigation",
"documentation": "https://github.com/Quratulain-bilal/spec-kit-preset-toc-navigation/blob/main/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.4.0"
},
"provides": {
"templates": 3,
"commands": 3
},
"tags": [
"navigation",
"toc",
"documentation"
]
},
"vscode-ask-questions": {
"name": "VS Code Ask Questions",
"id": "vscode-ask-questions",
"version": "1.0.0",
"description": "Enhances the clarify command to use vscode/askQuestions for batched interactive questioning, reducing API request costs in GitHub Copilot.",
"author": "fdcastel",
"repository": "https://github.com/fdcastel/spec-kit-presets",
"download_url": "https://github.com/fdcastel/spec-kit-presets/releases/download/vscode-ask-questions-v1.0.0/vscode-ask-questions.zip",
"homepage": "https://github.com/fdcastel/spec-kit-presets",
"documentation": "https://github.com/fdcastel/spec-kit-presets/blob/main/vscode-ask-questions/README.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.1.0"
},
"provides": {
"templates": 0,
"commands": 1
},
"tags": [
"vscode",
"askquestions",
"clarify",
"interactive"
]
}
}
}

View File

@@ -0,0 +1,4 @@
{
"cached_at": "2026-05-21T18:52:11.763650+00:00",
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/presets/catalog.json"
}

View File

@@ -0,0 +1,30 @@
{
"schema_version": "1.0",
"updated_at": "2026-04-24T00:00:00Z",
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/presets/catalog.json",
"presets": {
"lean": {
"name": "Lean Workflow",
"id": "lean",
"version": "1.0.0",
"description": "Minimal core workflow commands - just the prompt, just the artifact",
"author": "github",
"repository": "https://github.com/github/spec-kit",
"license": "MIT",
"bundled": true,
"requires": {
"speckit_version": ">=0.6.0"
},
"provides": {
"commands": 5,
"templates": 0
},
"tags": [
"lean",
"minimal",
"workflow",
"core"
]
}
}
}

View File

@@ -1,6 +1,7 @@
# Implementation Plan: [FEATURE]
**Branch**: `[###-feature-name]` | **Date**: [DATE] | **Spec**: [link]
**Input**: Feature specification from `/specs/[###-feature-name]/spec.md`
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/templates/plan-template.md` for the execution workflow.
@@ -17,14 +18,22 @@
the iteration process.
-->
**Language/Version**: [e.g., Python 3.11, Swift 5.9, Rust 1.75 or NEEDS CLARIFICATION]
**Primary Dependencies**: [e.g., FastAPI, UIKit, LLVM or NEEDS CLARIFICATION]
**Storage**: [if applicable, e.g., PostgreSQL, CoreData, files or N/A]
**Testing**: [e.g., pytest, XCTest, cargo test or NEEDS CLARIFICATION]
**Language/Version**: [e.g., Python 3.11, Swift 5.9, Rust 1.75 or NEEDS CLARIFICATION]
**Primary Dependencies**: [e.g., FastAPI, UIKit, LLVM or NEEDS CLARIFICATION]
**Storage**: [if applicable, e.g., PostgreSQL, CoreData, files or N/A]
**Testing**: [e.g., pytest, XCTest, cargo test or NEEDS CLARIFICATION]
**Target Platform**: [e.g., Linux server, iOS 15+, WASM or NEEDS CLARIFICATION]
**Project Type**: [e.g., library/cli/web-service/mobile-app/compiler/desktop-app or NEEDS CLARIFICATION]
**Performance Goals**: [domain-specific, e.g., 1000 req/s, 10k lines/sec, 60 fps or NEEDS CLARIFICATION]
**Constraints**: [domain-specific, e.g., <200ms p95, <100MB memory, offline-capable or NEEDS CLARIFICATION]
**Project Type**: [e.g., library/cli/web-service/mobile-app/compiler/desktop-app or NEEDS CLARIFICATION]
**Performance Goals**: [domain-specific, e.g., 1000 req/s, 10k lines/sec, 60 fps or NEEDS CLARIFICATION]
**Constraints**: [domain-specific, e.g., <200ms p95, <100MB memory, offline-capable or NEEDS CLARIFICATION]
**Scale/Scope**: [domain-specific, e.g., 10k users, 1M LOC, 50 screens or NEEDS CLARIFICATION]
## Constitution Check

View File

@@ -1,9 +1,9 @@
# Feature Specification: [FEATURE NAME]
**Feature Branch**: `[###-feature-name]`
**Created**: [DATE]
**Status**: Draft
**Input**: User description: "$ARGUMENTS"
**Feature Branch**: `[###-feature-name]`
**Created**: [DATE]
**Status**: Draft
**Input**: User description: "$ARGUMENTS"
**Cross-Platform Spec**: <!-- Link to meshtastic/design/features/ spec, or "N/A — platform-specific only" with justification -->
## Summary
@@ -11,7 +11,7 @@
<!--
Provide a brief (2-3 sentence) summary of the feature, its purpose, and what
user problem it solves. Mention which modules are primarily affected.
CROSS-PLATFORM CHECK: Before writing this spec, check meshtastic/design/features/
for an existing cross-platform behavior spec. If one exists, this spec should describe
the Android-specific scope and acceptance criteria — not redefine the cross-platform
@@ -37,7 +37,7 @@
IMPORTANT: User stories should be PRIORITIZED as user journeys ordered by importance.
Each user story/journey must be INDEPENDENTLY TESTABLE - meaning if you implement just ONE of them,
you should still have a viable MVP (Minimum Viable Product) that delivers value.
Assign priorities (P1, P2, P3, etc.) to each story, where P1 is the most critical.
Think of each story as a standalone slice of functionality that can be:
- Developed independently
@@ -101,6 +101,22 @@
- What happens when [boundary condition]?
- How does system handle [error scenario]?
## Requirements *(mandatory)*
<!--
ACTION REQUIRED: The content in this section represents placeholders.
Fill them out with the right functional requirements.
-->
### Functional Requirements
- **FR-001**: System MUST [specific capability]
- **FR-002**: System MUST [specific capability]
### Non-Functional Requirements
- **NFR-001**: [Performance, accessibility, or quality requirement]
## Architecture
<!--
@@ -121,27 +137,11 @@
| [Component] | `feature/[name]/component/` | [Purpose] |
| [Existing Component] | `core/ui/component/` | [Reuse purpose] |
## Requirements *(mandatory)*
<!--
ACTION REQUIRED: The content in this section represents placeholders.
Fill them out with the right functional requirements.
-->
### Functional Requirements
- **FR-001**: System MUST [specific capability]
- **FR-002**: System MUST [specific capability]
### Non-Functional Requirements
- **NFR-001**: [Performance, accessibility, or quality requirement]
## Source-Set Impact
<!--
ACTION REQUIRED: Identify which KMP source sets this feature affects.
All business logic and UI MUST be in commonMain (Constitution §I, §III).
All business logic and UI MUST be in commonMain (Constitution I, III).
-->
| Source Set | Impact | Justification |
@@ -154,7 +154,7 @@
<!--
ACTION REQUIRED: Note any UI elements that must be reviewed against the
Meshtastic Client Design Standards (Constitution §V). Flag intentional
Meshtastic Client Design Standards (Constitution V). Flag intentional
deviations with rationale.
-->
@@ -166,7 +166,7 @@
## Privacy Assessment
<!--
ACTION REQUIRED: Confirm this feature does not violate Constitution §IV.
ACTION REQUIRED: Confirm this feature does not violate Constitution IV.
If the feature handles any sensitive data, document the safeguards.
-->

View File

@@ -6,6 +6,7 @@ description: "Task list template for feature implementation"
# Tasks: [FEATURE NAME]
**Input**: Design documents from `/specs/[###-feature-name]/`
**Prerequisites**: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/
**Tests**: The examples below include test tasks. New automated tests are OPTIONAL and
@@ -31,21 +32,21 @@ touched modules before work is considered complete.
- **Mobile**: `api/src/`, `ios/src/` or `android/src/`
- Paths shown below assume single project - adjust based on plan.md structure
<!--
<!--
============================================================================
IMPORTANT: The tasks below are SAMPLE TASKS for illustration purposes only.
The /speckit.tasks command MUST replace these with actual tasks based on:
- User stories from spec.md (with their priorities P1, P2, P3...)
- Feature requirements from plan.md
- Entities from data-model.md
- Endpoints from contracts/
Tasks MUST be organized by user story so each story can be:
- Implemented independently
- Tested independently
- Delivered as an MVP increment
DO NOT keep these sample tasks in the generated tasks.md file.
============================================================================
-->

View File

@@ -0,0 +1 @@
{"url": "https://raw.githubusercontent.com/github/spec-kit/main/workflows/catalog.community.json", "fetched_at": 1779389640.9802408}

View File

@@ -0,0 +1,6 @@
{
"schema_version": "1.0",
"updated_at": "2026-04-10T00:00:00Z",
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/workflows/catalog.community.json",
"workflows": {}
}

View File

@@ -0,0 +1 @@
{"url": "https://raw.githubusercontent.com/github/spec-kit/main/workflows/catalog.json", "fetched_at": 1779389641.039055}

View File

@@ -0,0 +1,19 @@
{
"schema_version": "1.0",
"updated_at": "2026-04-13T00:00:00Z",
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/workflows/catalog.json",
"workflows": {
"speckit": {
"id": "speckit",
"name": "Full SDD Cycle",
"description": "Runs specify \u2192 plan \u2192 tasks \u2192 implement with review gates",
"author": "GitHub",
"version": "1.0.0",
"url": "https://raw.githubusercontent.com/github/spec-kit/main/workflows/speckit/workflow.yml",
"tags": [
"sdd",
"full-cycle"
]
}
}
}

View File

@@ -49,5 +49,4 @@ You are an expert Android/KMP engineer. Maintain architectural boundaries, use M
<!-- SPECKIT START -->
For additional context about technologies to be used, project structure,
shell commands, and other important information, read the current plan
at `specs/20260520-153504-udp-label-rename/plan.md`
<!-- SPECKIT END -->