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: 2 additions & 0 deletions .claude/skills/straymark-charter-new/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ If the title would derive a poor slug, pass `--slug <slug>` explicitly.

After the file is created, the CLI's "Next steps" output already lists what to fill. Surface it verbatim, then add:

> **Reconnaissance before declaration** (#210): when filling `## Files to modify`, `Read`/`ls` every path before you list it — do not declare a path you have not opened. Charters authored against assumed, un-read code drift before execution even begins (the LNXDrive findings showed declared paths like `lnxdrive-config/src/parser.rs` that never existed). Tag genuinely-new files "New" in the Change column. If the Charter modifies a cross-component API (D-Bus/gRPC/REST contract, shared trait, IPC method), list **all** consumers, not just the producer. `straymark validate --include-charters` flags declared paths that don't exist (`CHARTER-FILES-EXIST`).
>
> **Reminder**: Charter status starts at `declared`. Flip to `in-progress` only when execution actually begins. Run `straymark charter drift CHARTER-NN` before `straymark charter close` to catch declared-but-not-modified files (or modified-but-not-declared ones).

### 6. Report result
Expand Down
2 changes: 2 additions & 0 deletions .codex/skills/straymark-charter-new/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ If the title would derive a poor slug, pass `--slug <slug>` explicitly.

After the file is created, the CLI's "Next steps" output already lists what to fill. Surface it verbatim, then add:

> **Reconnaissance before declaration** (#210): when filling `## Files to modify`, `Read`/`ls` every path before you list it — do not declare a path you have not opened. Charters authored against assumed, un-read code drift before execution even begins (the LNXDrive findings showed declared paths like `lnxdrive-config/src/parser.rs` that never existed). Tag genuinely-new files "New" in the Change column. If the Charter modifies a cross-component API (D-Bus/gRPC/REST contract, shared trait, IPC method), list **all** consumers, not just the producer. `straymark validate --include-charters` flags declared paths that don't exist (`CHARTER-FILES-EXIST`).
>
> **Reminder**: Charter status starts at `declared`. Flip to `in-progress` only when execution actually begins. Run `straymark charter drift CHARTER-NN` before `straymark charter close` to catch declared-but-not-modified files (or modified-but-not-declared ones).

### 6. Report result
Expand Down
1 change: 0 additions & 1 deletion .cursor/rules/straymark.md
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,6 @@ StrayMark uses HTML comment markers to manage injected content in agent configur
*StrayMark | [GitHub](https://github.com/StrangeDaysTech/straymark)*
*[Strange Days Tech](https://strangedays.tech) — Because every change tells a story.*
<!-- straymark:end -->

## StrayMark Documentation Rules

Identity: Use `cursor-v{version}` in the `agent:` field.
Expand Down
1 change: 0 additions & 1 deletion .cursorrules
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,6 @@ StrayMark uses HTML comment markers to manage injected content in agent configur
*StrayMark | [GitHub](https://github.com/StrangeDaysTech/straymark)*
*[Strange Days Tech](https://strangedays.tech) — Because every change tells a story.*
<!-- straymark:end -->

## StrayMark Documentation Rules

Identity: Use `cursor-v{version}` in the `agent:` field.
Expand Down
2 changes: 2 additions & 0 deletions .gemini/skills/straymark-charter-new/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ If the title would derive a poor slug, pass `--slug <slug>` explicitly.

After the file is created, the CLI's "Next steps" output already lists what to fill. Surface it verbatim, then add:

> **Reconnaissance before declaration** (#210): when filling `## Files to modify`, `Read`/`ls` every path before you list it — do not declare a path you have not opened. Charters authored against assumed, un-read code drift before execution even begins (the LNXDrive findings showed declared paths like `lnxdrive-config/src/parser.rs` that never existed). Tag genuinely-new files "New" in the Change column. If the Charter modifies a cross-component API (D-Bus/gRPC/REST contract, shared trait, IPC method), list **all** consumers, not just the producer. `straymark validate --include-charters` flags declared paths that don't exist (`CHARTER-FILES-EXIST`).
>
> **Reminder**: Charter status starts at `declared`. Flip to `in-progress` only when execution actually begins. Run `straymark charter drift CHARTER-NN` before `straymark charter close` to catch declared-but-not-modified files (or modified-but-not-declared ones).

### 6. Report result
Expand Down
1 change: 0 additions & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
> **Read and follow the rules in [../STRAYMARK.md](../STRAYMARK.md).**
> That file contains all StrayMark documentation governance rules for this project.
<!-- straymark:end -->

---

## StrayMark Rules for Copilot
Expand Down
443 changes: 236 additions & 207 deletions .straymark/.checksums.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .straymark/00-governance/AGENT-RULES.md
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Rules for AI Agents - StrayMark

> This document defines the rules that all AI agents must follow when working on projects under StrayMark.
Expand Down Expand Up @@ -387,4 +387,4 @@

---

*StrayMark fw-4.19.0 | [Strange Days Tech](https://strangedays.tech)*
*StrayMark fw-4.20.0 | [Strange Days Tech](https://strangedays.tech)*
2 changes: 1 addition & 1 deletion .straymark/00-governance/C4-DIAGRAM-GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,4 +234,4 @@ Use a Level 1 (Context) diagram to illustrate:

---

*StrayMark fw-4.19.0 | [Strange Days Tech](https://strangedays.tech)*
*StrayMark fw-4.20.0 | [Strange Days Tech](https://strangedays.tech)*
2 changes: 1 addition & 1 deletion .straymark/00-governance/DOCUMENTATION-POLICY.md
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -318,4 +318,4 @@ See also [ADR-2025-01-20-001] for architectural context.

---

*StrayMark fw-4.19.0 | [Strange Days Tech](https://strangedays.tech)*
*StrayMark fw-4.20.0 | [Strange Days Tech](https://strangedays.tech)*
30 changes: 24 additions & 6 deletions .straymark/00-governance/POLISH-CHARTER-PATTERN.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Polish Charter Pattern — StrayMark

> The closing Charter of an Etapa (or SpecKit `Polish` Phase) is the load-bearing gate for detecting a recurring anti-pattern — **"Surface declaration without wiring"** — that user-story Charters' test suites systematically cannot catch.
Expand All @@ -8,9 +8,13 @@

## Status

**v0 — proven in N=1 domain** (`StrangeDaysTech/sentinel` CHARTER-19 → CHARTER-27, 2026-05-22).
**v1 — validated in N=2 independent domains.** Two axes, deliberately reported
separately so they are not conflated:

This is a **convention + named anti-pattern**, not a CLI feature. Adopters reproduce it locally with a dedicated polish Charter and (optionally) project-local CI guards. The pattern may evolve into a `straymark analyze declared-vs-wired` subcommand once a second adopter validates it (see [Open questions](#open-questions)). The gate for that cristallization mirrors the one used by [`FOLLOW-UPS-BACKLOG-PATTERN.md`](FOLLOW-UPS-BACKLOG-PATTERN.md): v0 → v1 graduation requires N=2.
- **Independent domains: 2.** `StrangeDaysTech/sentinel` (Go backend, CHARTER-19 → CHARTER-27, 2026-05-22) and `StrangeDaysTech/lnxdrive` (Rust Linux cloud-sync daemon + GTK desktop, 2026-05, [finding #209](https://github.com/StrangeDaysTech/straymark/issues/209)). A Rust desktop app validating a pattern first seen in a Go backend is the strong cross-domain signal the [N-status gate](../../../ADOPTERS.md) requires.
- **Occurrences: 3.** Sentinel surfaced the original sub-classes (1–4); LNXDrive surfaced a qualitatively new occurrence — a *cross-component regression of a shipped mitigation* (sub-class 5 below).

The N=2 gate for CLI crystallization (mirrored from [`FOLLOW-UPS-BACKLOG-PATTERN.md`](FOLLOW-UPS-BACKLOG-PATTERN.md)) is **now crossed**. The convention + named anti-pattern remains the portable core; the mechanical check graduates to a `straymark analyze declared-vs-wired` subcommand (config-driven set-difference, v0 scope ships in cli-3.17.x+ — see [Open questions](#open-questions)). Adopters can still reproduce the discovery locally with a dedicated polish Charter and (optionally) project-local CI guards.

---

Expand Down Expand Up @@ -49,13 +53,25 @@
| 2 | Metric instrument / observability symbol declared in a metrics package | Record / increment call site in handler or worker code | Each declared instrument has at least one record-call site |
| 3 | URL referenced from rendered HTML or embedded template (`<script src="/...">`, `<link href="/...">`) | Route registered with the same API surface | Each `src=`/`href=` in served HTML resolves to a registered route |
| 4 | Route marked public-by-contract (handler doc-comment, dedicated marker) | Entry in the auth middleware's public-prefix / public-paths list | Each public-by-contract handler has a matching prefix entry |
| 5 | Client-side IPC/RPC proxy method declared (D-Bus proxy, gRPC stub, REST client) — **especially one re-introduced after a shipped mitigation removed the server method** | Server / daemon interface that actually implements the method | Each declared proxy method resolves to an implemented interface method; a cross-component API change must update **all** consumers |

The unifying one-liner across the four sub-classes is:
The unifying one-liner across the sub-classes is:

> **Every declared surface artifact has at least one wiring site reachable from a real request.**

Adopters extending the list (new declaration↔wiring pairs the reference implementation has not yet surfaced) are welcome to contribute additional sub-classes via issue or PR.

### Sub-class 5 named: shipped-mitigation regression via an un-updated downstream consumer

LNXDrive surfaced sub-class 5 as a *regression of an already-shipped mitigation, across a component boundary* — a sharper data point than a fresh gap. The producer (a D-Bus daemon) had closed a security risk by removing a token-bearing method and shipping a token-safe replacement. A separate component (a GTK preferences client, compiled via a different build system) **kept calling the removed method** and fetching tokens client-side — the exact behavior the mitigation had eliminated.

Two compounding factors made it invisible to every existing backstop:

- **Cross-boundary blindness.** Producer and consumer live in different crates, built by different toolchains (Cargo vs Meson), joined only at runtime over the bus. zbus/D-Bus proxies are validated at *runtime*, not compile time — so the daemon's own tests passed, the client compiled clean, and no single test suite spanned the contract.
- **Feature-gated dead code.** The stale call sat behind a `#[cfg(feature = "goa")]` whose feature `Cargo.toml` never defined. It compiled *out* entirely — dead code that defeats both CI and code review, since neither exercises an undefined feature. Activating the feature for the first time even surfaced a latent type error that had never compiled: concrete proof the path was never wired.

The legible signal that caught it was the polish/audit's **ex-ante contract check** — a diff of the client's declared proxy methods against the daemon's implemented interface. This generalizes the mechanical check from "every declared surface artifact has a wiring site" to its cross-component corollary: **a producer-side API change must update, or at least account for, every declared consumer of that API.** The Charter discipline that operationalizes this lives in [the template guidance](#related) (#209.c): a mitigation touching a cross-component API lists *all* consumers in `## Files to modify`, so a producer change can't silently orphan a consumer.

### Why integration tests miss these

The common cause across the four sub-classes is that the standard integration-test harness mounts handlers directly via the testing API (`humatest.NewTestAdapter`, equivalent in other stacks), bypassing the composition step where the declaration and wiring are joined. The handler under test is wired correctly *by the test fixture*; the production composition is what is broken. CI's green signal reflects "the handler behaves correctly given a request" — not "the request can reach the handler" nor "the declared artifact is reachable from production".
Expand Down Expand Up @@ -96,7 +112,7 @@

These are not resolved in v0. Future revisions of this pattern, or a CLI helper, may address them:

- **Crystallization as `straymark analyze declared-vs-wired` CLI subcommand**. Today the four sub-class checks are project-local (one Go analyzer in the reference implementation). Once a second adopter validates the pattern, the framework may ship a cross-project subcommand parameterized by: which packages contain declared artifacts (metric instrument types, env-var docs format, HTML embed paths, public-route marker convention); which sites count as wiring (record call, env-var reader, route registrar, prefix list). Gate: N=2 adopters.
- **Crystallization as `straymark analyze declared-vs-wired` CLI subcommand** — *N=2 gate crossed; v0 scope resolved.* With LNXDrive validating the pattern in a second domain, the framework ships a **config-driven set-difference** v0: the operator supplies a declared-side glob+regex and a wired-side glob+regex (the regex capture group is the symbol name), and the command reports symbols declared-but-not-wired (`D \ W`). This is mechanically tractable on *any* stack precisely because the stack-specific knowledge lives in the adopter's regexes, not in the CLI — and it directly catches sub-class 5 (D-Bus proxy method names client-side vs interface method names server-side). **Deferred to a later revision:** AST-based variants of sub-classes 1–4 (env-var docs, metric instruments, HTML embeds, public-route markers), which need per-stack parsers; and the runtime/dynamic checks (full-chain boot, route resolution), which are inherently project-local.
- **Sub-class enumeration completeness**. The four sub-classes were the ones the reference implementation surfaced. Additional candidates: database column declared in a migration but never read/written by application code; feature flag declared but never checked; protobuf field defined but never serialized. Each additional sub-class needs at least one adopter empirical surfacing to enter the canon.
- **Integration with `straymark charter close --polish-checklist`**. A polish-specific subcommand could surface the canonical checklist (run runbook end-to-end; verify each declared artifact has a wiring site; verify env-var inventory matches the binary's actual requirements; verify CLI tooling referenced in the runbook exists). Gate: after the `declared-vs-wired` CLI subcommand lands, since the checklist's last item would invoke it.
- **Per-stack instantiation guides**. The four sub-classes are language-agnostic; the concrete check shape (Go `analysis.Pass`, TypeScript AST walker, Python `ast` module, etc.) is not. A future pattern revision may host per-stack reference implementations as sibling docs.
Expand All @@ -106,7 +122,9 @@

## Credits

Contributed via [issue #199](https://github.com/StrangeDaysTech/straymark/issues/199) by the Sentinel adopter. Empirical foundation: CHARTER-19 → CHARTER-27 chain in `StrangeDaysTech/sentinel`, retrospective [AIDEC-2026-05-22-001](https://github.com/StrangeDaysTech/sentinel/pull/93). Author: José Villaseñor Montfort.
Originated via [issue #199](https://github.com/StrangeDaysTech/straymark/issues/199) by the Sentinel adopter (N=1). Empirical foundation: CHARTER-19 → CHARTER-27 chain in `StrangeDaysTech/sentinel`, retrospective [AIDEC-2026-05-22-001](https://github.com/StrangeDaysTech/sentinel/pull/93).

Crystallized to **v1 (N=2)** via [finding #209](https://github.com/StrangeDaysTech/straymark/issues/209) by the LNXDrive adopter (Rust desktop, second independent domain), which contributed sub-class 5 (shipped-mitigation regression via an un-updated downstream consumer) and triggered the `analyze declared-vs-wired` subcommand. The companion [finding #210](https://github.com/StrangeDaysTech/straymark/issues/210) added the `charter new` reconnaissance discipline and the `CHARTER-FILES-EXIST` validate rule. Author: José Villaseñor Montfort.

*This document was produced with assistance from generative AI tools (Claude 4.7); all responsibility for the content rests with the human author.*

Expand All @@ -121,4 +139,4 @@

---

*StrayMark fw-4.19.0 | [Strange Days Tech](https://strangedays.tech)*
*StrayMark fw-4.20.0 | [Strange Days Tech](https://strangedays.tech)*
2 changes: 1 addition & 1 deletion .straymark/00-governance/QUICK-REFERENCE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# StrayMark - Quick Reference

> One-page reference for AI agents and developers.
Expand Down Expand Up @@ -242,4 +242,4 @@

---

*StrayMark fw-4.19.0 | [Strange Days Tech](https://strangedays.tech)*
*StrayMark fw-4.20.0 | [Strange Days Tech](https://strangedays.tech)*
Empty file modified .straymark/00-governance/exceptions/.gitkeep
100755 → 100644
Empty file.
2 changes: 1 addition & 1 deletion .straymark/00-governance/i18n/es/AGENT-RULES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Reglas para Agentes IA - StrayMark

> Este documento define las reglas que todos los agentes de IA deben seguir cuando trabajan en proyectos bajo StrayMark.
Expand Down Expand Up @@ -387,4 +387,4 @@

---

*StrayMark fw-4.19.0 | [Strange Days Tech](https://strangedays.tech)*
*StrayMark fw-4.20.0 | [Strange Days Tech](https://strangedays.tech)*
2 changes: 1 addition & 1 deletion .straymark/00-governance/i18n/es/C4-DIAGRAM-GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,4 +234,4 @@ Usar un diagrama de Nivel 1 (Contexto) para ilustrar:

---

*StrayMark fw-4.19.0 | [Strange Days Tech](https://strangedays.tech)*
*StrayMark fw-4.20.0 | [Strange Days Tech](https://strangedays.tech)*
2 changes: 1 addition & 1 deletion .straymark/00-governance/i18n/es/DOCUMENTATION-POLICY.md
Original file line number Diff line number Diff line change
Expand Up @@ -311,4 +311,4 @@ Ver también [ADR-2025-01-20-001] para contexto arquitectónico.

---

*StrayMark fw-4.19.0 | [Strange Days Tech](https://strangedays.tech)*
*StrayMark fw-4.20.0 | [Strange Days Tech](https://strangedays.tech)*
Loading
Loading