Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion decisions/0004-dependabot-unification.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

- **Status:** ACCEPTED
- **Date:** 2026-05-20
- **Deciders:** ss-o, Gemini CLI
- **Deciders:** ss-o
- **Supersedes:** None
- **Superseded by:** `decisions/0012-hybrid-dependency-management.md`

Expand Down
2 changes: 1 addition & 1 deletion decisions/0005-workflow-naming-conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

- **Status:** ACCEPTED
- **Date:** 2026-05-21
- **Deciders:** ss-o, Claude Code
- **Deciders:** ss-o
- **Supersedes:** None
- **Superseded by:** None

Expand Down
4 changes: 2 additions & 2 deletions decisions/0006-wiki-content-root-boundaries.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

- **Status:** ACCEPTED
- **Date:** 2026-05-29
- **Deciders:** ss-o, Claude Code
- **Deciders:** ss-o
- **Supersedes:** None
- **Superseded by:** None

Expand All @@ -20,7 +20,7 @@ The three content roots have fixed, non-overlapping scopes:
2. `community/` holds **Z-Shell ecosystem community content only** — contributing, the Zsh handbook/plugin standard, ZUnit.
3. `ecosystem/` holds the third-party catalog: annexes, packages, plugins.

Maintainer, operational, and infrastructure runbooks do not belong on the public wiki at all. They live in `z-shell/.github/runbooks/`, which is the established home for operational documentation. Feature *implementation* (Edge Functions, migrations, scripts) still lives in the owning repository.
Maintainer, operational, and infrastructure runbooks do not belong on the public wiki at all. They live in `z-shell/.github/runbooks/`, which is the established home for operational documentation. Feature _implementation_ (Edge Functions, migrations, scripts) still lives in the owning repository.

These boundaries are recorded in the wiki `AGENTS.md` (with `CLAUDE.md` as a symlink to it) and the wiki authoring instructions (`docs-authoring.instructions.md`, `agent-docusaurus-writer.instructions.md`).

Expand Down
2 changes: 1 addition & 1 deletion decisions/0007-release-publication-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

- **Status:** ACCEPTED
- **Date:** 2026-05-26
- **Deciders:** ss-o, Claude Code
- **Deciders:** ss-o
- **Supersedes:** None
- **Superseded by:** None

Expand Down
46 changes: 23 additions & 23 deletions decisions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,26 @@ Check: python3 scripts/decision-records.py --check
Durable organization decisions. Draft new records with `runbooks/adr.md`; only
a maintainer moves a record from `PROPOSED` to `ACCEPTED`.

