Skip to content
Development
Skill

/night-market-architecture-contract

States load-bearing decisions, invariants, and weak points. Use when judging a design change. Do not use for gating; use night-market-change-control.

From plugin
claude-night-market
337200 skills59 agents162 commands1 MCP
Install
$ npx -y skills add athola/claude-night-market --skill night-market-architecture-contract --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/night-market-architecture-contract

Context preview

The summary Claude sees to decide when to auto-load this skill.

States load-bearing decisions, invariants, and weak points. Use when judging a design change. Do not use for gating; use night-market-change-control.

SKILL.md

night-market-architecture-contract.SKILL.md
name: night-market-architecture-contract
description: States load-bearing decisions, invariants, and weak points. Use when judging a design change. Do not use for gating; use night-market-change-control.

Night Market Architecture Contract

This skill records the design decisions that hold claude-night-market together, the invariants that enforcement code keeps true, and the weak points that are known and accepted. Read it before proposing a change that crosses a plugin boundary, touches a hook, adds a skill, or bumps a version. Every claim cites in-repo evidence: an ADR (Architecture Decision Record, in `docs/adr/`), a commit hash, or a checked-in enforcement file. Verify a citation before relying on it:

git log --oneline -1 <hash>
rg -n "Status" docs/adr/<file>.md

Load-bearing decisions

1. Plugins are self-contained deployables

Each of the 23 plugins under `plugins/` must install and run alone. There is no shared registry and no root-level shared library that plugins import at runtime (ADR-0001, Accepted). Plugins detect each other at runtime via filesystem checks and must degrade gracefully when a sibling is absent.

Cross-plugin DRY is an anti-pattern here, and that is settled by experiment, not taste. Commit `054e2679` consolidated 1164 lines of duplicated `tasks_manager.py` from attune, sanctum, and spec-kit into a shared root script. It broke plugin self-containment and was reverted in `29961cd2`. The durable fix, `d89a55c7`, made the copies per-plugin and intentionally different. `docs/dependency-audit.md` records the per-plugin copies as the approved state. Do not re-propose the consolidation.

Practical test before you extract shared code: if a user installs only one plugin from the marketplace, does your change still work? If not, duplicate the code into each plugin instead.

2. Hooks run under host Python from a cache directory

Claude Code copies an installed plugin into a cache directory and runs its hooks under the host system Python, which can be as old as 3.9. The repo itself is Python 3.12 (root `pyproject.toml`, `requires-python >= 3.12`). Only hook scripts and their transitive import chains carry the 3.9 constraint. Five contract rules follow, each purchased with an outage:

| Rule | Why (evidence) | |------|----------------| | Hook code and every transitive import must be Python 3.9 compatible | `datetime.UTC` (a 3.11+ alias) broke the whole hook import chain repeatedly. ruff kept auto-reverting the fix until `UP017` was globally ignored (`pyproject.toml` line 165) and an AST scan test held the line (`plugins/leyline/tests/test_python39_compat.py`) | | Read the hook payload as JSON on stdin, never from `CLAUDE_TOOL_*` env vars | Claude Code does not set those env vars, so env-reading hooks were silent no-ops for months (full record: night-market-failure-archaeology SB9). Canonical reader: `read_hook_payload()` in `plugins/abstract/hooks/shared/hook_io.py` | | No relative paths in hooks | The cache directory is not the repo checkout. conserve's session-start hook broke on a relative path and now inlines its JSON utilities (CHANGELOG) | | Hook entrypoints must import safely under a bare interpreter | An eager `import yaml` in gauntlet made every git commit emit `ModuleNotFoundError`. Guarded in `45dd77ef` (#518), `anthropic` deferred in `9bfc0a7a` | | Subprocess timeouts must sit below the budget registered in `hooks.json` | herald's LLM call once outlived its registered Stop-hook budget, so the harness killed the hook with no verdict at all (full record: night-market-failure-archaeology SB7). Guard test: `plugins/herald/tests/unit/test_double_shot_latte.py` |

CI enforcement: `.github/workflows/python39-compat.yml` runs two gates with uneven coverage. Gate 1 (ruff `UP007`, flags 3.10+ union syntax) covers 12 plugins' `hooks/` dirs. Gate 2 (hook test suites inside a real Python 3.9 venv) covers only 7 plugins: abstract, conserve, egregore, imbue, leyline, memory-palace, sanctum. herald ships a Stop hook yet appears in neither gate.

3. One ecosystem version, fanned out to every manifest

`.claude-plugin/marketplace.json` is the version source of truth (1.9.15 as of 2026-07-02). Each plugin carries three manifests that must stay in sync with it and with each other:

  • `.claude-plugin/plugin.json` (name, version, component arrays)
  • `.claude-plugin/metadata.json` (version plus dependency hints)
  • `openpackage.yml` (cross-framework manifest)

Plus `pyproject.toml` and any `__init__.py` carrying `__version__`. Never hand-edit versions across files. Use the bumper, which finds and rewrites all of them:

uv run python plugins/sanctum/scripts/update_versions.py <version>

One trap: `metadata.json` `dependencies` (for example imbue declaring `"abstract": ">=2.0.0"`) is a separate semver namespace for capability compatibility. It does not track the marketplace version and a `2.0.0` there does not mean marketplace 2.0.0 exists.

4. Skill discovery budget is finite and overflow is silent

Claude Code loads every installed skill's description into context at 2% of the context window, with a 16,000-character fallback (ADR-0004, Accepted, updated 2026-05-21). Descriptions that exceed the budget make skills invisible with no error anywhere. That is why:

  • Each description is capped at 160 characters

(`docs/skill-description-guide.md`), enforced by the `validate-description-budget` pre-commit hook backed by `plugins/abstract/scripts/validate_budget.py`.

  • The ecosystem-wide validator ceiling is 90,000 characters

(`DEFAULT_BUDGET` in `plugins/abstract/scripts/validate_budget.py`, overridable via `SLASH_COMMAND_TOOL_CHAR_BUDGET`). ADR-0004 and `docs/skill-description-guide.md` still cite a stale 60,000 figure; the script is the enforcer. Flag the ADR for an update through change control.

When adding a skill, spend the 160 characters on trigger phrases, not on restating the name.

5. Collective memory and trus

Read more
Ships withclaude-night-market

A plugin marketplace for Claude Code. Install only the plugins you need to run git workflows, code review, spec-driven development, and autonomous agents from inside your Claude Code session.

Get the whole plugin

Other skills on claude-night-market.