Skip to content

Commit 346a950

Browse files
authored
feat(framework+cli): surface Charter as top-level concept (closes #113) (#122)
* fix(cli): align charter subcommand path to .straymark/charters/ The `straymark charter list/audit/close/drift/new` subcommands hardcoded `docs/charters/` as the discovery root, while `straymark init` and `straymark status` already validated `.straymark/charters/` as the canonical structure. Projects on the post-rebrand layout (fw-4.11.0) were silently invisible to the CLI: charters created with `charter new` landed in `docs/charters/` but `straymark status` only looked under `.straymark/`, and reciprocally `charter list/audit/close` could not see charters living under `.straymark/charters/`. This change unifies on `.straymark/charters/` (the canonical post-rebrand location), where declarative `*.md` and telemetry `*.telemetry.yaml` sidecars now share one directory. The drift bash script and its documentation are updated to match. Changes: - New `charter::charters_dir(project_root)` helper as the single source of truth for the Charter discovery path. - `discover_charters` and `commands/charter/new.rs` now route through it; previously they constructed `docs/charters/` directly. - `commands/charter/close.rs` reuses the same helper for telemetry destination — declarative + telemetry are no longer split. - Error messages in `audit/close/drift` now name the path that was searched and hint at `straymark charter list` (per the Issue #119 workaround request). - `dist/.straymark/scripts/check-charter-drift.sh` matches against `.straymark/charters/*` instead of `docs/charters/*`. - All existing tests (`cli/tests/charter_*.rs`, inline tests in `charter.rs`, `tui/index.rs`, `commands/charter/list.rs`, `commands/charter/status.rs`) updated to the new path. Tested: `cargo test --release` (479 passed); smoke test (`charter new` → `charter list` round-trip on `.straymark/charters/`). Closes #119 * docs(framework): surface Charter as top-level concept Address the discoverability gap reported in #113: STRAYMARK.md and QUICK-REFERENCE.md (EN/ES/zh-CN) did not name Charters anywhere, so agents onboarding via canonical entry points built binary mental models (SpecKit = planning, StrayMark = audit-trail) and silently dropped the third layer where Charters live. - STRAYMARK.md §6: add Charter trigger ("multi-session implementation block, >1 day, >5 tasks") to the When-to-Document table. - STRAYMARK.md §9: add Charter row to the Autonomy Limits table. - STRAYMARK.md §10: add charters/ to the documentation map tree. - STRAYMARK.md §11: add Charter rows to the When-to-Load table (template path + how to list existing Charters + bridge doc). - STRAYMARK.md §13: add Charter to the Quick Type Reference, noting the NN-slug.md filename divergence from TYPE-YYYY-...-NNN-*. - STRAYMARK.md §15 (new): dedicated section explaining what a Charter is, when to declare one, the lifecycle (declared → in-progress → closed), and how it relates to AILOG/ADR/SpecKit. - QUICK-REFERENCE.md (×3 langs): add "Bounded Units of Work — Charter" subsection alongside the doc-type tables, charters/ entry in the folder tree, Charter trigger row in When-to-Document, and /straymark-charter-new in the skills table. * docs(directives): add Charter trigger to pre-commit checklist Inject the Charter declaration trigger into the directive templates (CLAUDE.md, GEMINI.md, copilot-instructions.md) that `straymark init` fans out to adopting projects. Now agents reading the local CLAUDE.md / GEMINI.md / .github/copilot-instructions.md see Charter in their pre-commit checklist alongside AILOG / AIDEC / ADR / ETH triggers, instead of having to hunt for it in STRAYMARK.md §15. Trigger wording: "Starting a multi-session implementation block (>1 day, >5 tasks, multi-phase)? → Declare a Charter via `straymark charter new` (see STRAYMARK.md §15)". Closes the second contributing factor of #113 (root cause #2: "CLAUDE.md Pre-commit Checklist has no Charter trigger"). * feat(cli): scan .straymark/charters/ in straymark status Surface Charters in the canonical health view. Until now `straymark status` enumerated only the 12 governance doc types — Charters were structurally invisible to the compliance-observability tool, even when present. That blind spot is the fifth contributing factor of #113 ("/straymark-status excludes Charters from its scan"). The new "Charters" block sits below "Documentation": - When the project has no Charters yet: a single dimmed line pointing at `/straymark-charter-new` and STRAYMARK.md §15. - When Charters exist: a status-keyed table (declared / in-progress / closed / TOTAL), with declared in normal weight, in-progress in yellow, closed in green — matching the colorize_status convention already used by `charter list`. - Unparseable Charter files (Charter-shaped filename, schema mismatch) are surfaced as a warning row so the operator knows to fix them. Counts come from `charter::discover_and_parse(project_root)` — the same source of truth that `straymark charter list` uses, ensuring the two commands cannot disagree about what's in the project. * feat(skills): add /straymark-charter-new + Charter mentions in status/new Add a dedicated /straymark-charter-new skill across the three skill surfaces (Claude Code, Gemini, agnostic) so Charter declaration is discoverable through skill autocomplete and through any "what slash commands exist?" exploration. Previously Charter creation was only reachable via the bare `straymark charter new` CLI invocation, which the issue (#113 root cause #4) flagged as the reason agents miss the concept entirely. The new skill drives the existing CLI — slug derivation, sequential numbering and template substitution stay server-side; the skill's job is to gather title/effort/origin (--from-ailog vs --from-spec vs none), confirm with the operator, then run `straymark charter new` with the right flags. The skill explicitly does NOT flip status, run drift, or run audit — those have their own skills / CLI surfaces and shouldn't be conflated with declaration. Also amend the existing skills: - /straymark-status (×3): scan `.straymark/charters/` after the doc-type prefixes, surface "no Charters yet but the work fits the trigger → recommend /straymark-charter-new" as a gap. - /straymark-new (×3): add Charter as a *redirect* row (not a doc type that `straymark new` can produce) — the skill recognizes "create a Charter" / "declare a Charter" intent and points at /straymark-charter-new instead of trying to handle it inline. Closes the third, fourth, fifth and sixth contributing factors of #113 (no charter-new skill, /straymark-status excludes Charters, audit-* skills' framing). * refactor(framework): wire CLI to charter templates' new subdirectory Templates were moved to `dist/.straymark/templates/charter/` in the preceding "surface Charter as top-level concept" commit so that the charter-* templates are visually distinguishable from auxiliary doc templates (root cause #7 of #113: "charter-template.md and charter-telemetry-template.yaml are listed in `.straymark/templates/` but indistinguishable from auxiliary templates"). This commit wires the CLI and tests to the new layout: - `commands/charter/new.rs` resolves the declarative template through `templates/charter/charter-template.md` (with i18n fallback via `templates/charter/i18n/<lang>/`). - `commands/charter/close.rs` reads the telemetry template from `templates/charter/charter-telemetry-template.yaml`. - `cli/tests/charter_{test,drift,close}.rs` build their fixtures under `templates/charter/` and create the subdir explicitly. `utils::resolve_localized_path` already handles arbitrary base directories, so no change was needed there. * docs(governance): add SPECKIT-CHARTER-BRIDGE.md (EN/ES/zh-CN) Close root cause #8 of #113: "no documented bridge between SpecKit and StrayMark Charters". The Charter frontmatter has had `originating_spec: specs/NNN-feature/spec.md` from day one — the schema slot was the bridge, but nothing told operators or agents *when* a SpecKit feature should yield a Charter, *how granular* it should be (1 per feature? 1 per phase? 1 per User Story?), or *who triggers the creation* (after `/speckit-tasks`? before `/speckit-implement`?). Without that, agents formed the binary mental model the issue flagged — "SpecKit = planning, StrayMark = audit-trail" — and silently dropped the Charter layer. The new doc: - Names the three layers (specification → Charter → AILOG/AIDEC/ADR) and the handoff pattern between them. - Lists four "yes-Charter" conditions (≥5 tasks across sessions, multi-phase, audit-worthy, telemetry-worthy) and three "no-Charter" conditions (single-session, planning-only, ad-hoc maintenance). - Gives four granularity heuristics with the rule "one Charter per shippable cut" — explicitly NOT per User Story, NOT per feature. - Anchors the creation timing to the SpecKit pipeline: /speckit-tasks → declare Charter → /speckit-implement → drift → audit (optional) → close. - Documents the frontmatter linkage in both directions (Charter.originating_spec, AILOG.originating_charter). - Lists five anti-patterns (Charter "to be safe", per-US, missing origin, premature close, audit without auditors). - Names five cases where the pattern doesn't apply (single-session, arch-only, pure refactor, incident response, compliance refresh). Cited in STRAYMARK.md §11 ("SpecKit user — when does a feature yield a Charter?"), STRAYMARK.md §15 ("Charters as bounded units of work"), and the QUICK-REFERENCE Charter subsection. Skill `/straymark-charter-new` also points to it. Translations follow the same patterns established for `docs/i18n/{es,zh-CN}/` — preserve technical terms (Charter, SpecKit, drift, scope), localize narrative.
1 parent 464b15f commit 346a950

28 files changed

Lines changed: 1106 additions & 16 deletions

File tree

cli/src/commands/charter/close.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,11 @@ fn copy_template_for(
162162
dest: &Path,
163163
non_interactive: bool,
164164
) -> Result<String> {
165+
// Charter templates live under their own subdirectory (`templates/charter/`)
166+
// since fw-4.12.0.
165167
let template_path = straymark_dir
166168
.join("templates")
169+
.join("charter")
167170
.join("charter-telemetry-template.yaml");
168171
let template = std::fs::read_to_string(&template_path).with_context(|| {
169172
format!(

cli/src/commands/charter/new.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,10 @@ pub fn run(
6565
validate_spec_path(project_root, spec_path)?;
6666
}
6767

68-
// Resolve template (with i18n) and load.
69-
let templates_dir = straymark_dir.join("templates");
68+
// Resolve template (with i18n) and load. Charter templates live under
69+
// their own subdirectory (`templates/charter/`) since fw-4.12.0; the
70+
// helper handles i18n fallback within that subdir.
71+
let templates_dir = straymark_dir.join("templates").join("charter");
7072
let template_path = utils::resolve_localized_path(&templates_dir, "charter-template.md", lang);
7173
let template = std::fs::read_to_string(&template_path).with_context(|| {
7274
format!(
@@ -505,7 +507,7 @@ mod tests {
505507
use super::*;
506508

507509
/// Minimal template that covers all substitution points the runner touches.
508-
/// Mirrors the structure of dist/.straymark/templates/charter-template.md
510+
/// Mirrors the structure of dist/.straymark/templates/charter/charter-template.md
509511
/// without the full body.
510512
const TEMPLATE: &str = r#"---
511513
charter_id: CHARTER-NN

cli/src/commands/status.rs

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use anyhow::Result;
22
use colored::Colorize;
3-
use std::path::PathBuf;
3+
use std::path::{Path, PathBuf};
44

5+
use crate::charter::{self, CharterStatus};
56
use crate::config::StrayMarkConfig;
67
use crate::manifest::DistManifest;
78
use crate::utils::{self, pad_right_visual, visual_width};
@@ -223,6 +224,13 @@ pub fn run(path: &str) -> Result<()> {
223224
);
224225
println!();
225226

227+
// ── Charters ──
228+
// Charters are an optional pattern (bounded units of work). Surfaced as a
229+
// dedicated block so adopters of `straymark charter new` see them in the
230+
// canonical health view; projects without Charters see a one-line hint.
231+
let charter_counts = count_charters(&target);
232+
print_charters_block(&charter_counts);
233+
226234
// ── Hints ──
227235
if total_missing > 0 {
228236
println!(
@@ -313,3 +321,99 @@ fn walk_files(dir: &std::path::Path) -> Vec<PathBuf> {
313321
}
314322
files
315323
}
324+
325+
/// Counts of Charters by lifecycle status. `total` includes parseable charters
326+
/// only; `unparseable` reports files that look like charters by filename but
327+
/// failed schema parse, so the user knows to fix them.
328+
struct CharterCounts {
329+
declared: usize,
330+
in_progress: usize,
331+
closed: usize,
332+
unparseable: usize,
333+
total: usize,
334+
}
335+
336+
fn count_charters(project_root: &Path) -> CharterCounts {
337+
let (charters, errors) = charter::discover_and_parse(project_root);
338+
let mut declared = 0;
339+
let mut in_progress = 0;
340+
let mut closed = 0;
341+
for c in &charters {
342+
match c.frontmatter.status {
343+
CharterStatus::Declared => declared += 1,
344+
CharterStatus::InProgress => in_progress += 1,
345+
CharterStatus::Closed => closed += 1,
346+
}
347+
}
348+
CharterCounts {
349+
declared,
350+
in_progress,
351+
closed,
352+
unparseable: errors.len(),
353+
total: charters.len(),
354+
}
355+
}
356+
357+
fn print_charters_block(c: &CharterCounts) {
358+
println!(" {}", "Charters".bold());
359+
if c.total == 0 && c.unparseable == 0 {
360+
println!(
361+
" {} {}",
362+
"·".dimmed(),
363+
"No Charters yet — run `straymark charter new` to declare one (see STRAYMARK.md §15).".dimmed(),
364+
);
365+
println!();
366+
return;
367+
}
368+
369+
let rows: Vec<(&str, usize, colored::Color)> = vec![
370+
("declared", c.declared, colored::Color::White),
371+
("in-progress", c.in_progress, colored::Color::Yellow),
372+
("closed", c.closed, colored::Color::Green),
373+
];
374+
let label_w = rows
375+
.iter()
376+
.map(|(l, _, _)| visual_width(l))
377+
.max()
378+
.unwrap_or(11);
379+
let count_w = 5;
380+
381+
println!();
382+
println!(
383+
" {} {} {}",
384+
pad_right_visual("Status", label_w).dimmed(),
385+
"│".dimmed(),
386+
pad_right_visual("Count", count_w).dimmed(),
387+
);
388+
println!(
389+
" {}",
390+
format!("{}─┼─{}", "─".repeat(label_w), "─".repeat(count_w)).dimmed()
391+
);
392+
393+
for (label, count, color) in &rows {
394+
let count_str = format!("{count:>count_w$}");
395+
let padded = pad_right_visual(label, label_w);
396+
if *count > 0 {
397+
println!(" {} │ {}", padded, count_str.color(*color).bold());
398+
} else {
399+
println!(" {} │ {}", padded.dimmed(), count_str.dimmed());
400+
}
401+
}
402+
403+
let total_str = format!("{:>count_w$}", c.total);
404+
println!(
405+
" {} │ {}",
406+
pad_right_visual("TOTAL", label_w).bold(),
407+
total_str.cyan().bold(),
408+
);
409+
410+
if c.unparseable > 0 {
411+
println!(
412+
" {} {} unparseable Charter file{} — run `straymark charter list` to see the warning detail.",
413+
"!".yellow().bold(),
414+
c.unparseable,
415+
if c.unparseable == 1 { "" } else { "s" },
416+
);
417+
}
418+
println!();
419+
}

cli/tests/charter_close_test.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,21 @@ const TELEMETRY_SCHEMA: &str = include_str!(
5353
/// after fw-4.6.0 ships.
5454
fn setup_straymark(dir: &Path) {
5555
let straymark = dir.join(".straymark");
56-
std::fs::create_dir_all(straymark.join("templates")).unwrap();
56+
std::fs::create_dir_all(straymark.join("templates").join("charter")).unwrap();
5757
std::fs::create_dir_all(straymark.join("schemas")).unwrap();
5858
std::fs::write(straymark.join("config.yml"), "language: en\n").unwrap();
5959
std::fs::write(
60-
straymark.join("templates").join("charter-template.md"),
60+
straymark
61+
.join("templates")
62+
.join("charter")
63+
.join("charter-template.md"),
6164
CHARTER_TEMPLATE,
6265
)
6366
.unwrap();
6467
std::fs::write(
6568
straymark
6669
.join("templates")
70+
.join("charter")
6771
.join("charter-telemetry-template.yaml"),
6872
TELEMETRY_TEMPLATE,
6973
)

cli/tests/charter_drift_test.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,15 @@ fn bash_available() -> bool {
4040

4141
fn setup_straymark(dir: &Path) {
4242
let straymark = dir.join(".straymark");
43-
std::fs::create_dir_all(straymark.join("templates")).unwrap();
43+
std::fs::create_dir_all(straymark.join("templates").join("charter")).unwrap();
4444
std::fs::create_dir_all(straymark.join("scripts")).unwrap();
4545
std::fs::create_dir_all(straymark.join("07-ai-audit/agent-logs")).unwrap();
4646
std::fs::write(straymark.join("config.yml"), "language: en\n").unwrap();
4747
std::fs::write(
48-
straymark.join("templates").join("charter-template.md"),
48+
straymark
49+
.join("templates")
50+
.join("charter")
51+
.join("charter-template.md"),
4952
CHARTER_TEMPLATE,
5053
)
5154
.unwrap();

cli/tests/charter_test.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fn setup_straymark_with_charter_template(dir: &std::path::Path) {
1111
std::fs::write(straymark.join("config.yml"), "language: en\n").unwrap();
1212

1313
// Bundled template. We ship the actual template from
14-
// dist/.straymark/templates/charter-template.md in the framework; this test
14+
// dist/.straymark/templates/charter/charter-template.md in the framework; this test
1515
// helper inlines a structurally-equivalent copy so tests don't depend on
1616
// the dist/ path being available at test runtime.
1717
let template = r#"---
@@ -76,7 +76,9 @@ When closing this Charter (post-merge):
7676
7777
1. Drift check.
7878
"#;
79-
std::fs::write(straymark.join("templates").join("charter-template.md"), template).unwrap();
79+
let charter_templates = straymark.join("templates").join("charter");
80+
std::fs::create_dir_all(&charter_templates).unwrap();
81+
std::fs::write(charter_templates.join("charter-template.md"), template).unwrap();
8082
}
8183

8284
#[test]
@@ -316,13 +318,15 @@ fn charter_new_uses_es_template_when_config_says_es() {
316318
std::fs::write(straymark.join("config.yml"), "language: es\n").unwrap();
317319

318320
// EN template (fallback).
321+
let charter_templates = straymark.join("templates").join("charter");
322+
std::fs::create_dir_all(charter_templates.join("i18n").join("es")).unwrap();
319323
std::fs::write(
320-
straymark.join("templates").join("charter-template.md"),
324+
charter_templates.join("charter-template.md"),
321325
"---\ncharter_id: CHARTER-NN\nstatus: declared\neffort_estimate: M\ntrigger: \"[x]\"\n---\n\n# Charter: [BRIEF TITLE]\n\nEN body.\n",
322326
).unwrap();
323327
// ES translation.
324328
std::fs::write(
325-
straymark.join("templates").join("i18n").join("es").join("charter-template.md"),
329+
charter_templates.join("i18n").join("es").join("charter-template.md"),
326330
"---\ncharter_id: CHARTER-NN\nstatus: declared\neffort_estimate: M\ntrigger: \"[x]\"\n---\n\n# Charter: [TÍTULO BREVE]\n\nES body.\n",
327331
).unwrap();
328332

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
---
2+
description: Scaffold a Charter — StrayMark's bounded unit of work that pairs declarative ex-ante scope with telemetry ex-post. Use when starting a multi-session implementation block (>1 day, >5 tasks, multi-phase).
3+
---
4+
5+
# StrayMark Charter Scaffold Skill
6+
7+
Declare a Charter at the start of a bounded, auditable unit of work — *not* every change. Charters wrap multi-session work that warrants a stable scope contract you can drift-check at close. They are conceptually distinct from the 12+4 governance document types (AILOG, ADR, AIDEC, …): Charters live at `.straymark/charters/NN-slug.md` and use a sequential prefix instead of a date prefix.
8+
9+
> See `STRAYMARK.md §15` and `.straymark/00-governance/SPECKIT-CHARTER-BRIDGE.md` for the lifecycle and the SpecKit ↔ Charter bridge.
10+
11+
## When to use this skill
12+
13+
Trigger on any of:
14+
15+
- Multi-session implementation block (>1 day, >5 tasks across phases).
16+
- Work that warrants external audit at completion.
17+
- A SpecKit feature has reached `tasks.md` and the operator wants a stable scope contract before `/speckit-implement`.
18+
- The user asks to "declare", "open", or "start" a Charter.
19+
20+
If the work is a single-session change → use `straymark-ailog` instead.
21+
22+
## Instructions
23+
24+
### 1. Gather context
25+
26+
```bash
27+
# Sequential number of the Charter being created
28+
straymark charter list 2>/dev/null | tail -5 || true
29+
30+
# Surrounding spec / AILOG context — Charters frequently originate from one
31+
ls specs/*/spec.md 2>/dev/null | head -5
32+
ls .straymark/07-ai-audit/agent-logs/AILOG-*.md 2>/dev/null | tail -5
33+
```
34+
35+
### 2. Confirm with user
36+
37+
Surface the required and optional inputs:
38+
39+
- **Required**: title (one line), effort estimate (`XS | S | M | L`).
40+
- **Optional but encouraged**: one of `--from-ailog AILOG-ID` (post-MVP / maintenance origin) or `--from-spec specs/.../spec.md` (greenfield / SpecKit origin).
41+
- **Default** effort: M.
42+
43+
### 3. Pick origin and effort
44+
45+
- **Effort heuristic**: XS (≤ half day), S (≤ 1 day), M (1–3 days, default), L (≥ 1 week).
46+
- **Origin precedence**: a single live AILOG → `--from-ailog`; a SpecKit feature spec → `--from-spec`; otherwise omit (the operator can fill `originating_*` fields manually).
47+
48+
### 4. Run the CLI
49+
50+
The CLI does the scaffolding — slug derivation, sequential numbering, template substitution, write to `.straymark/charters/NN-slug.md`. The skill's job is to drive it with the right flags.
51+
52+
```bash
53+
# Greenfield, SpecKit-driven
54+
straymark charter new \
55+
--title "Workspace foundation for peek MVP" \
56+
--type M \
57+
--from-spec specs/001-peek-mvp-foundation/spec.md
58+
59+
# Post-MVP / maintenance, AILOG-driven
60+
straymark charter new \
61+
--title "Per-service anomaly thresholds" \
62+
--type S \
63+
--from-ailog AILOG-2026-04-28-021
64+
65+
# No explicit origin (operator fills frontmatter manually)
66+
straymark charter new --title "Refactor signal pipeline" --type M
67+
```
68+
69+
If the title would derive a poor slug, pass `--slug <slug>` explicitly.
70+
71+
### 5. Hand off to the operator
72+
73+
After the file is created, the CLI's "Next steps" output already lists what to fill. Surface it verbatim, then remind:
74+
75+
> 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).
76+
77+
### 6. Report result
78+
79+
```
80+
StrayMark: Created CHARTER-NN-slug at .straymark/charters/NN-slug.md
81+
status: declared
82+
effort_estimate: <XS|S|M|L>
83+
origin: <ailog | spec | none>
84+
```
85+
86+
## What this skill does NOT do
87+
88+
- It does not flip status to `in-progress` or `closed`. Lifecycle transitions are operator decisions.
89+
- It does not run drift or audit. Use `straymark charter drift` and the audit-prompt / audit-execute / audit-review skills for those phases.
90+
- It does not replace AILOGs. Day-to-day work inside the Charter still produces AILOGs; the Charter aggregates them via `originating_ailogs:`.

dist/.agent/workflows/straymark-new.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ If the user specified a document type (e.g., `/straymark-new ailog`), skip to st
1616

1717
Valid types: `ailog`, `aidec`, `adr`, `eth`, `req`, `tes`, `inc`, `tde`, `sec`, `mcard`, `sbom`, `dpia`
1818

19+
> **Charter is not a `straymark new` type.** Charters are bounded units of work (filename `NN-slug.md`, sequential prefix) and have their own command. If the user asks for a Charter (`/straymark-new charter`, *"create a Charter"*, *"declare a Charter"*), redirect to the `straymark-charter-new` skill.
20+
1921
### 2. Analyze Context
2022

2123
Gather information about recent changes:
@@ -52,6 +54,7 @@ Based on the analysis, suggest a document type:
5254
| Bug fixes, hotfixes | INC |
5355
| `TODO`, `FIXME`, `HACK` comments added | TDE |
5456
| Requirements or spec files | REQ |
57+
| Multi-session implementation block (>1 day, >5 tasks, multi-phase) | **Charter** — redirect to `straymark-charter-new` (Charters use `straymark charter new`, not `straymark new`) |
5558

5659
### 4. Confirm with User
5760

dist/.agent/workflows/straymark-status.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ Check these directories for each document type:
3737
| SBOM | `SBOM-` | `.straymark/07-ai-audit/` |
3838
| DPIA | `DPIA-` | `.straymark/07-ai-audit/ethical-reviews/` |
3939

40+
Also enumerate **Charters** (bounded units of work — distinct from doc types; see STRAYMARK.md §15):
41+
42+
```bash
43+
# Charters list with status counts (declared / in-progress / closed)
44+
straymark charter list 2>/dev/null
45+
```
46+
47+
If the project has no Charters yet but the work clearly fits the trigger (multi-session implementation block, >5 tasks across phases, audit value), surface that as a gap and recommend the `straymark-charter-new` skill.
48+
4049
### 2. Find Modified Source Files
4150

4251
Identify source files that were modified and might need documentation:
@@ -69,6 +78,7 @@ For each modified source file, check if there's a corresponding StrayMark docume
6978
- Changes involving personal data processing should have a DPIA
7079
- Test files should have a TES record
7180
- Bug fixes or incidents should have an INC record
81+
- Multi-session implementation blocks (>1 day, >5 tasks, multi-phase) should have an open or closed **Charter** at `.straymark/charters/`
7282

7383
### 4. Display Results
7484

0 commit comments

Comments
 (0)