| ADR | Title | Status | Date | Deciders |
| ------------------------------------------------------- | -------------------------------------------------------------- | -------- | ---------- | ----------------- |
| [0001](0001-meta-repo-and-agents-md.md) | Adopt a meta-repo pattern centered on `AGENTS.md` | ACCEPTED | 2026-05-29 | ss-o |
| [0002](0002-zi-as-canonical-plugin-manager.md) | `zi` is the canonical plugin manager for the z-shell ecosystem | ACCEPTED | 2026-05-29 | ss-o |
| [0003](0003-conventional-commits.md) | Adopt Conventional Commits across z-shell repositories | ACCEPTED | 2026-05-29 | ss-o |
| [0004](0004-dependabot-unification.md) | Standardize on Dependabot for Dependency Management | ACCEPTED | 2026-05-20 | ss-o, Gemini CLI |
| [0005](0005-workflow-naming-conventions.md) | No Emojis in Workflow and Job Name Fields | ACCEPTED | 2026-05-21 | ss-o, Claude Code |
| [0006](0006-wiki-content-root-boundaries.md) | Wiki Content-Root Boundaries | ACCEPTED | 2026-05-29 | ss-o, Claude Code |
| [0007](0007-release-publication-flow.md) | Release and Publication Flow | ACCEPTED | 2026-05-26 | ss-o, Claude Code |
| [0008](0008-branching-model.md) | Branching Model | ACCEPTED | 2026-07-25 | ss-o |
| [0009](0009-testing-ci-strategy.md) | Testing and CI Strategy | ACCEPTED | 2026-07-25 | ss-o |
| [0010](0010-security-incident-response.md) | Security Incident Response | PROPOSED | 2026-05-29 | TBD |
| [0011](0011-zsh-lint-semantic-analyzer-architecture.md) | zsh-lint Conditional Semantic Analysis Pipeline | ACCEPTED | 2026-07-25 | ss-o |
| [0012](0012-hybrid-dependency-management.md) | Split Dependency Updates Between Renovate and Dependabot | ACCEPTED | 2026-06-21 | ss-o |
| [0013](0013-repository-settings-baseline.md) | Repository Settings Baseline by Class | ACCEPTED | 2026-07-25 | ss-o |
| [0014](0014-portable-agent-instruction-architecture.md) | Adopt portable agent-instruction delivery | ACCEPTED | 2026-07-23 | ss-o |
| [0015](0015-zsh-scripting-standard.md) | Adopt an organization-wide Zsh scripting standard | ACCEPTED | 2026-08-27 | ss-o |
| [0016](0016-promotion-trigger-criteria.md) | Next-to-Main Promotion Trigger Criteria | ACCEPTED | 2026-08-16 | ss-o |
| [0017](0017-licensing-standard-by-provenance.md) | Licensing Standard by Provenance and Consumption | ACCEPTED | 2026-08-18 | ss-o |
| [0018](0018-portable-worktree-management.md) | Adopt Portable Worktree Management | ACCEPTED | 2026-08-27 | ss-o |
| [0019](0019-trunk-on-main-default.md) | Trunk-on-Main Default with a Zi Integration Exception | ACCEPTED | 2026-08-28 | ss-o |
| [0020](0020-adopt-zsh-plugin-standard-2.md) | Adopt Zsh Plugin Standard 2 as a Clean Portable Contract | ACCEPTED | 2026-08-28 | ss-o |
| [0021](0021-derive-chroma-knowledge-at-runtime.md) | Derive Chroma Command Knowledge at Runtime | ACCEPTED | 2026-08-29 | ss-o |
| ADR | Title | Status | Date | Deciders |
| ------------------------------------------------------- | -------------------------------------------------------------- | -------- | ---------- | -------- |
| [0001](0001-meta-repo-and-agents-md.md) | Adopt a meta-repo pattern centered on `AGENTS.md` | ACCEPTED | 2026-05-29 | ss-o |
| [0002](0002-zi-as-canonical-plugin-manager.md) | `zi` is the canonical plugin manager for the z-shell ecosystem | ACCEPTED | 2026-05-29 | ss-o |
| [0003](0003-conventional-commits.md) | Adopt Conventional Commits across z-shell repositories | ACCEPTED | 2026-05-29 | ss-o |
| [0004](0004-dependabot-unification.md) | Standardize on Dependabot for Dependency Management | ACCEPTED | 2026-05-20 | ss-o |
| [0005](0005-workflow-naming-conventions.md) | No Emojis in Workflow and Job Name Fields | ACCEPTED | 2026-05-21 | ss-o |
| [0006](0006-wiki-content-root-boundaries.md) | Wiki Content-Root Boundaries | ACCEPTED | 2026-05-29 | ss-o |
| [0007](0007-release-publication-flow.md) | Release and Publication Flow | ACCEPTED | 2026-05-26 | ss-o |
| [0008](0008-branching-model.md) | Branching Model | ACCEPTED | 2026-07-25 | ss-o |
| [0009](0009-testing-ci-strategy.md) | Testing and CI Strategy | ACCEPTED | 2026-07-25 | ss-o |
| [0010](0010-security-incident-response.md) | Security Incident Response | PROPOSED | 2026-05-29 | TBD |
| [0011](0011-zsh-lint-semantic-analyzer-architecture.md) | zsh-lint Conditional Semantic Analysis Pipeline | ACCEPTED | 2026-07-25 | ss-o |
| [0012](0012-hybrid-dependency-management.md) | Split Dependency Updates Between Renovate and Dependabot | ACCEPTED | 2026-06-21 | ss-o |
| [0013](0013-repository-settings-baseline.md) | Repository Settings Baseline by Class | ACCEPTED | 2026-07-25 | ss-o |
| [0014](0014-portable-agent-instruction-architecture.md) | Adopt portable agent-instruction delivery | ACCEPTED | 2026-07-23 | ss-o |
| [0015](0015-zsh-scripting-standard.md) | Adopt an organization-wide Zsh scripting standard | ACCEPTED | 2026-08-27 | ss-o |
| [0016](0016-promotion-trigger-criteria.md) | Next-to-Main Promotion Trigger Criteria | ACCEPTED | 2026-08-16 | ss-o |
| [0017](0017-licensing-standard-by-provenance.md) | Licensing Standard by Provenance and Consumption | ACCEPTED | 2026-08-18 | ss-o |
| [0018](0018-portable-worktree-management.md) | Adopt Portable Worktree Management | ACCEPTED | 2026-08-27 | ss-o |
| [0019](0019-trunk-on-main-default.md) | Trunk-on-Main Default with a Zi Integration Exception | ACCEPTED | 2026-08-28 | ss-o |
| [0020](0020-adopt-zsh-plugin-standard-2.md) | Adopt Zsh Plugin Standard 2 as a Clean Portable Contract | ACCEPTED | 2026-08-28 | ss-o |
| [0021](0021-derive-chroma-knowledge-at-runtime.md) | Derive Chroma Command Knowledge at Runtime | ACCEPTED | 2026-08-29 | ss-o |
23 changes: 23 additions & 0 deletions scripts/decision-records.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,17 @@ class of drift the organization asks to catch with an executable check rather
UNRESOLVED_DECIDERS = ("TBD", "None", "")
DATE_PATTERN = re.compile(r"^\d{4}-\d{2}-\d{2}$")

