Skip to content

Commit 9c3a613

Browse files
montfortclaude
andauthored
feat(framework+cli): fw-4.14.2 / cli-3.13.1 — TDE terminal resolved (closes #149) (#151)
Closes #149 — surfaced by Sentinel post-CHARTER-17 housekeeping. TDE adopters who keep documents on disk as audit history after the debt is paid had no canonical status to mark the closure; `accepted` / `superseded` / `deprecated` all carry the wrong semantics. The validator rejected `resolved` with META-003. This release ships Option A of the issue's proposal triplet (flat enum + `resolved`) and documents Option B (per-doc-type lifecycle vocabulary) as the deliberate next evolution. CLI changes (cli-3.13.1): - cli/src/validation.rs:48: add `resolved` to VALID_STATUSES with an extensive comment explaining (1) the TDE semantics it captures vs. the alternatives, (2) why Option A ships now over B/C, and (3) what the future per-doc-type lookup will tighten. - cli/tests/validate_test.rs: two new regression tests — `test_validate_tde_resolved_terminal_state` (positive) and `test_validate_rejects_non_canonical_ailog_terminals` (negative; `final` / `closed` / `completed` continue to fail per #149's Sentinel-invention caveat). Framework changes (fw-4.14.2): - dist/.straymark/00-governance/DOCUMENTATION-POLICY.md §3 (EN + ES + zh-CN): lifecycle diagram extended with the `resolved` terminal branch; new row in the status table with the principled distinction from `accepted` / `superseded` / `deprecated`; §6 TDE row annotated with the `identified → resolved` lifecycle. - dist/.straymark/templates/TEMPLATE-TDE.md (EN + ES + zh-CN): frontmatter `status: identified` annotated with the transition; new optional `## Resolution` body section (Resolved by / Date / Verification / Notes). Adopter guidance: `straymark update-framework` + `straymark update-cli` unblock TDE files marked `status: resolved` immediately. AILOGs invented `final` / `closed` / `completed` continue to fail — canonical AILOG terminal is `accepted` per TEMPLATE-AILOG.md. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent c166369 commit 9c3a613

31 files changed

Lines changed: 243 additions & 65 deletions

CHANGELOG.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,39 @@ and this project uses [independent versioning](README.md#versioning) for Framewo
77

88
---
99

10+
## Framework 4.14.2 / CLI 3.13.1 — TDE terminal `resolved` (closes #149)
11+
12+
Closes [#149](https://github.com/StrangeDaysTech/straymark/issues/149) — surfaced by Sentinel post-CHARTER-17 housekeeping. TDE adopters who keep documents on disk as audit history after the debt is paid had no canonical status to mark the closure; `accepted` / `superseded` / `deprecated` all carry the wrong semantics. The validator rejected `resolved` with `META-003`.
13+
14+
This release ships **Option A** of the issue's proposal triplet (flat enum + `resolved`) and documents **Option B** (per-doc-type lifecycle vocabulary) as the deliberate next evolution.
15+
16+
### Added (CLI)
17+
18+
- **`resolved`** is now a valid value in `VALID_STATUSES` (`cli/src/validation.rs:48`). Adopter-facing effect: `straymark validate` accepts `status: resolved` on TDE documents without `META-003`. Two new tests pin the behavior:
19+
- `test_validate_tde_resolved_terminal_state` — TDE with `status: resolved` passes.
20+
- `test_validate_rejects_non_canonical_ailog_terminals``final`, `closed`, `completed` (Sentinel's invented AILOG terminals reported in #149) continue to fail with `META-003`. Adopters using these on AILOGs should migrate to `accepted` per `TEMPLATE-AILOG.md` and `DOCUMENTATION-POLICY.md §6`.
21+
22+
### Changed (Framework)
23+
24+
- **`dist/.straymark/00-governance/DOCUMENTATION-POLICY.md` §3 (EN + i18n/es + i18n/zh-CN)** — lifecycle diagram extended with the `resolved` terminal branch (TDE-only); new `resolved` row in the status table with the principled distinction from `accepted` / `superseded` / `deprecated`; §6 table column updated to note that TDE enters at `identified` and has its own terminal `resolved`.
25+
- **`dist/.straymark/templates/TEMPLATE-TDE.md` (EN + i18n/es + i18n/zh-CN)** — frontmatter `status: identified` annotated with the `→ resolved` transition; new optional `## Resolution` body section (omit while the debt is still open) with fields for Resolved by / Date / Verification / Notes.
26+
27+
### Deliberately deferred (Option B)
28+
29+
The principled fix to the per-doc-type lifecycle vocabulary problem is to promote the flat `VALID_STATUSES` enum to a `HashMap<DocType, Vec<&str>>` so each doc type has its own canonical state machine and the validator inspects `doc.doc_type` before deciding which set to apply. The reasons to defer:
30+
31+
- Option A unblocks adopters today (Sentinel reports 2 TDE files with `status: resolved`); shipping it is ~30 LOC + docs.
32+
- Option B is ~150 LOC + a per-type test matrix expansion + non-trivial decisions about which terminals each type should have. Doing it pre-announcement risks calcifying choices we'd rather make based on a second adopter's lifecycle needs.
33+
- The `VALID_STATUSES` constant doc-comment in `validation.rs` and the explanatory paragraph in `DOCUMENTATION-POLICY.md §3` both name the trade-off explicitly: "TDE is the only type today with a custom terminal; the validator accepts `resolved` globally as a stop-gap. Issue #149 Option B will scope `resolved` strictly to TDE; until then, using it on non-TDE documents passes validation but is semantically incorrect."
34+
35+
### Adopter guidance
36+
37+
- `straymark update-framework` brings the new `TEMPLATE-TDE.md` and `DOCUMENTATION-POLICY.md`. Existing TDE files are unaffected — the template change is purely additive.
38+
- `straymark update-cli` brings the relaxed validator. TDE files marked `status: resolved` start passing immediately.
39+
- Sentinel-side AILOGs marked `final` / `closed` / `completed` continue to fail validation. The fix is to migrate those to `accepted` (the canonical AILOG terminal per `TEMPLATE-AILOG.md`) and capture the "work completed" semantics in the body or in the originating Charter's telemetry, not in the AILOG status field.
40+
41+
---
42+
1043
## Framework 4.14.1 — Docs sync for batch-complete + Batch Ledger discoverability
1144

1245
Framework-only patch that closes the documentation gap left by `fw-4.14.0` / `cli-3.13.0`. The release added the `batch-complete` subcommand and the Batch Ledger workflow but didn't surface them in three places adopters and contributors discover the project from: the root `README.md` (and i18n overlays), the project's user-facing comparison/feature lists, and **`dist/STRAYMARK.md`** — the governance file shipped to every adopter via `straymark init`.

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,8 @@ StrayMark uses independent version tags for each component:
274274

275275
| Component | Tag prefix | Example | Includes |
276276
|-----------|-----------|---------|----------|
277-
| Framework | `fw-` | `fw-4.14.1` | Templates (12 types), governance, directives, Charter template + schema |
278-
| CLI | `cli-` | `cli-3.13.0` | The `straymark` binary |
277+
| Framework | `fw-` | `fw-4.14.2` | Templates (12 types), governance, directives, Charter template + schema |
278+
| CLI | `cli-` | `cli-3.13.1` | The `straymark` binary |
279279

280280
Check installed versions with `straymark status` or `straymark about`.
281281

@@ -307,7 +307,7 @@ See [CLI Reference](https://github.com/StrangeDaysTech/straymark/blob/main/docs/
307307
```bash
308308
# Download the latest framework release ZIP from GitHub
309309
# Go to https://github.com/StrangeDaysTech/straymark/releases
310-
# and download the latest fw-* release (e.g., fw-4.14.1)
310+
# and download the latest fw-* release (e.g., fw-4.14.2)
311311
312312
# Extract and copy to your project
313313
unzip straymark-fw-*.zip -d your-project/

cli/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "straymark-cli"
3-
version = "3.13.0"
3+
version = "3.13.1"
44
edition = "2021"
55
description = "CLI for StrayMark — the cognitive discipline your AI-assisted projects need"
66
license = "MIT"

cli/src/validation.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,33 @@ impl ValidationResult {
4242
}
4343

4444
/// Valid status values per DOCUMENTATION-POLICY.md §3 lifecycle + §6 per-type defaults.
45-
/// `identified` is the canonical TDE entry state (agent-driven discovery, awaits
46-
/// human prioritization); functionally equivalent to `draft` for lifecycle gating
47-
/// but semantically distinct in adopter analytics.
45+
///
46+
/// - `identified` is the canonical TDE entry state (agent-driven discovery, awaits
47+
/// human prioritization); functionally equivalent to `draft` for lifecycle gating
48+
/// but semantically distinct in adopter analytics (regression #130).
49+
/// - `resolved` is the canonical TDE terminal state for "the debt described here
50+
/// was addressed; document is kept on disk as audit history". Neither `accepted`
51+
/// ("we accept this debt continues to exist"), `superseded` ("another TDE took
52+
/// its place"), nor `deprecated` ("the TDE concept itself is no longer relevant")
53+
/// captures this semantics correctly. Issue #149 surfaced the gap empirically
54+
/// in Sentinel post-CHARTER-17 housekeeping.
55+
///
56+
/// **Per-doc-type lifecycle vocabulary** (Option B in issue #149) is the principled
57+
/// next evolution: promote this flat enum to a `HashMap<DocType, Vec<&str>>` so each
58+
/// doc type has its own canonical state machine and the validator inspects
59+
/// `doc.doc_type` before deciding which set to apply. Deferred deliberately —
60+
/// shipping Option A (flat enum + `resolved`) keeps the validator's surface stable
61+
/// and avoids per-type branching until a second doc type needs a non-standard
62+
/// terminal. Adding `resolved` flat-globally is mildly permissive (an ADR with
63+
/// `status: resolved` would pass) but the damage is bounded: `DOCUMENTATION-POLICY`
64+
/// documents `resolved` as TDE-specific, and the per-type expansion in Option B
65+
/// will tighten the validation without breaking any existing TDE adopters.
4866
const VALID_STATUSES: &[&str] = &[
4967
"draft",
5068
"identified",
5169
"review",
5270
"accepted",
71+
"resolved",
5372
"superseded",
5473
"deprecated",
5574
];

cli/tests/validate_test.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,61 @@ fn test_validate_dpia_document_valid() {
349349
.stdout(predicate::str::contains("passed validation"));
350350
}
351351

352+
/// Regression test for issue #149: TDE documents can move to `status: resolved`
353+
/// when the debt described has been addressed. The document is kept on disk as
354+
/// audit history. `accepted` / `superseded` / `deprecated` do not capture this
355+
/// semantics correctly.
356+
#[test]
357+
fn test_validate_tde_resolved_terminal_state() {
358+
let dir = TempDir::new().unwrap();
359+
setup_straymark(dir.path());
360+
361+
create_doc(
362+
dir.path(),
363+
"06-evolution/technical-debt",
364+
"TDE-2026-05-11-001-architectural-refactor.md",
365+
"id: TDE-2026-05-11-001\ntitle: Architectural Refactor Debt\nstatus: resolved\ncreated: 2026-05-11\nagent: claude-code-v1.0\nconfidence: high\nreview_required: false\nrisk_level: medium\ntype: architecture\nimpact: high\neffort: medium\ntags:\n - architecture\nrelated: []\npriority: null\nassigned_to: null",
366+
);
367+
368+
let mut cmd = Command::cargo_bin("straymark").unwrap();
369+
cmd.arg("validate")
370+
.arg(dir.path().to_str().unwrap())
371+
.assert()
372+
.success()
373+
.stdout(predicate::str::contains("passed validation"));
374+
}
375+
376+
/// Regression test for issue #149: status values reported by Sentinel as invented
377+
/// local terminals (`final`, `closed`, `completed`) MUST continue to fail
378+
/// validation. They are not canonical AILOG terminals — the canonical AILOG
379+
/// terminal is `accepted` per TEMPLATE-AILOG.md and DOCUMENTATION-POLICY.md §6.
380+
/// Documented in CHANGELOG fw-4.14.2 / cli-3.13.1 as "adopters using `final` /
381+
/// `closed` / `completed` should migrate to `accepted`".
382+
#[test]
383+
fn test_validate_rejects_non_canonical_ailog_terminals() {
384+
for status in ["final", "closed", "completed"] {
385+
let dir = TempDir::new().unwrap();
386+
setup_straymark(dir.path());
387+
388+
create_doc(
389+
dir.path(),
390+
"07-ai-audit/agent-logs",
391+
"AILOG-2026-05-13-001-test.md",
392+
&format!(
393+
"id: AILOG-2026-05-13-001\ntitle: Test\nstatus: {}\ncreated: 2026-05-13\nagent: claude-code-v1.0\nconfidence: high\nreview_required: false\nrisk_level: low\ntags: []\nrelated: []",
394+
status
395+
),
396+
);
397+
398+
let mut cmd = Command::cargo_bin("straymark").unwrap();
399+
cmd.arg("validate")
400+
.arg(dir.path().to_str().unwrap())
401+
.assert()
402+
.failure()
403+
.stdout(predicate::str::contains("META-003"));
404+
}
405+
}
406+
352407
/// Regression test for issue #130: TDE documents ship with `status: identified`
353408
/// per TEMPLATE-TDE.md and DOCUMENTATION-POLICY.md §6 — the validator must accept
354409
/// it as a valid lifecycle entry state.

dist/.straymark/00-governance/AGENT-RULES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,4 +379,4 @@ When a project accumulates a high volume of AILOGs across multiple Charters and
379379
380380
---
381381
382-
*StrayMark v4.14.1 | [Strange Days Tech](https://strangedays.tech)*
382+
*StrayMark v4.14.2 | [Strange Days Tech](https://strangedays.tech)*

dist/.straymark/00-governance/C4-DIAGRAM-GUIDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,4 +234,4 @@ Use a Level 1 (Context) diagram to illustrate:
234234

235235
---
236236

237-
*StrayMark v4.14.1 | [Strange Days Tech](https://strangedays.tech)*
237+
*StrayMark v4.14.2 | [Strange Days Tech](https://strangedays.tech)*

dist/.straymark/00-governance/DOCUMENTATION-POLICY.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,17 +156,22 @@ identified ──┐
156156
│ └──────► superseded
157157
158158
└──► (TDE-only entry state, see §6)
159+
160+
161+
resolved
162+
(TDE-only terminal — debt paid; see §6)
159163
```
160164
161165
| Status | Description |
162166
|--------|-------------|
163167
| `identified` | Entry state for agent-driven discovery types (TDE today). Functionally equivalent to `draft` for lifecycle gating — a human reviewer is expected to prioritize and promote it. Semantically distinct so adopter analytics can distinguish "agent found this debt" from "human is drafting a deliberate doc". |
164168
| `draft` | In draft, pending review |
165169
| `accepted` | Approved and current |
170+
| `resolved` | **TDE-only terminal state**: the technical debt described in this document has been addressed; the file is kept on disk as audit history. Distinct from `accepted` ("we accept this debt continues to exist"), `superseded` ("another TDE replaced this one"), and `deprecated` ("the TDE concept itself is no longer relevant"). The canonical closing reference (the Charter, PR, or commit that paid the debt) goes in the `## Resolution` body section. |
166171
| `deprecated` | Obsolete, but kept as reference |
167172
| `superseded` | Replaced by another document |
168173
169-
The per-type default status mapping lives in §6 — most types enter at `draft` or `accepted`, but TDE enters at `identified` per the agent-autonomy boundary (agent identifies, human prioritizes).
174+
The per-type default status mapping lives in §6 — most types enter at `draft` or `accepted`, but TDE enters at `identified` per the agent-autonomy boundary (agent identifies, human prioritizes). TDE is the only type today with a custom terminal state (`resolved`); the validator accepts `resolved` globally as a stop-gap. A future per-doc-type lifecycle vocabulary (issue #149 Option B) will scope `resolved` to TDE strictly; until then, using it on non-TDE documents is allowed by the validator but semantically incorrect.
170175
171176
---
172177
@@ -269,7 +274,7 @@ For documents that require multiple reviewers (e.g., ETH with both legal and eng
269274
| `REQ` | Requirement | `01-requirements/` | `draft` | Yes |
270275
| `TES` | Test Plan | `04-testing/` | `draft` | Yes |
271276
| `INC` | Incident Post-mortem | `05-operations/incidents/` | `draft` | Yes |
272-
| `TDE` | Technical Debt | `06-evolution/technical-debt/` | `identified` | No |
277+
| `TDE` | Technical Debt | `06-evolution/technical-debt/` | `identified` (enters here; terminal `resolved` when debt paid — TDE-only) | No |
273278
| `SEC` | Security Assessment | `08-security/` | `draft` | Yes (always) |
274279
| `MCARD` | Model/System Card | `09-ai-models/` | `draft` | Yes (always) |
275280
| `SBOM` | Software Bill of Materials | `07-ai-audit/` | `accepted` | No |
@@ -313,4 +318,4 @@ See also [ADR-2025-01-20-001] for architectural context.
313318
314319
---
315320

316-
*StrayMark v4.14.1 | [Strange Days Tech](https://strangedays.tech)*
321+
*StrayMark v4.14.2 | [Strange Days Tech](https://strangedays.tech)*

dist/.straymark/00-governance/FOLLOW-UPS-BACKLOG-PATTERN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,4 +233,4 @@ Contributed via [issue #111](https://github.com/StrangeDaysTech/straymark/issues
233233

234234
---
235235

236-
*StrayMark v4.14.1 | [Strange Days Tech](https://strangedays.tech)*
236+
*StrayMark v4.14.2 | [Strange Days Tech](https://strangedays.tech)*

0 commit comments

Comments
 (0)