# A decision record names the humans who hold decision authority. Organization
# policy bans crediting a bot or AI agent as a co-author, and runbooks/adr.md
# reserves acceptance for a maintainer, so an automation identity can never be
# a decider. The commit-msg hook enforces the same rule for commit trailers;
# this is the decision-record half of it.
AGENT_DECIDER_PATTERN = re.compile(
r"\[bot\]|\b(?:claude(?:\s+code)?|copilot|gemini(?:\s+cli)?|codex|cursor"
r"|devin|openai|anthropic|chatgpt|gpt-\d)\b",
re.IGNORECASE,
)

INDEX_HEADER = """<!--
GENERATED FILE. DO NOT EDIT DIRECTLY.
Regenerate: python3 scripts/decision-records.py
Expand Down Expand Up @@ -197,6 +208,18 @@ def _validate_record(
)
)

agent_match = AGENT_DECIDER_PATTERN.search(record.deciders)
if agent_match is not None:
errors.append(
error(
path,
f"Deciders credits the automation identity "
f"{agent_match.group(0)!r}",
"list only the humans who hold decision authority; an agent "
"may draft a record but never decides it (see runbooks/adr.md)",
)
)

if not DATE_PATTERN.match(record.date):
errors.append(
error(
Expand Down
22 changes: 22 additions & 0 deletions scripts/test_decision_records.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,28 @@ def test_allows_proposed_record_without_deciders(self) -> None:
self.write_record("0001-proposed.md", text)
self.assertEqual(self.errors(), [])

def test_rejects_ai_agent_decider(self) -> None:
for identity in (
"Claude Code",
"Gemini CLI",
"Copilot",
"Codex",
"renovate[bot]",
):
with self.subTest(identity=identity):
self.write_record(
"0001-agent-decider.md",
VALID_RECORD.replace("ss-o", f"ss-o, {identity}"),
)
errors = self.errors()
self.assertTrue(any("automation identity" in e for e in errors), errors)

def test_allows_human_deciders(self) -> None:
self.write_record(
"0001-humans.md", VALID_RECORD.replace("ss-o", "ss-o, wicoop")
)
self.assertEqual(self.errors(), [])

def test_rejects_unknown_status(self) -> None:
self.write_record("0001-unknown.md", VALID_RECORD.replace("ACCEPTED", "MAYBE"))
errors = self.errors()
Expand Down
8 changes: 2 additions & 6 deletions scripts/test_validate_zsh_standard_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -3525,12 +3525,8 @@ def test_rendered_plugin_template_restores_lifecycle_state(self) -> None:
[[ $0 == "$caller_zero" ]] || exit 34
""")
direct_source = str(entry_path)
direct_relative_source = str(
entry_path.relative_to(temporary_directory)
)
manager_source = str(
plugin_root / "manager [literal]*? plugin.plugin.zsh"
)
direct_relative_source = str(entry_path.relative_to(temporary_directory))
manager_source = str(plugin_root / "manager [literal]*? plugin.plugin.zsh")
manager_raw_source = str(
plugin_root
/ "discarded [literal]*? segment"
Expand Down
Loading