From 343ac783845674e42b840122ab1f0dda4551a0bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Villase=C3=B1or=20Montfort?= <195970+montfort@users.noreply.github.com> Date: Sat, 18 Jul 2026 03:46:59 -0600 Subject: [PATCH] =?UTF-8?q?feat(followups):=20premise/verify=20reframe=20?= =?UTF-8?q?=E2=80=94=20dated=20hypotheses=20(fw-4.36.0=20/=20cli-3.37.0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements the signed AIDEC-2026-07-18-001 (#365 Part 1, Weft field report): reframe follow-up registry entries as dated, decaying hypotheses and place premise verification at execution, not capture. The backlog is a speculative buffer — cheap capture is its value — so the only real bug is executing an entry without re-testing its premise. Three layers, at the operator's chosen depth (doc + schema + CLI affordance): - **CLI**: new `followups verify FU-NNN` verb (surface the premise, `--premise` to record it, `--verified [--at]` to stamp `Verified-at`); `followups promote` now surfaces the premise with a re-verify reminder and stamps `Verified-at` with `--premise-verified`; `followups status` shows the fields and nudges when an actionable entry's premise is unverified. Both affordances remind and record — they never gate. `Entry` gains optional `premise`/`verified_at` (lenient parse); reuses charter::new's markup/sentence helpers. - **Schema + template**: optional `premise`/`verified_at` in `$defs.entry`; backward-compatible, `schema_version` stays v1. - **Docs (EN + es + zh-CN)**: new "Epistemic status" section in the pattern doc, reconciled "planning input" framing, AGENT-RULES §13 execution directive, CLI-REFERENCE command docs. Verified: full suite green (38 groups) + new unit/integration tests; clippy clean on new files; end-to-end with the release binary (status nudge → verify read-only → verify record+stamp → nudge clears → promote --premise-verified); schema JSON valid; `straymark validate` 0 errors on the new AILOG/AIDEC. Governed AILOG: .straymark/07-ai-audit/agent-logs/AILOG-2026-07-18-001. Co-Authored-By: Claude Opus 4.8 (1M context) --- ...2026-07-18-001-followups-premise-verify.md | 80 ++++++++++ CHANGELOG.md | 15 ++ CLAUDE.md | 3 +- Cargo.lock | 2 +- README.md | 4 +- cli/Cargo.toml | 2 +- cli/src/commands/charter/close.rs | 4 +- cli/src/commands/followups/mod.rs | 4 +- cli/src/commands/followups/promote.rs | 69 ++++++++- cli/src/commands/followups/status.rs | 35 +++++ cli/src/commands/followups/verify.rs | 142 ++++++++++++++++++ cli/src/followups.rs | 37 +++++ cli/src/main.rs | 55 ++++++- cli/tests/followups_test.rs | 121 +++++++++++++++ dist/.straymark/00-governance/AGENT-RULES.md | 8 +- .../00-governance/C4-DIAGRAM-GUIDE.md | 2 +- .../00-governance/DOCUMENTATION-POLICY.md | 2 +- .../FOLLOW-UPS-BACKLOG-PATTERN.md | 31 +++- .../00-governance/QUICK-REFERENCE.md | 2 +- .../00-governance/i18n/es/AGENT-RULES.md | 8 +- .../00-governance/i18n/es/C4-DIAGRAM-GUIDE.md | 2 +- .../i18n/es/DOCUMENTATION-POLICY.md | 2 +- .../i18n/es/FOLLOW-UPS-BACKLOG-PATTERN.md | 31 +++- .../00-governance/i18n/es/QUICK-REFERENCE.md | 2 +- .../00-governance/i18n/zh-CN/AGENT-RULES.md | 8 +- .../i18n/zh-CN/C4-DIAGRAM-GUIDE.md | 2 +- .../i18n/zh-CN/DOCUMENTATION-POLICY.md | 2 +- .../i18n/zh-CN/FOLLOW-UPS-BACKLOG-PATTERN.md | 31 +++- .../i18n/zh-CN/QUICK-REFERENCE.md | 2 +- .../schemas/follow-ups-backlog.schema.v1.json | 8 + .../templates/follow-ups-backlog.md | 8 + dist/dist-manifest.yml | 2 +- docs/adopters/CLI-REFERENCE.md | 30 +++- docs/i18n/es/README.md | 4 +- docs/i18n/es/adopters/CLI-REFERENCE.md | 30 +++- docs/i18n/zh-CN/README.md | 4 +- docs/i18n/zh-CN/adopters/CLI-REFERENCE.md | 30 +++- 37 files changed, 775 insertions(+), 49 deletions(-) create mode 100644 .straymark/07-ai-audit/agent-logs/AILOG-2026-07-18-001-followups-premise-verify.md create mode 100644 cli/src/commands/followups/verify.rs diff --git a/.straymark/07-ai-audit/agent-logs/AILOG-2026-07-18-001-followups-premise-verify.md b/.straymark/07-ai-audit/agent-logs/AILOG-2026-07-18-001-followups-premise-verify.md new file mode 100644 index 00000000..437aa954 --- /dev/null +++ b/.straymark/07-ai-audit/agent-logs/AILOG-2026-07-18-001-followups-premise-verify.md @@ -0,0 +1,80 @@ +--- +id: AILOG-2026-07-18-001 +title: Implement follow-ups premise/verify reframe (AIDEC-2026-07-18-001, #365 Part 1) +status: accepted +created: 2026-07-18 +agent: claude-opus-4-8-1m +confidence: high +review_required: false +risk_level: low +eu_ai_act_risk: not_applicable +nist_genai_risks: [] +iso_42001_clause: [] +lines_changed: 0 +files_modified: [] +observability_scope: none +tags: [follow-ups, epistemics, cli, governance, self-adoption, adopter-feedback] +related: [AIDEC-2026-07-18-001-followups-as-hypotheses.md] +--- + +# AILOG: Implement follow-ups premise/verify reframe (AIDEC-2026-07-18-001) + +## Summary + +Implemented the three layers of the signed [`AIDEC-2026-07-18-001`](../decisions/AIDEC-2026-07-18-001-followups-as-hypotheses.md) — reframing follow-up registry entries as **dated, decaying hypotheses** and placing premise verification at execution, not capture (Weft field report #365 Part 1). Ships as **fw-4.36.0 / cli-3.37.0**. First substantive governed change of the self-adopted repo, so this AILOG lives in the in-force `/.straymark/` tree. + +## Context + +Three genuine Weft follow-ups (FU-017/FU-016/FU-010) each rested on a premise that was false *at write time* and cheap to falsify at read time. The registry is a speculative buffer — cheap capture is its value — so the only real bug is executing an entry without re-testing its premise. The AIDEC chose the full depth: doc + schema + CLI affordance (both `promote --premise-verified` and a new `verify` verb). + +## Actions Performed + +1. **CLI parsing** — added optional `premise` / `verified_at` to `followups::Entry` with lenient field aliases (`Verified-at` / `Verified at` / `verified_at`); the generic `set_entry_field` writes them. +2. **CLI shape A** — `followups promote` now surfaces the entry's `Premise` (falling back to `Notes`) with a re-verify reminder and, with `--premise-verified`, stamps `Verified-at`. Advisory: promotion proceeds either way. Threaded the new arg through `charter close`'s auto-promotion caller. +3. **CLI shape B** — new `followups verify FU-NNN` verb (`verify.rs` + `mod.rs` + `main.rs` routing): surfaces the premise, `--premise "..."` records/updates it, `--verified [--at DATE]` stamps `Verified-at`. Read-only with no flags. +4. **CLI status** — `followups status FU-NNN` shows `Premise` / `Verified-at` and nudges to re-verify when an actionable entry's premise is unverified. +5. **Schema + template** — added optional `premise` / `verified_at` to `$defs.entry`; template documents both and the discipline. +6. **Docs (EN + es + zh-CN)** — new "Epistemic status" section in the pattern doc, reconciled the "planning input" framing, documented the fields + CLI verbs, and added the "before acting on an entry (execution)" directive to `AGENT-RULES.md §13`. Updated `CLI-REFERENCE` command docs. +7. **Versioning** — `dist-manifest.yml` → 4.36.0, `cli/Cargo.toml` → 3.37.0 (+ `Cargo.lock`), governance footers, README/CLI-REFERENCE version tables (×3 locales), `CHANGELOG.md`, `CLAUDE.md` command table. + +## Decisions Made + +- **`premise`/`verified_at` are optional and lenient-parsed** — every existing registry stays valid; `schema_version` stays `v1` (experimental). No data migration. +- **The CLI reminds and records; it never gates.** Promotion proceeds without `--premise-verified`; `verify` with no flags is read-only. Human judgment stays out of the CLI, consistent with `promote`. +- **Both affordance shapes ship** (operator decision 2026-07-18): `verify` covers chores acted on without promotion; `promote`'s reminder covers TDE graduation. + +## Verification + +- Full workspace `cargo test` green (38 result groups). New unit test (parse + `set_entry_field` round-trip) and 6 integration tests (promote surfacing ± flag, verify record/read-only/unknown, status nudge). +- Clippy: no new warnings in `verify.rs`/`promote.rs`/`status.rs`. +- End-to-end with the release binary: `status` nudge when unverified → `verify` read-only surfacing → `verify --premise --verified` records the corrected premise + stamps `Verified-at` → nudge gone → `promote --premise-verified` surfaces the confirmed premise, promotes, and stamps. Schema JSON well-formed; loads via the `status` advisory validation. + +## Risk + +No new risk. All schema/CLI additions are additive and optional; no change to `drift` dedup, counters, or existing entry parsing. Behavioral (not enforced) adoption is by design — the discipline lives in the doc + the prompts. + +## Modified Files + +| File | Change | +|------|--------| +| `cli/src/followups.rs` | `Entry.premise` / `verified_at` + lenient parse + unit test | +| `cli/src/commands/followups/verify.rs` | New `verify` verb | +| `cli/src/commands/followups/promote.rs` | Premise surfacing + `--premise-verified` stamp | +| `cli/src/commands/followups/status.rs` | Show premise/verified-at + re-verify nudge | +| `cli/src/commands/followups/mod.rs` | Wire `verify` module | +| `cli/src/commands/charter/close.rs` | Thread `premise_verified: false` into auto-promote | +| `cli/src/commands/charter/new.rs` | `strip_inline_markup` / `leading_sentences` → `pub(crate)` (reused) | +| `cli/src/main.rs` | `verify` subcommand + `--premise-verified` flag + routing | +| `cli/tests/followups_test.rs` | Integration tests for verify + promote surfacing | +| `cli/Cargo.toml` | Version 3.37.0 | +| `dist/.straymark/schemas/follow-ups-backlog.schema.v1.json` | Optional `premise` / `verified_at` | +| `dist/.straymark/templates/follow-ups-backlog.md` | Document the fields + discipline | +| `dist/.straymark/00-governance/FOLLOW-UPS-BACKLOG-PATTERN.md` | Epistemic-status section (EN + es + zh-CN) | +| `dist/.straymark/00-governance/AGENT-RULES.md` | §13 execution directive (EN + es + zh-CN) | +| `dist/dist-manifest.yml` | Version 4.36.0 | +| `docs/adopters/CLI-REFERENCE.md` | `verify` + `--premise-verified` docs (EN + es + zh-CN) | +| `CHANGELOG.md` | Framework 4.36.0 / CLI 3.37.0 entry | + +## Follow-ups + +- None. The AIDEC's "read-only surfacing" and "both shapes" scope shipped in full; the historical-decisions migration is tracked separately in issue #368. diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f5039f3..9cadee6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,21 @@ and this project uses [independent versioning](README.md#versioning) for Framewo --- +## Framework 4.36.0 / CLI 3.37.0 — 2026-07-18 + +Follow-ups are dated hypotheses — verify the premise at execution, not at capture (#365 Part 1, [`AIDEC-2026-07-18-001`](.straymark/07-ai-audit/decisions/AIDEC-2026-07-18-001-followups-as-hypotheses.md)). From the Weft field report: three genuine follow-ups each rested on a premise that was false *at write time* and cheap to falsify at read time. + +### Added (Framework) + +- **Follow-ups pattern — "Epistemic status" reframe.** [`FOLLOW-UPS-BACKLOG-PATTERN.md`](dist/.straymark/00-governance/FOLLOW-UPS-BACKLOG-PATTERN.md) (EN + es + zh-CN) gains a first-class section framing a registry entry as a **dated, decaying hypothesis, not an instruction**: the backlog is a speculative buffer whose value is cheap capture, an under-verified entry is the *expected* status of a buffer item, and the only real bug is executing one without re-testing its premise. Discipline: **write cheaply at capture; re-verify the premise when you promote/act.** `AGENT-RULES.md §13` gains the matching "before acting on an entry (execution)" directive. +- **Two optional entry fields** in the registry schema (`$defs.entry`) and pattern doc: **`Premise`** (the load-bearing assumption an entry rests on) and **`Verified-at`** (the date it was last re-checked against the code). Backward-compatible; `schema_version` stays `v1` (experimental). Template documents both. + +### Added (CLI) + +- **`straymark followups verify FU-NNN`** *(new)* — re-verify a dated hypothesis's premise at execution: surface the `Premise` (or `Notes`), optionally record/update it (`--premise "..."`), and stamp `Verified-at` (`--verified [--at DATE]`). Read-only surfacing with no flags. +- **`straymark followups promote --premise-verified`** — promotion now surfaces the entry's premise with a re-verify reminder and, with the flag, stamps `Verified-at`. Advisory: promotion proceeds either way. +- `followups status FU-NNN` shows `Premise`/`Verified-at` and nudges to re-verify when an actionable entry's premise is unverified. The entry parser reads both fields leniently (`Verified-at` / `Verified at` / `verified_at`). + ## CLI 3.36.2 — 2026-07-18 ### Fixed (CLI) diff --git a/CLAUDE.md b/CLAUDE.md index 4cfc62b2..fb9bff0e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -273,7 +273,8 @@ Loom releases are GitHub-release-only (no crates.io while experimental). Tag for | `straymark followups status [FU-NNN]` | Registry pulse (counters recomputed on the fly) or entry detail | | `straymark followups drift [--apply] [--scan-all]` | Detect/extract AILOGs with unextracted follow-up content (native, anti-noise `suspected-closed`, recomputes CLI-owned counters even with zero extractions, upgrades v0→v1) | | `straymark followups recount` | Recompute the CLI-owned counters after a manual-triage session (no AILOG scan, idempotent) | -| `straymark followups promote FU-NNN` | Elevate an entry to a TDE document with `promoted_from_followup` traceability | +| `straymark followups promote FU-NNN [--premise-verified]` | Elevate an entry to a TDE document with `promoted_from_followup` traceability; surfaces the premise re-check, stamps `Verified-at` with the flag | +| `straymark followups verify FU-NNN [--premise "..."] [--verified] [--at DATE]` | Re-verify a dated hypothesis's premise at execution: surface/record the premise, stamp `Verified-at` (AIDEC-2026-07-18-001) | | `straymark architecture generate [path] [--force] [--out DIR]` | EXPERIMENTAL (Loom A1.2) — write a first-draft `architecture/model.yml` + `plan.drawio` by mining codebase structure (top-level source dirs → components) enriched with ADR C4 diagrams + "Affected Components" tables. `--force` overwrites; `--out` overrides the default `.straymark/architecture/` | | `straymark architecture sync [path] [--out DIR] [--apply]` | EXPERIMENTAL (Loom A1.3) — append-only: detect new top-level source dirs / ADR components not yet covered by the model and append them to `model.yml` + `plan.drawio` (never clobbers human edits/geometry). Dry-run by default; `--apply` writes | | `straymark architecture validate [path] [--out DIR] [--output FMT]` | EXPERIMENTAL (Loom A1.3) — report model↔plan.drawio integrity signals (`undrawn`/`unmodeled`/`empty`) via `core::architecture::validate_model`. `--output text\|json\|markdown`; exits 1 when any signal is found (CI-gateable) | diff --git a/Cargo.lock b/Cargo.lock index 1b2be5c6..c033dc64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2573,7 +2573,7 @@ dependencies = [ [[package]] name = "straymark-cli" -version = "3.36.2" +version = "3.37.0" dependencies = [ "anyhow", "arborist-metrics", diff --git a/README.md b/README.md index 58ca67f0..6837fed1 100644 --- a/README.md +++ b/README.md @@ -277,8 +277,8 @@ StrayMark uses independent version tags for each component: | Component | Tag prefix | Example | Includes | | --- | --- | --- | --- | -| Framework | `fw-` | `fw-4.35.0` | Templates (12 types), governance, directives, Charter template + schema | -| CLI | `cli-` | `cli-3.36.2` | The `straymark` binary | +| Framework | `fw-` | `fw-4.36.0` | Templates (12 types), governance, directives, Charter template + schema | +| CLI | `cli-` | `cli-3.37.0` | The `straymark` binary | | Loom (EXPERIMENTAL) | `loom-` | `loom-0.4.2` | The `straymark-loom` visualization server, downloaded on demand by `straymark loom serve` | Check installed versions with `straymark status` or `straymark about`. diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 091e67b2..32f91c46 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "straymark-cli" -version = "3.36.2" +version = "3.37.0" edition = "2021" description = "CLI for StrayMark — the cognitive discipline your AI-assisted projects need" license = "MIT" diff --git a/cli/src/commands/charter/close.rs b/cli/src/commands/charter/close.rs index 6579379e..8eb7f929 100644 --- a/cli/src/commands/charter/close.rs +++ b/cli/src/commands/charter/close.rs @@ -286,7 +286,9 @@ fn offer_followup_promotions(path: &str, project_root: &Path) -> Result<()> { marker ); if prompts::prompt_bool(&label, false)? { - promote::run(path, &fu.fu_id, None)?; + // premise_verified: false — close-time promotion surfaces the + // premise re-check reminder; the operator hasn't confirmed it here. + promote::run(path, &fu.fu_id, None, false)?; } } Ok(()) diff --git a/cli/src/commands/followups/mod.rs b/cli/src/commands/followups/mod.rs index 03b871aa..bd5cedae 100644 --- a/cli/src/commands/followups/mod.rs +++ b/cli/src/commands/followups/mod.rs @@ -5,7 +5,8 @@ //! and inspect, `drift` keeps the registry in sync with AILOGs (native //! replacement for the deprecated adopter-side bash script), `recount` //! reconciles the CLI-owned counters after a manual-triage session, -//! `promote` automates the FU → TDE elevation. See +//! `promote` automates the FU → TDE elevation, and `verify` re-checks an +//! entry's premise at execution time (AIDEC-2026-07-18-001). See //! `FOLLOW-UPS-BACKLOG-PATTERN.md` and `STRAYMARK.md §16`. pub mod drift; @@ -13,3 +14,4 @@ pub mod list; pub mod promote; pub mod recount; pub mod status; +pub mod verify; diff --git a/cli/src/commands/followups/promote.rs b/cli/src/commands/followups/promote.rs index d5db1617..1f993545 100644 --- a/cli/src/commands/followups/promote.rs +++ b/cli/src/commands/followups/promote.rs @@ -23,7 +23,7 @@ use std::path::Path; use crate::followups::{self, FuStatus}; use crate::utils; -pub fn run(path: &str, fu_id: &str, title: Option<&str>) -> Result<()> { +pub fn run(path: &str, fu_id: &str, title: Option<&str>, premise_verified: bool) -> Result<()> { let resolved = utils::resolve_project_root(path) .ok_or_else(|| anyhow!("StrayMark not installed. Run 'straymark init' first."))?; let project_root = &resolved.path; @@ -61,6 +61,12 @@ pub fn run(path: &str, fu_id: &str, title: Option<&str>) -> Result<()> { ); } + // ── 0. Surface the premise for a re-check at execution ── + // A follow-up is a dated, decaying hypothesis (AIDEC-2026-07-18-001). The + // cheap moment to re-test its premise is now — acting on it — not at + // capture. Advisory, never a gate: promotion proceeds either way. + print_premise_reminder(&entry, premise_verified); + // ── 1. Create the TDE document ── let tde_title = title.unwrap_or(&entry.description).to_string(); let (tde_id, tde_path) = create_tde(project_root, &straymark_dir, &tde_title, &entry)?; @@ -81,6 +87,20 @@ pub fn run(path: &str, fu_id: &str, title: Option<&str>) -> Result<()> { let entry3 = followups::find_entry(&reparsed, &entry.fu_id).unwrap().clone(); body = followups::set_entry_field(&body, &entry3, "Promoted to", &tde_id); + // Stamp Verified-at only when the operator confirmed the premise re-check. + let stamped_verified = if premise_verified { + let reparsed = followups::parse_registry_str( + ®istry_path, + &followups::assemble(®istry.frontmatter_raw, &body), + )?; + let entry4 = followups::find_entry(&reparsed, &entry.fu_id).unwrap().clone(); + let today = Local::now().format("%Y-%m-%d").to_string(); + body = followups::set_entry_field(&body, &entry4, "Verified-at", &today); + Some(today) + } else { + None + }; + let final_registry = followups::parse_registry_str( ®istry_path, &followups::assemble(®istry.frontmatter_raw, &body), @@ -100,6 +120,9 @@ pub fn run(path: &str, fu_id: &str, title: Option<&str>) -> Result<()> { " Registry updated: Status promoted, Destination/Promoted to → {} (counters recomputed).", tde_id ); + if let Some(date) = &stamped_verified { + println!(" Premise re-verification recorded: Verified-at → {}.", date); + } println!(); println!(" {}", "Next steps:".bold()); println!(" 1. Fill impact / effort / type and the body sections in the TDE."); @@ -112,6 +135,50 @@ pub fn run(path: &str, fu_id: &str, title: Option<&str>) -> Result<()> { Ok(()) } +/// Surface the entry's premise before promotion so the operator re-checks it at +/// the cheap moment — acting on the entry — rather than trusting a note that may +/// have been false at capture or gone stale since (AIDEC-2026-07-18-001). Prints +/// the `Premise` (falling back to `Notes`), then either confirms the recorded +/// re-verification or reminds the operator to run one. Never blocks promotion. +fn print_premise_reminder(entry: &followups::Entry, premise_verified: bool) { + let premise = entry + .premise + .as_deref() + .filter(|s| !s.is_empty()) + .or(entry.notes.as_deref().filter(|s| !s.is_empty())); + + println!(); + println!(" {}", "Premise re-check (this entry is a dated hypothesis):".bold()); + match premise { + Some(text) => println!(" {}", text), + None => println!( + " {}", + "(no premise or notes recorded — state the assumption this entry rests on)".dimmed() + ), + } + if premise_verified { + println!( + " {}", + "✓ You confirmed the premise still holds (--premise-verified).".green() + ); + } else { + println!( + " {}", + "Is this still true? Re-verify against the code before you build on it." + .yellow() + ); + println!( + " {}", + format!( + "If you have: `straymark followups promote {} --premise-verified` (or `followups verify {} --verified` first).", + entry.fu_id, entry.fu_id + ) + .dimmed() + ); + } + println!(); +} + /// Create the TDE document from the (localized) framework template. Returns /// `(tde_id, path)`. Mirrors the fill logic of `commands::new` for the TDE /// type, plus the `promoted_from_followup` traceability field. diff --git a/cli/src/commands/followups/status.rs b/cli/src/commands/followups/status.rs index bdd2afd1..88cc2a0f 100644 --- a/cli/src/commands/followups/status.rs +++ b/cli/src/commands/followups/status.rs @@ -213,6 +213,8 @@ fn print_entry_detail(registry: &Registry, id: &str) -> Result<()> { "Severity", entry.severity.map(|s| s.as_str()), ); + print_field("Premise", entry.premise.as_deref()); + print_field("Verified-at", entry.verified_at.as_deref()); print_field("Origin", entry.origin.as_deref()); print_field("Origin-class", entry.origin_class.as_deref()); print_field("Trigger", entry.trigger.as_deref()); @@ -234,10 +236,43 @@ fn print_entry_detail(registry: &Registry, id: &str) -> Result<()> { ); println!(); } + print_premise_nudge(entry); let _ = print_promote_hint(entry); Ok(()) } +/// Follow-up entries are *dated hypotheses* (AIDEC-2026-07-18-001): the premise +/// they rest on may have been false at capture, or gone stale since. Nudge the +/// operator to re-verify at execution — the cheap moment — before acting. Fires +/// for actionable entries whose premise has not been re-verified. +fn print_premise_nudge(entry: &Entry) { + if !matches!(entry.status, FuStatus::Open | FuStatus::InProgress) { + return; + } + if entry.verified_at.is_some() { + return; + } + let what = if entry.premise.is_some() { + "Its premise hasn't been re-verified since capture." + } else { + "It carries no explicit premise — state and re-check the assumption it rests on." + }; + println!( + " {} This is a dated hypothesis. {}", + "?".yellow().bold(), + what.dimmed() + ); + println!( + " {}", + format!( + "Re-verify against the code before you build on it: `straymark followups verify {}`.", + entry.fu_id + ) + .dimmed() + ); + println!(); +} + fn print_field(label: &str, value: Option<&str>) { match value { Some(v) if !v.is_empty() => { diff --git a/cli/src/commands/followups/verify.rs b/cli/src/commands/followups/verify.rs new file mode 100644 index 00000000..78bd14db --- /dev/null +++ b/cli/src/commands/followups/verify.rs @@ -0,0 +1,142 @@ +//! `straymark followups verify FU-NNN` — re-verify a follow-up's premise at +//! execution time and record it. +//! +//! A follow-up entry is a **dated, decaying hypothesis** (AIDEC-2026-07-18-001, +//! from Weft field report #365): its premise may have been false at capture or +//! gone stale since, and the only real bug is acting on one *without* re-testing +//! that premise. The registry is a speculative buffer — cheap capture is its +//! value — so verification belongs at the cheap moment (acting on the entry), +//! not at capture. +//! +//! This verb covers the common case: an entry acted on as a chore that never +//! promotes (the promote-time reminder in `promote.rs` covers the graduation +//! path). It: +//! +//! - surfaces the entry's `Premise` (falling back to `Notes`); +//! - optionally records/updates the premise (`--premise "..."`); +//! - stamps `Verified-at: ` when the operator confirms the re-check +//! (`--verified`). +//! +//! Human judgment stays out of the CLI (as with `promote`): the command puts the +//! premise in front of the operator and records that the check happened — it +//! never decides truth itself. + +use anyhow::{anyhow, bail, Result}; +use chrono::Local; +use colored::Colorize; + +use crate::followups; +use crate::utils; + +pub fn run( + path: &str, + fu_id: &str, + premise: Option<&str>, + verified: bool, + at: Option<&str>, +) -> Result<()> { + let resolved = utils::resolve_project_root(path) + .ok_or_else(|| anyhow!("StrayMark not installed. Run 'straymark init' first."))?; + let project_root = &resolved.path; + + let registry_path = followups::registry_path(project_root); + if !registry_path.exists() { + bail!( + "No follow-ups registry at {}.\n hint: see STRAYMARK.md §16 for the adoption walkthrough.", + registry_path.display() + ); + } + let registry = followups::parse_registry(®istry_path)?; + let entry = followups::find_entry(®istry, fu_id) + .ok_or_else(|| { + anyhow!( + "Entry {} not found in the registry.\n hint: run `straymark followups list` to see entries.", + fu_id + ) + })? + .clone(); + + // ── Surface the premise (the assumption to re-check) ── + let effective_premise = premise + .filter(|s| !s.trim().is_empty()) + .map(|s| s.to_string()) + .or_else(|| entry.premise.clone()) + .or_else(|| entry.notes.clone()); + + println!(); + println!(" {} — {}", entry.fu_id.bold().cyan(), entry.description.bold()); + println!(); + println!(" {}", "Premise (re-check against the code):".bold()); + match &effective_premise { + Some(text) if !text.trim().is_empty() => println!(" {}", text), + _ => println!( + " {}", + "(none recorded — pass --premise \"\")".dimmed() + ), + } + println!(); + + // ── Write-back: record premise and/or stamp verification ── + let mut body = registry.body.clone(); + let mut wrote = false; + + if let Some(new_premise) = premise.filter(|s| !s.trim().is_empty()) { + body = followups::set_entry_field(&body, &entry, "Premise", new_premise.trim()); + wrote = true; + } + + let stamped = if verified { + // Re-parse before the second edit so the span is current. + let entry_now = if wrote { + let reparsed = followups::parse_registry_str( + ®istry_path, + &followups::assemble(®istry.frontmatter_raw, &body), + )?; + followups::find_entry(&reparsed, &entry.fu_id).unwrap().clone() + } else { + entry.clone() + }; + let date = at + .map(|s| s.to_string()) + .unwrap_or_else(|| Local::now().format("%Y-%m-%d").to_string()); + body = followups::set_entry_field(&body, &entry_now, "Verified-at", &date); + wrote = true; + Some(date) + } else { + None + }; + + if wrote { + // Recompute the CLI-owned counters + v0→v1 upgrade, like every write + // command — even though status is unchanged, this keeps the registry + // canonical and idempotent. + let final_registry = followups::parse_registry_str( + ®istry_path, + &followups::assemble(®istry.frontmatter_raw, &body), + )?; + let counters = followups::compute_counters(&final_registry); + let fm = followups::fm_apply_counters_and_v1(®istry.frontmatter_raw, &counters); + std::fs::write(®istry_path, followups::assemble(&fm, &body))?; + + if premise.filter(|s| !s.trim().is_empty()).is_some() { + utils::success(&format!("{} premise recorded.", entry.fu_id)); + } + if let Some(date) = &stamped { + utils::success(&format!("{} verified — Verified-at → {}.", entry.fu_id, date)); + } + println!(); + } else { + // Read-only surfacing: nudge toward recording the re-check. + println!( + " {}", + format!( + "When you've re-checked it: `straymark followups verify {} --verified` (add `--premise \"...\"` to record the assumption).", + entry.fu_id + ) + .dimmed() + ); + println!(); + } + + Ok(()) +} diff --git a/cli/src/followups.rs b/cli/src/followups.rs index f7f6012d..b070c7f5 100644 --- a/cli/src/followups.rs +++ b/cli/src/followups.rs @@ -141,6 +141,15 @@ pub struct Entry { pub labels: Vec, pub notes: Option, pub promoted_to: Option, + /// The load-bearing assumption the entry rests on, stated so it can be + /// re-checked in seconds at execution (AIDEC-2026-07-18-001). Optional; an + /// entry is a *dated hypothesis*, and this is the hypothesis to re-test + /// before acting. Absent on entries authored before the field existed. + pub premise: Option, + /// Date the `premise` was last re-verified against reality, stamped by + /// `followups verify`/`promote --premise-verified`. Absent = never + /// re-checked since capture (the default, honest state). + pub verified_at: Option, /// Byte offset of the `### ` heading line start, into `Registry::body`. pub span_start: usize, /// Byte offset one past the entry's last byte (start of the next heading @@ -397,6 +406,8 @@ fn parse_entries( labels: Vec::new(), notes: None, promoted_to: None, + premise: None, + verified_at: None, span_start: abs_start, span_end: abs_end, }; @@ -433,6 +444,10 @@ fn parse_entries( "promoted to" | "promoted-to" | "promoted_to" => { entry.promoted_to = some_nonempty(value) } + "premise" => entry.premise = some_nonempty(value), + "verified-at" | "verified at" | "verified_at" => { + entry.verified_at = some_nonempty(value) + } _ => {} // unknown field — lenient, preserved in the raw body } } @@ -1379,6 +1394,28 @@ fully_extracted_ailogs: [] assert_eq!(e.destination.as_deref(), Some("mini-charter")); } + #[test] + fn parses_and_sets_premise_and_verified_at() { + // Parse the optional #365-Part-1 fields (lenient aliases too). + let content = "---\nschema_version: v1\nfully_extracted_ailogs: []\n---\n\n\ + ## Bucket: ready\n\n### FU-020 — Loro parity gate\n\ + - **Status**: open\n\ + - **Premise**: yrs has an independent reference (Yjs)\n\ + - **Verified at**: 2026-07-18\n"; + let reg = parse(content); + let e = find_entry(®, "20").unwrap(); + assert_eq!(e.premise.as_deref(), Some("yrs has an independent reference (Yjs)")); + assert_eq!(e.verified_at.as_deref(), Some("2026-07-18")); + + // set_entry_field round-trips both (insert-if-absent + replace). + let e = e.clone(); + let body2 = set_entry_field(®.body, &e, "Premise", "the reference cannot exist (WASM of same core)"); + let reg2 = parse(&assemble(®.frontmatter_raw, &body2)); + let e2 = find_entry(®2, "20").unwrap(); + assert_eq!(e2.premise.as_deref(), Some("the reference cannot exist (WASM of same core)")); + assert_eq!(e2.verified_at.as_deref(), Some("2026-07-18")); // untouched + } + #[test] fn malformed_fu_heading_is_warning_not_error() { let content = r#"--- diff --git a/cli/src/main.rs b/cli/src/main.rs index 7c458544..08a7352c 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -435,6 +435,34 @@ enum FollowupsCommands { /// TDE title override (default: the FU description) #[arg(long)] title: Option, + /// Confirm the entry's premise was re-verified against the code before + /// promoting. Stamps `Verified-at: `. A follow-up is a dated + /// hypothesis (AIDEC-2026-07-18-001) — re-check its premise at + /// execution, not capture. Advisory: promotion proceeds either way. + #[arg(long = "premise-verified")] + premise_verified: bool, + /// Project directory (default: current directory) + #[arg(long = "path", default_value = ".")] + path: String, + }, + /// Re-verify a follow-up's premise at execution time and record it. A + /// follow-up is a dated, decaying hypothesis (AIDEC-2026-07-18-001): the + /// only real bug is acting on one without re-testing its premise. Surfaces + /// the premise, optionally records/updates it, and stamps `Verified-at`. + Verify { + /// Entry identifier (FU-NNN or just NNN) + fu_id: String, + /// Record or update the entry's premise (the load-bearing assumption + /// to re-check). When omitted, the existing premise is surfaced. + #[arg(long)] + premise: Option, + /// Stamp `Verified-at: `, confirming the premise was re-checked + /// against the code. Without it, the command only surfaces the premise. + #[arg(long)] + verified: bool, + /// Verification date (default: today, format YYYY-MM-DD) + #[arg(long)] + at: Option, /// Project directory (default: current directory) #[arg(long = "path", default_value = ".")] path: String, @@ -945,9 +973,30 @@ fn main() { path, } => commands::followups::drift::run(&path, apply, scan_all, range.as_deref()), FollowupsCommands::Recount { path } => commands::followups::recount::run(&path), - FollowupsCommands::Promote { fu_id, title, path } => { - commands::followups::promote::run(&path, &fu_id, title.as_deref()) - } + FollowupsCommands::Promote { + fu_id, + title, + premise_verified, + path, + } => commands::followups::promote::run( + &path, + &fu_id, + title.as_deref(), + premise_verified, + ), + FollowupsCommands::Verify { + fu_id, + premise, + verified, + at, + path, + } => commands::followups::verify::run( + &path, + &fu_id, + premise.as_deref(), + verified, + at.as_deref(), + ), }, Commands::Architecture { command } => match command { ArchitectureCommands::Generate { path, force, out } => { diff --git a/cli/tests/followups_test.rs b/cli/tests/followups_test.rs index 9773d761..2532c5b5 100644 --- a/cli/tests/followups_test.rs +++ b/cli/tests/followups_test.rs @@ -578,6 +578,127 @@ fn promote_unknown_entry_fails_with_hint() { .stderr(predicate::str::contains("not found")); } +#[test] +fn promote_surfaces_premise_reminder_and_does_not_stamp_without_flag() { + let tmp = TempDir::new().unwrap(); + let straymark = scaffold(tmp.path()); + write_registry(&straymark, V1_REGISTRY); + std::fs::write(straymark.join("templates/TEMPLATE-TDE.md"), TDE_TEMPLATE).unwrap(); + + cmd() + .args(["followups", "promote", "FU-010", "--path", tmp.path().to_str().unwrap()]) + .assert() + .success() + .stdout(predicate::str::contains("Premise re-check")) + .stdout(predicate::str::contains("Is this still true?")); + + // No --premise-verified → no Verified-at stamp. + let updated = std::fs::read_to_string(straymark.join("follow-ups-backlog.md")).unwrap(); + assert!(!updated.contains("- **Verified-at**")); +} + +#[test] +fn promote_with_premise_verified_stamps_verified_at() { + let tmp = TempDir::new().unwrap(); + let straymark = scaffold(tmp.path()); + write_registry(&straymark, V1_REGISTRY); + std::fs::write(straymark.join("templates/TEMPLATE-TDE.md"), TDE_TEMPLATE).unwrap(); + + cmd() + .args([ + "followups", "promote", "FU-010", "--premise-verified", + "--path", tmp.path().to_str().unwrap(), + ]) + .assert() + .success() + .stdout(predicate::str::contains("re-verification recorded")); + + let updated = std::fs::read_to_string(straymark.join("follow-ups-backlog.md")).unwrap(); + let entry_block = &updated[updated.find("### FU-010").unwrap()..updated.find("### FU-011").unwrap()]; + assert!(entry_block.contains("- **Status**: promoted")); + assert!(entry_block.contains("- **Verified-at**:")); +} + +// ───────────────────────────── verify ───────────────────────────── + +#[test] +fn verify_records_premise_and_stamps_verified_at() { + let tmp = TempDir::new().unwrap(); + let straymark = scaffold(tmp.path()); + write_registry(&straymark, V1_REGISTRY); + + cmd() + .args([ + "followups", "verify", "FU-011", + "--premise", "the rollout runbook template already exists", + "--verified", "--at", "2026-07-18", + "--path", tmp.path().to_str().unwrap(), + ]) + .assert() + .success() + .stdout(predicate::str::contains("premise recorded")) + .stdout(predicate::str::contains("Verified-at → 2026-07-18")); + + let updated = std::fs::read_to_string(straymark.join("follow-ups-backlog.md")).unwrap(); + let entry_block = &updated[updated.find("### FU-011").unwrap()..]; + assert!(entry_block.contains("- **Premise**: the rollout runbook template already exists")); + assert!(entry_block.contains("- **Verified-at**: 2026-07-18")); + // Verify does not change status. + assert!(entry_block.contains("- **Status**: open")); +} + +#[test] +fn verify_read_only_surfacing_without_flags_does_not_write() { + let tmp = TempDir::new().unwrap(); + let straymark = scaffold(tmp.path()); + write_registry(&straymark, V1_REGISTRY); + let before = std::fs::read_to_string(straymark.join("follow-ups-backlog.md")).unwrap(); + + cmd() + .args(["followups", "verify", "FU-010", "--path", tmp.path().to_str().unwrap()]) + .assert() + .success() + .stdout(predicate::str::contains("Premise")) + .stdout(predicate::str::contains("re-checked")); + + // Read-only: registry untouched. + let after = std::fs::read_to_string(straymark.join("follow-ups-backlog.md")).unwrap(); + assert_eq!(before, after); +} + +#[test] +fn verify_unknown_entry_fails_with_hint() { + let tmp = TempDir::new().unwrap(); + let straymark = scaffold(tmp.path()); + write_registry(&straymark, V1_REGISTRY); + + cmd() + .args(["followups", "verify", "FU-404", "--path", tmp.path().to_str().unwrap()]) + .assert() + .failure() + .stderr(predicate::str::contains("not found")); +} + +#[test] +fn status_detail_shows_premise_and_nudges_when_unverified() { + let tmp = TempDir::new().unwrap(); + let straymark = scaffold(tmp.path()); + // Add a premise to FU-011 and re-check the nudge fires (no Verified-at). + let reg = V1_REGISTRY.replace( + "### FU-011 — Document the rollout runbook\n- **Origin**: AILOG-2026-06-01-002 §Follow-ups", + "### FU-011 — Document the rollout runbook\n- **Origin**: AILOG-2026-06-01-002 §Follow-ups\n- **Premise**: the runbook does not exist yet", + ); + write_registry(&straymark, ®); + + cmd() + .args(["followups", "status", "FU-011", "--path", tmp.path().to_str().unwrap()]) + .assert() + .success() + .stdout(predicate::str::contains("the runbook does not exist yet")) + .stdout(predicate::str::contains("dated hypothesis")) + .stdout(predicate::str::contains("Re-verify against the code")); +} + // ───────────────────────────── status command block ───────────────────────────── #[test] diff --git a/dist/.straymark/00-governance/AGENT-RULES.md b/dist/.straymark/00-governance/AGENT-RULES.md index a9c0164b..1867fe1a 100644 --- a/dist/.straymark/00-governance/AGENT-RULES.md +++ b/dist/.straymark/00-governance/AGENT-RULES.md @@ -385,7 +385,7 @@ These are heuristics, not rigid rules — you are close to the context, refine t ## 13. Follow-ups Backlog (registry maintenance) -When the project maintains the central follow-ups registry (`.straymark/follow-ups-backlog.md` — see [`FOLLOW-UPS-BACKLOG-PATTERN.md`](FOLLOW-UPS-BACKLOG-PATTERN.md) and `STRAYMARK.md §16`), the agent is its **primary maintainer**. Three directives: +When the project maintains the central follow-ups registry (`.straymark/follow-ups-backlog.md` — see [`FOLLOW-UPS-BACKLOG-PATTERN.md`](FOLLOW-UPS-BACKLOG-PATTERN.md) and `STRAYMARK.md §16`), the agent is its **primary maintainer**. Four directives: ### Session start @@ -395,6 +395,10 @@ Glance at `.straymark/follow-ups-backlog.md` (or run `straymark followups status Created or modified any AILOG with `## Follow-ups` or `R (new, not in Charter)` entries? → run `straymark followups drift --apply` so the registry extension rides **the same commit** as the AILOG. Entries the AILOG text already marks as resolved in-Charter are extracted as `suspected-closed` automatically — do not delete them; the operator confirms at the next triage. +### Before acting on an entry (execution) + +A registry entry is a **dated, decaying hypothesis, not an instruction** (AIDEC-2026-07-18-001, from #365): its premise may have been false at capture or gone stale since. **Re-verify the premise at execution, not at capture** — the moment you promote or act on an entry you are already in that code, so the check (a `grep`, a file read, a traced call chain) is seconds. Do it *before* you build on the entry: a plausible-but-false premise implemented is a wasted Charter. Record the re-check with `straymark followups verify FU-NNN --verified` (or `followups promote FU-NNN --premise-verified`), which stamps `Verified-at`. Do **not** verify at capture time — the backlog is a speculative buffer whose value is cheap capture; front-loading verification would make the rational move "stop writing follow-ups." + ### Post-Charter close Review the registry entries the just-closed Charter resolved: @@ -414,4 +418,4 @@ When a project accumulates a high volume of AILOGs across multiple Charters and --- -*StrayMark fw-4.35.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.36.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/dist/.straymark/00-governance/C4-DIAGRAM-GUIDE.md b/dist/.straymark/00-governance/C4-DIAGRAM-GUIDE.md index 2fb5f74c..eea9e916 100644 --- a/dist/.straymark/00-governance/C4-DIAGRAM-GUIDE.md +++ b/dist/.straymark/00-governance/C4-DIAGRAM-GUIDE.md @@ -234,4 +234,4 @@ Use a Level 1 (Context) diagram to illustrate: --- -*StrayMark fw-4.35.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.36.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/dist/.straymark/00-governance/DOCUMENTATION-POLICY.md b/dist/.straymark/00-governance/DOCUMENTATION-POLICY.md index 54049aeb..3f1be82d 100644 --- a/dist/.straymark/00-governance/DOCUMENTATION-POLICY.md +++ b/dist/.straymark/00-governance/DOCUMENTATION-POLICY.md @@ -319,4 +319,4 @@ See also [ADR-2025-01-20-001] for architectural context. --- -*StrayMark fw-4.35.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.36.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/dist/.straymark/00-governance/FOLLOW-UPS-BACKLOG-PATTERN.md b/dist/.straymark/00-governance/FOLLOW-UPS-BACKLOG-PATTERN.md index 7693ff43..f798bb63 100644 --- a/dist/.straymark/00-governance/FOLLOW-UPS-BACKLOG-PATTERN.md +++ b/dist/.straymark/00-governance/FOLLOW-UPS-BACKLOG-PATTERN.md @@ -39,6 +39,27 @@ Below that volume, the per-AILOG convention alone is sufficient — adopting thi Empirical lesson from the reference adopter (issue #214, N=91 entries): the backlog is more than a list of deferred chores. Follow-ups originate not only from planning (ex-ante) but from **execution reality** — test runs, telemetry readings, staging incidents, bugs observed in real (non-simulated) environments — and they feed planning back: they become chores, mini-charters, or even reshape Charters that were already planned. The registry is the **ex-post counterpart of SpecKit**: SpecKit feeds planning from intent; the backlog feeds it from execution. The v1 dimensions (`Origin-class`, `Severity`, `Labels`, the `Destination` vocabulary) exist to make that planning loop queryable. +It *feeds* planning — but do not read it *as* a plan. Each entry is a bet to re-check when drawn, not a committed task (see "Epistemic status" next). + +--- + +## Epistemic status — entries are dated hypotheses + +*(AIDEC-2026-07-18-001, from Weft field report #365.)* + +A follow-up backlog is a **speculative buffer**. Its value is *cheap capture* so a signal is not lost while you finish something else. That cheapness is the whole point — and it dictates how an entry should be read and when its premise should be checked. + +**An entry is a dated, decaying hypothesis, not an instruction.** It records what looked true and worth doing at capture time — a note jotted with attention on other work. That note can be wrong the moment it is written: a comment believed, an analogy over-trusted, a mental model already going stale. (In the founding field report, three genuine follow-ups each rested on a premise that was false *at write time* and cost a ~30-second check to falsify months later.) So: + +- **An under-verified entry is not an authoring defect** — it is the *expected* epistemic status of anything in a speculative buffer. Demanding verification at capture would defeat the buffer's purpose; the rational response would be to stop writing follow-ups and lose the signal. +- **The only real bug is executing an entry without re-testing its premise.** Read as instructions, false premises become wasted Charters. Read as dated hypotheses to re-check at execution, they become cheap bets. + +**Discipline — write cheaply at capture; re-verify the premise when you promote/act:** + +- At capture, jot the follow-up freely. Optionally state its **`Premise`** — the load-bearing assumption it rests on — so the later re-check has a concrete target. +- At execution (you are about to build on it), **re-verify the premise against the code first** — a `grep`, a file read, a traced call chain. You are already inside that subsystem, so the check is seconds. Record it with `straymark followups verify FU-NNN --verified` (or `followups promote FU-NNN --premise-verified`), which stamps **`Verified-at`**. +- `Verified-at` absent = never re-checked since capture (the honest default). Its presence is provenance that the hypothesis was tested against reality before you spent effort on it. + --- ## Shape @@ -113,6 +134,8 @@ Each entry inside a bucket follows this shape (v1 fields marked; all of them opt - **Destination**: chore | mini-charter | charter-replanning | operations | | - **Cost**: - **Labels**: (v1, optional) +- **Premise**: (v1, optional) +- **Verified-at**: (v1, optional) - **Notes**: - **Promoted to**: ``` @@ -125,6 +148,7 @@ Each entry inside a bucket follows this shape (v1 fields marked; all of them opt - **`Severity`** — `blocking` marks reliability-class issues that must land before a production cutover. Canonicalizes the `PROD-BLOCKER` prose convention that emerged in the reference adopter's `Notes` field (Signal 3). Orthogonal to the bucket: a `charter-triggered` entry can be `blocking`. - **`Labels`** — free tags for grouping entries into planned Charters / mini-charters / chores during triage. Queryable via `straymark followups list --label `. - **`Destination` vocabulary** — formalizes where the work lands when triggered: `chore`, `mini-charter`, `charter-replanning` (the entry reshapes an already-planned Charter rather than adding a task to it), `operations`, a specific Charter id, or a TDE id. Free-form values remain accepted (lenient parsing). +- **`Premise` / `Verified-at`** *(AIDEC-2026-07-18-001)* — the load-bearing assumption an entry rests on, and the date it was last re-checked against the code. An entry is a *dated hypothesis* (see "Epistemic status"); these fields give the re-verify-at-execution discipline a concrete target and an audit stamp. Both optional; `Verified-at` absent = never re-checked since capture. ### Status vocabulary @@ -241,9 +265,12 @@ straymark followups status # registry pulse: counters (recomputed straymark followups status FU-NNN # detail view of one entry straymark followups drift [--apply|--scan-all] # drift detection (see above) straymark followups recount # recompute the CLI-owned counters after a manual-triage session (cli-3.20.0+) -straymark followups promote FU-NNN # automate FU → TDE promotion (see above) +straymark followups promote FU-NNN [--premise-verified] # automate FU → TDE promotion; surfaces the premise re-check, stamps Verified-at with the flag (cli-3.37.0+) +straymark followups verify FU-NNN [--premise "..."] [--verified] [--at DATE] # re-verify a dated hypothesis at execution: surface/record the premise, stamp Verified-at (cli-3.37.0+) ``` +`verify` and `promote --premise-verified` are the execution-time affordances of the "Epistemic status" discipline: they put the premise in front of the operator at the moment of spending and record that the re-check happened. Human judgment stays out of the CLI — it surfaces and stamps, it never decides truth. + The registry also appears as a synthetic **Follow-ups** group in the `straymark explore` TUI (sub-nodes per bucket) and as a counts block in `straymark status`. --- @@ -316,4 +343,4 @@ Contributed via [issue #111](https://github.com/StrangeDaysTech/straymark/issues --- -*StrayMark fw-4.34.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.36.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/dist/.straymark/00-governance/QUICK-REFERENCE.md b/dist/.straymark/00-governance/QUICK-REFERENCE.md index 383643e4..d0ea6ea9 100644 --- a/dist/.straymark/00-governance/QUICK-REFERENCE.md +++ b/dist/.straymark/00-governance/QUICK-REFERENCE.md @@ -263,4 +263,4 @@ Mark `review_required: true` when: --- -*StrayMark fw-4.35.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.36.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/dist/.straymark/00-governance/i18n/es/AGENT-RULES.md b/dist/.straymark/00-governance/i18n/es/AGENT-RULES.md index fc896bbd..4d3d8ae3 100644 --- a/dist/.straymark/00-governance/i18n/es/AGENT-RULES.md +++ b/dist/.straymark/00-governance/i18n/es/AGENT-RULES.md @@ -385,7 +385,7 @@ Son heurísticas, no reglas rígidas — estás cerca del contexto, afínalas co ## 13. Follow-ups Backlog (mantenimiento del registry) -Cuando el proyecto mantiene el registry central de follow-ups (`.straymark/follow-ups-backlog.md` — ver [`FOLLOW-UPS-BACKLOG-PATTERN.md`](FOLLOW-UPS-BACKLOG-PATTERN.md) y `STRAYMARK.md §16`), el agente es su **mantenedor primario**. Tres directivas: +Cuando el proyecto mantiene el registry central de follow-ups (`.straymark/follow-ups-backlog.md` — ver [`FOLLOW-UPS-BACKLOG-PATTERN.md`](FOLLOW-UPS-BACKLOG-PATTERN.md) y `STRAYMARK.md §16`), el agente es su **mantenedor primario**. Cuatro directivas: ### Session start @@ -395,6 +395,10 @@ Echa un vistazo a `.straymark/follow-ups-backlog.md` (o ejecuta `straymark follo ¿Creaste o modificaste algún AILOG con entradas `## Follow-ups` o `R (new, not in Charter)`? → ejecuta `straymark followups drift --apply` para que la extensión del registry viaje en **el mismo commit** que el AILOG. Las entradas que el texto del AILOG ya marca como resueltas in-Charter se extraen como `suspected-closed` automáticamente — no las elimines; el operador las confirma en el siguiente triage. +### Antes de actuar sobre una entrada (ejecución) + +Una entrada del registry es una **hipótesis fechada y decadente, no una instrucción** (AIDEC-2026-07-18-001, de #365): su premisa pudo ser falsa en la captura o haberse vuelto obsoleta desde entonces. **Re-verifica la premisa en la ejecución, no en la captura** — en el momento en que promueves o actúas sobre una entrada ya estás dentro de ese código, así que el chequeo (un `grep`, la lectura de un archivo, una cadena de llamadas trazada) son segundos. Hazlo *antes* de construir sobre la entrada: una premisa plausible-pero-falsa implementada es un Charter desperdiciado. Registra el re-chequeo con `straymark followups verify FU-NNN --verified` (o `followups promote FU-NNN --premise-verified`), que sella `Verified-at`. **No** verifiques en la captura — el backlog es un buffer especulativo cuyo valor es la captura barata; adelantar la verificación haría que la jugada racional fuera "dejar de escribir follow-ups". + ### Post-Charter close Revisa las entradas del registry que el Charter recién cerrado resolvió: @@ -414,4 +418,4 @@ Cuando un proyecto acumula un volumen alto de AILOGs a lo largo de múltiples Ch --- -*StrayMark fw-4.35.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.36.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/dist/.straymark/00-governance/i18n/es/C4-DIAGRAM-GUIDE.md b/dist/.straymark/00-governance/i18n/es/C4-DIAGRAM-GUIDE.md index ea0e84ed..6fcbefd9 100644 --- a/dist/.straymark/00-governance/i18n/es/C4-DIAGRAM-GUIDE.md +++ b/dist/.straymark/00-governance/i18n/es/C4-DIAGRAM-GUIDE.md @@ -234,4 +234,4 @@ Usar un diagrama de Nivel 1 (Contexto) para ilustrar: --- -*StrayMark fw-4.35.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.36.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/dist/.straymark/00-governance/i18n/es/DOCUMENTATION-POLICY.md b/dist/.straymark/00-governance/i18n/es/DOCUMENTATION-POLICY.md index a103c7ec..6bd6d501 100644 --- a/dist/.straymark/00-governance/i18n/es/DOCUMENTATION-POLICY.md +++ b/dist/.straymark/00-governance/i18n/es/DOCUMENTATION-POLICY.md @@ -312,4 +312,4 @@ Ver también [ADR-2025-01-20-001] para contexto arquitectónico. --- -*StrayMark fw-4.35.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.36.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/dist/.straymark/00-governance/i18n/es/FOLLOW-UPS-BACKLOG-PATTERN.md b/dist/.straymark/00-governance/i18n/es/FOLLOW-UPS-BACKLOG-PATTERN.md index 5dda112c..7e88bcd0 100644 --- a/dist/.straymark/00-governance/i18n/es/FOLLOW-UPS-BACKLOG-PATTERN.md +++ b/dist/.straymark/00-governance/i18n/es/FOLLOW-UPS-BACKLOG-PATTERN.md @@ -39,6 +39,27 @@ Por debajo de ese volumen, la convención per-AILOG por sí sola es suficiente Lección empírica del adopter de referencia (issue #214, N=91 entradas): el backlog es más que una lista de chores diferidos. Los follow-ups se originan no solo de la planificación (ex-ante) sino de la **realidad de ejecución** — corridas de tests, lecturas de telemetría, incidentes de staging, bugs observados en entornos reales (no simulados) — y retroalimentan la planificación: se vuelven chores, mini-charters, o incluso reconfiguran Charters que ya estaban planeados. El registry es el **contraparte ex-post de SpecKit**: SpecKit alimenta la planificación desde la intención; el backlog la alimenta desde la ejecución. Las dimensiones de v1 (`Origin-class`, `Severity`, `Labels`, el vocabulario de `Destination`) existen para hacer ese bucle de planificación consultable. +*Alimenta* la planificación — pero no lo leas *como* un plan. Cada entrada es una apuesta a re-chequear cuando se toma, no una tarea comprometida (ver "Estatus epistémico" a continuación). + +--- + +## Estatus epistémico — las entradas son hipótesis fechadas + +*(AIDEC-2026-07-18-001, del reporte de campo de Weft #365.)* + +Un backlog de follow-ups es un **buffer especulativo**. Su valor es la *captura barata* para no perder una señal mientras terminas otra cosa. Esa baratura es justamente el punto — y dicta cómo debe leerse una entrada y cuándo debe verificarse su premisa. + +**Una entrada es una hipótesis fechada y decadente, no una instrucción.** Registra lo que parecía cierto y valía la pena hacer en el momento de captura — una nota anotada con la atención puesta en otro trabajo. Esa nota puede ser falsa en el instante en que se escribe: un comentario creído, una analogía sobre-confiada, un modelo mental ya volviéndose obsoleto. (En el reporte fundacional, tres follow-ups genuinos descansaban cada uno sobre una premisa que era falsa *al momento de escribirse* y costó un chequeo de ~30 segundos falsificar meses después.) Por lo tanto: + +- **Una entrada sub-verificada no es un defecto de autoría** — es el estatus epistémico *esperado* de cualquier cosa en un buffer especulativo. Exigir verificación en la captura anularía el propósito del buffer; la respuesta racional sería dejar de escribir follow-ups y perder la señal. +- **El único bug real es ejecutar una entrada sin re-testear su premisa.** Leídas como instrucciones, las premisas falsas se vuelven Charters desperdiciados. Leídas como hipótesis fechadas a re-chequear en la ejecución, se vuelven apuestas baratas. + +**Disciplina — escribe barato en la captura; re-verifica la premisa cuando promuevas/actúes:** + +- En la captura, anota el follow-up libremente. Opcionalmente declara su **`Premise`** — la suposición que lo sostiene — para que el re-chequeo posterior tenga un blanco concreto. +- En la ejecución (estás por construir sobre ella), **re-verifica la premisa contra el código primero** — un `grep`, la lectura de un archivo, una cadena de llamadas trazada. Ya estás dentro de ese subsistema, así que el chequeo son segundos. Regístralo con `straymark followups verify FU-NNN --verified` (o `followups promote FU-NNN --premise-verified`), que sella **`Verified-at`**. +- `Verified-at` ausente = nunca re-chequeada desde la captura (el default honesto). Su presencia es la procedencia de que la hipótesis se probó contra la realidad antes de gastar esfuerzo en ella. + --- ## Forma @@ -113,6 +134,8 @@ Cada entrada dentro de un bucket sigue esta forma (campos v1 marcados; todos opc - **Destination**: chore | mini-charter | charter-replanning | operations | | - **Cost**: - **Labels**: (v1, opcional) +- **Premise**: (v1, opcional) +- **Verified-at**: (v1, opcional) - **Notes**: - **Promoted to**: ``` @@ -125,6 +148,7 @@ Cada entrada dentro de un bucket sigue esta forma (campos v1 marcados; todos opc - **`Severity`** — `blocking` marca issues de clase fiabilidad que deben aterrizar antes de un cutover a producción. Canonicaliza la convención en prosa `PROD-BLOCKER` que emergió en el campo `Notes` del adopter de referencia (Señal 3). Ortogonal al bucket: una entrada `charter-triggered` puede ser `blocking`. - **`Labels`** — tags libres para agrupar entradas en Charters / mini-charters / chores planeados durante el triage. Consultable vía `straymark followups list --label `. - **Vocabulario de `Destination`** — formaliza dónde aterriza el trabajo cuando se dispara: `chore`, `mini-charter`, `charter-replanning` (la entrada reconfigura un Charter ya planeado en vez de agregarle una tarea), `operations`, un id de Charter específico, o un id de TDE. Los valores free-form siguen siendo aceptados (parsing tolerante). +- **`Premise` / `Verified-at`** *(AIDEC-2026-07-18-001)* — la suposición que sostiene una entrada, y la fecha en que se re-chequeó por última vez contra el código. Una entrada es una *hipótesis fechada* (ver "Estatus epistémico"); estos campos le dan a la disciplina de re-verificar-en-ejecución un blanco concreto y un sello de auditoría. Ambos opcionales; `Verified-at` ausente = nunca re-chequeada desde la captura. ### Vocabulario de status @@ -241,9 +265,12 @@ straymark followups status # pulso del registry: contadores (reca straymark followups status FU-NNN # vista de detalle de una entrada straymark followups drift [--apply|--scan-all] # detección de drift (ver arriba) straymark followups recount # recalcula los contadores CLI-owned tras una sesión de triage manual (cli-3.20.0+) -straymark followups promote FU-NNN # automatiza la promoción FU → TDE (ver arriba) +straymark followups promote FU-NNN [--premise-verified] # automatiza la promoción FU → TDE; superficie el re-chequeo de la premisa, sella Verified-at con el flag (cli-3.37.0+) +straymark followups verify FU-NNN [--premise "..."] [--verified] [--at FECHA] # re-verifica una hipótesis fechada en la ejecución: superficie/registra la premisa, sella Verified-at (cli-3.37.0+) ``` +`verify` y `promote --premise-verified` son las afordancias en tiempo de ejecución de la disciplina de "Estatus epistémico": ponen la premisa frente al operador en el momento del gasto y registran que el re-chequeo ocurrió. El juicio humano queda fuera del CLI — superficie y sella, nunca decide la verdad. + El registry también aparece como un grupo sintético **Follow-ups** en la TUI de `straymark explore` (sub-nodos por bucket) y como un bloque de conteos en `straymark status`. --- @@ -316,4 +343,4 @@ Contribuido vía [issue #111](https://github.com/StrangeDaysTech/straymark/issue --- -*StrayMark fw-4.34.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.36.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/dist/.straymark/00-governance/i18n/es/QUICK-REFERENCE.md b/dist/.straymark/00-governance/i18n/es/QUICK-REFERENCE.md index c447f0c7..f1cf9644 100644 --- a/dist/.straymark/00-governance/i18n/es/QUICK-REFERENCE.md +++ b/dist/.straymark/00-governance/i18n/es/QUICK-REFERENCE.md @@ -235,4 +235,4 @@ Marcar `review_required: true` cuando: --- -*StrayMark fw-4.35.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.36.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/dist/.straymark/00-governance/i18n/zh-CN/AGENT-RULES.md b/dist/.straymark/00-governance/i18n/zh-CN/AGENT-RULES.md index 53b9c049..685c25b5 100644 --- a/dist/.straymark/00-governance/i18n/zh-CN/AGENT-RULES.md +++ b/dist/.straymark/00-governance/i18n/zh-CN/AGENT-RULES.md @@ -380,7 +380,7 @@ confidence: high | medium | low ## 13. Follow-ups Backlog(注册表维护) -当项目维护中央 follow-ups 注册表(`.straymark/follow-ups-backlog.md` —— 见 [`FOLLOW-UPS-BACKLOG-PATTERN.md`](FOLLOW-UPS-BACKLOG-PATTERN.md) 和 `STRAYMARK.md §16`)时,代理是它的**主要维护者**。三条指令: +当项目维护中央 follow-ups 注册表(`.straymark/follow-ups-backlog.md` —— 见 [`FOLLOW-UPS-BACKLOG-PATTERN.md`](FOLLOW-UPS-BACKLOG-PATTERN.md) 和 `STRAYMARK.md §16`)时,代理是它的**主要维护者**。四条指令: ### 会话开始 @@ -390,6 +390,10 @@ confidence: high | medium | low 创建或修改了任何带有 `## Follow-ups` 或 `R (new, not in Charter)` 条目的 AILOG 吗? → 运行 `straymark followups drift --apply`,使注册表扩展与 AILOG 搭乘**同一个 commit**。AILOG 文本已标记为在 Charter 内解决的条目会被自动提取为 `suspected-closed` —— 不要删除它们;操作员在下一次 triage 时确认。 +### 在对一个条目采取行动之前(执行时) + +一个注册表条目是一个**有日期、会衰减的假设,而非一条指令**(AIDEC-2026-07-18-001,来自 #365):它的前提在捕获时可能就为假,或自那以后已经过时。**在执行时重新验证前提,而不是在捕获时** —— 在你提升或对一个条目采取行动的那一刻,你已经身处那段代码之中,所以核查(一次 `grep`、读一个文件、追踪一条调用链)只需数秒。在你于其之上构建*之前*就去做:一个貌似合理却为假的前提一旦被实现,就是一个被浪费的 Charter。用 `straymark followups verify FU-NNN --verified`(或 `followups promote FU-NNN --premise-verified`)记录该次重新核查,它会盖上 `Verified-at` 印记。**不要**在捕获时验证 —— backlog 是一个推测性缓冲区,其价值在于廉价捕获;把验证前置会让理性的做法变成"停止撰写 follow-up"。 + ### Charter 关闭后 审查刚关闭的 Charter 所解决的注册表条目: @@ -409,4 +413,4 @@ confidence: high | medium | low --- -*StrayMark fw-4.35.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.36.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/dist/.straymark/00-governance/i18n/zh-CN/C4-DIAGRAM-GUIDE.md b/dist/.straymark/00-governance/i18n/zh-CN/C4-DIAGRAM-GUIDE.md index 9bd41128..434f5a37 100644 --- a/dist/.straymark/00-governance/i18n/zh-CN/C4-DIAGRAM-GUIDE.md +++ b/dist/.straymark/00-governance/i18n/zh-CN/C4-DIAGRAM-GUIDE.md @@ -234,4 +234,4 @@ Rel(api, db, "Reads/Writes", "SQL") --- -*StrayMark fw-4.35.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.36.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/dist/.straymark/00-governance/i18n/zh-CN/DOCUMENTATION-POLICY.md b/dist/.straymark/00-governance/i18n/zh-CN/DOCUMENTATION-POLICY.md index 35dd2349..f7437f3b 100644 --- a/dist/.straymark/00-governance/i18n/zh-CN/DOCUMENTATION-POLICY.md +++ b/dist/.straymark/00-governance/i18n/zh-CN/DOCUMENTATION-POLICY.md @@ -311,4 +311,4 @@ review_outcome: approved # approved | revisions_requested | rejec --- -*StrayMark fw-4.35.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.36.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/dist/.straymark/00-governance/i18n/zh-CN/FOLLOW-UPS-BACKLOG-PATTERN.md b/dist/.straymark/00-governance/i18n/zh-CN/FOLLOW-UPS-BACKLOG-PATTERN.md index d8a166f3..ad7a3227 100644 --- a/dist/.straymark/00-governance/i18n/zh-CN/FOLLOW-UPS-BACKLOG-PATTERN.md +++ b/dist/.straymark/00-governance/i18n/zh-CN/FOLLOW-UPS-BACKLOG-PATTERN.md @@ -39,6 +39,27 @@ StrayMark 的 per-AILOG `§Follow-ups` 约定在写入时有效 —— 创建 AI 来自参考 adopter 的经验教训(issue #214,N=91 个条目):backlog 不仅仅是一份延期杂务清单。Follow-ups 不仅源自规划(ex-ante,事前),也源自**执行现实** —— 测试运行、遥测读数、staging 事故、在真实(非模拟)环境中观察到的 bug —— 并且它们反过来反哺规划:它们变成杂务(chore)、迷你 Charter,甚至重塑已经规划好的 Charter。该注册表是 **SpecKit 的 ex-post(事后)对应物**:SpecKit 从意图反哺规划;backlog 从执行反哺规划。v1 维度(`Origin-class`、`Severity`、`Labels`、`Destination` 词汇表)的存在正是为了让这个规划闭环可被查询。 +它*反哺*规划 —— 但不要把它*当作*一份计划来读。每个条目都是取用时需要重新核查的一个赌注,而不是一项已承诺的任务(见下文"认识论地位")。 + +--- + +## 认识论地位 —— 条目是有日期的假设 + +*(AIDEC-2026-07-18-001,来自 Weft 现场报告 #365。)* + +follow-ups backlog 是一个**推测性缓冲区(speculative buffer)**。它的价值在于*廉价捕获*,以便在你完成其他工作时不丢失某个信号。这种廉价正是要点所在 —— 它决定了一个条目应当如何被阅读,以及何时应当核查它的前提。 + +**一个条目是一个有日期、会衰减的假设,而非一条指令。** 它记录的是在捕获时看起来为真且值得做的事 —— 一条在注意力集中于其他工作时随手记下的笔记。这条笔记在写下的那一刻就可能是错的:一个被轻信的注释、一个被过度信任的类比、一个已经开始过时的心智模型。(在奠基性的现场报告中,三个真实的 follow-up 各自都建立在一个*在写下时就为假*的前提上,而几个月后只需 ~30 秒的核查便可将其证伪。)因此: + +- **一个未经核查的条目不是撰写缺陷** —— 它是推测性缓冲区中任何事物*预期的*认识论地位。要求在捕获时就核查会破坏缓冲区的目的;理性的反应将是停止撰写 follow-up,从而丢失信号。 +- **唯一真正的 bug 是在不重新验证前提的情况下执行一个条目。** 当作指令来读,虚假的前提会变成被浪费的 Charter;当作有日期、需在执行时重新核查的假设来读,它们就成了廉价的赌注。 + +**纪律 —— 在捕获时廉价地写;在提升/执行时重新验证前提:** + +- 捕获时,自由地记下 follow-up。可选地声明它的 **`Premise`(前提)** —— 支撑它的核心假设 —— 使后续的重新核查有一个具体的靶子。 +- 执行时(你正要在其之上构建),**先针对代码重新验证前提** —— 一次 `grep`、读一个文件、追踪一条调用链。你已经身处那个子系统,所以核查只需数秒。用 `straymark followups verify FU-NNN --verified`(或 `followups promote FU-NNN --premise-verified`)记录它,这会盖上 **`Verified-at`** 印记。 +- `Verified-at` 缺失 = 自捕获以来从未重新核查(诚实的默认状态)。它的存在是一种溯源证据,表明在投入精力之前,该假设已针对现实被检验过。 + --- ## 形式 @@ -113,6 +134,8 @@ bucket 内的每个条目遵循以下形式(标注了 v1 字段;所有这些 - **Destination**: chore | mini-charter | charter-replanning | operations | | - **Cost**: <工作量估计> - **Labels**: <自由标签,逗号分隔> (v1, 可选) +- **Premise**: <支撑此条目的核心假设> (v1, 可选) +- **Verified-at**: (v1, 可选) - **Notes**: <自由格式上下文> - **Promoted to**: ``` @@ -125,6 +148,7 @@ bucket 内的每个条目遵循以下形式(标注了 v1 字段;所有这些 - **`Severity`** —— `blocking` 标记必须在生产切换之前落地的可靠性类问题。将参考 adopter 在 `Notes` 字段中浮现的 `PROD-BLOCKER` 散文约定规范化(信号 3)。与 bucket 正交:一个 `charter-triggered` 条目也可以是 `blocking`。 - **`Labels`** —— 用于在 triage 期间将条目分组到已规划的 Charter / 迷你 Charter / 杂务中的自由标签。可通过 `straymark followups list --label ` 查询。 - **`Destination` 词汇表** —— 形式化触发后工作落地的去向:`chore`、`mini-charter`、`charter-replanning`(该条目重塑一个已规划的 Charter,而不是向其添加一个任务)、`operations`、某个具体的 Charter id,或某个 TDE id。仍接受自由格式的值(宽松解析)。 +- **`Premise` / `Verified-at`** *(AIDEC-2026-07-18-001)* —— 一个条目所依赖的核心假设,以及它上次针对代码重新核查的日期。一个条目是一个*有日期的假设*(见"认识论地位");这两个字段为"在执行时重新验证"的纪律提供了具体的靶子和审计印记。二者皆可选;`Verified-at` 缺失 = 自捕获以来从未重新核查。 ### Status 词汇表 @@ -241,9 +265,12 @@ straymark followups status # 注册表脉搏:计数器(即时重 straymark followups status FU-NNN # 单个条目的详情视图 straymark followups drift [--apply|--scan-all] # 漂移检测(见上文) straymark followups recount # 手动分诊会话后重新计算 CLI 拥有的计数器(cli-3.20.0+) -straymark followups promote FU-NNN # 自动化 FU → TDE 提升(见上文) +straymark followups promote FU-NNN [--premise-verified] # 自动化 FU → TDE 提升;浮现前提重新核查,带该 flag 时盖上 Verified-at(cli-3.37.0+) +straymark followups verify FU-NNN [--premise "..."] [--verified] [--at 日期] # 在执行时重新验证一个有日期的假设:浮现/记录前提,盖上 Verified-at(cli-3.37.0+) ``` +`verify` 与 `promote --premise-verified` 是"认识论地位"纪律的执行时可供性(affordance):它们在投入的那一刻把前提摆在操作员面前,并记录重新核查已经发生。人的判断留在 CLI 之外 —— 它浮现并盖印,从不裁定真伪。 + 注册表也在 `straymark explore` TUI 中作为一个合成的 **Follow-ups** 分组出现(每个 bucket 一个子节点),并在 `straymark status` 中作为一个计数块出现。 --- @@ -316,4 +343,4 @@ straymark followups promote FU-NNN # 自动化 FU → TDE 提升(见上 --- -*StrayMark fw-4.34.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.36.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/dist/.straymark/00-governance/i18n/zh-CN/QUICK-REFERENCE.md b/dist/.straymark/00-governance/i18n/zh-CN/QUICK-REFERENCE.md index 15c11f63..812226fd 100644 --- a/dist/.straymark/00-governance/i18n/zh-CN/QUICK-REFERENCE.md +++ b/dist/.straymark/00-governance/i18n/zh-CN/QUICK-REFERENCE.md @@ -235,4 +235,4 @@ risk_level: low | medium | high | critical --- -*StrayMark fw-4.35.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.36.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/dist/.straymark/schemas/follow-ups-backlog.schema.v1.json b/dist/.straymark/schemas/follow-ups-backlog.schema.v1.json index eaf71fbd..c5d0bec9 100644 --- a/dist/.straymark/schemas/follow-ups-backlog.schema.v1.json +++ b/dist/.straymark/schemas/follow-ups-backlog.schema.v1.json @@ -121,6 +121,14 @@ "type": "string", "pattern": "^TDE-[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{3}.*$", "description": "TDE id, present when Status: promoted. The TDE's frontmatter carries the reverse pointer (promoted_from_followup: FU-NNN)." + }, + "premise": { + "type": "string", + "description": "NEW in v1 (optional, AIDEC-2026-07-18-001). The load-bearing assumption the entry rests on, stated so it can be re-checked in seconds at execution. A follow-up is a dated, decaying hypothesis: the only real bug is acting on one without re-testing its premise. Making the premise explicit turns 're-verify' from a vague nudge into a concrete, targetable check. Absent on entries authored before the field existed." + }, + "verified_at": { + "type": "string", + "description": "NEW in v1 (optional, AIDEC-2026-07-18-001). Date (YYYY-MM-DD) the premise was last re-verified against reality, stamped by `straymark followups verify --verified` or `followups promote --premise-verified`. Absent = never re-checked since capture (the default, honest state). Advisory provenance, not a validation signal — the pattern warns, never fails, on its absence." } }, "required": ["fu_id", "origin", "status"] diff --git a/dist/.straymark/templates/follow-ups-backlog.md b/dist/.straymark/templates/follow-ups-backlog.md index 227c9828..f30da8da 100644 --- a/dist/.straymark/templates/follow-ups-backlog.md +++ b/dist/.straymark/templates/follow-ups-backlog.md @@ -34,7 +34,15 @@ Entry shape (v1 — optional fields marked): - **Destination**: chore | mini-charter | charter-replanning | operations | | - **Cost**: - **Labels**: (optional) +- **Premise**: (optional) +- **Verified-at**: (optional) - **Notes**: + +An entry is a dated, decaying *hypothesis*, not an instruction. Its premise may +have been false at capture or gone stale since. Re-verify it at execution — the +cheap moment — not at capture: `straymark followups verify FU-NNN --verified` +(or `followups promote FU-NNN --premise-verified`). See the pattern doc's +"Epistemic status" section. --> ## Bucket: ready diff --git a/dist/dist-manifest.yml b/dist/dist-manifest.yml index 94d09580..d905f0db 100644 --- a/dist/dist-manifest.yml +++ b/dist/dist-manifest.yml @@ -1,4 +1,4 @@ -version: "4.35.0" +version: "4.36.0" description: "StrayMark distribution manifest" repository: "https://github.com/StrangeDaysTech/straymark" diff --git a/docs/adopters/CLI-REFERENCE.md b/docs/adopters/CLI-REFERENCE.md index 568cd597..1de873ac 100644 --- a/docs/adopters/CLI-REFERENCE.md +++ b/docs/adopters/CLI-REFERENCE.md @@ -45,8 +45,8 @@ StrayMark uses **independent version tags** for each component: | Component | Tag prefix | Example | What it includes | |-----------|-----------|---------|------------------| -| Framework | `fw-` | `fw-4.35.0` | Templates (12 types), governance docs, directives, Charter template + schema | -| CLI | `cli-` | `cli-3.36.2` | The `straymark` binary | +| Framework | `fw-` | `fw-4.36.0` | Templates (12 types), governance docs, directives, Charter template + schema | +| CLI | `cli-` | `cli-3.37.0` | The `straymark` binary | | Loom (EXPERIMENTAL) | `loom-` | `loom-0.4.2` | The `straymark-loom` visualization server, downloaded on demand by `straymark loom serve` | Framework and CLI are released independently. A framework update does not require a CLI update, and vice versa. @@ -940,6 +940,7 @@ Parsing is **lenient**: v0 registries (pre-fw-4.21.0) are read without errors; t - `straymark followups drift` — sync the registry with AILOGs (native replacement for the deprecated adopter-side `check-followups-drift.sh`) *(cli-3.19.0+)* - `straymark followups recount` — recompute the CLI-owned counters after a manual-triage session *(cli-3.20.0+)* - `straymark followups promote` — elevate an entry to a TDE document *(cli-3.19.0+)* +- `straymark followups verify` — re-verify a dated hypothesis's premise at execution time *(cli-3.37.0+)* #### `straymark followups list [--bucket ] [--status ] [--severity ] [--label ] [path]` @@ -991,14 +992,35 @@ $ straymark followups recount ✓ Counters recomputed: 0 open / 0 suspected-closed / 2 promoted (total 2). ``` -#### `straymark followups promote [--title ] [--path <dir>]` +#### `straymark followups promote <FU-NNN> [--title <title>] [--premise-verified] [--path <dir>]` Automate the FU → TDE elevation (`FOLLOW-UPS-BACKLOG-PATTERN.md` §Promotion to TDE): creates the TDE document from the framework template with `promoted_from_followup: FU-NNN` traceability, flips the entry to `Status: promoted` with `Destination`/`Promoted to` pointing at the TDE id, and recomputes the counters. Non-interactive (agent-friendly); the FU description becomes the TDE title unless `--title` overrides it. Prioritization and assignment stay human (`AGENT-RULES.md §3`). +Since **cli-3.37.0** the command surfaces the entry's `Premise` (falling back to `Notes`) with a re-verify reminder — a follow-up is a *dated hypothesis* (§Epistemic status), so re-check its premise against the code before building on it. `--premise-verified` records that you did, stamping `Verified-at: <today>`. The reminder is advisory — promotion proceeds either way. + ```bash -$ straymark followups promote FU-010 +$ straymark followups promote FU-010 --premise-verified ✓ FU-010 promoted → TDE-2026-06-04-001 TDE created: .straymark/06-evolution/technical-debt/TDE-2026-06-04-001-harden-staging-probe.md + Premise re-verification recorded: Verified-at → 2026-06-04. +``` + +#### `straymark followups verify <FU-NNN> [--premise "..."] [--verified] [--at <YYYY-MM-DD>] [--path <dir>]` *(cli-3.37.0+)* + +Re-verify a follow-up's premise **at execution time** and record it. A registry entry is a **dated, decaying hypothesis** (`AIDEC-2026-07-18-001`, from #365): its premise may have been false at capture or gone stale since, and the only real bug is acting on one without re-testing its premise. The registry is a speculative buffer — cheap capture is its value — so verification belongs at the cheap moment (acting on the entry), not at capture. This verb covers the common case of an entry acted on as a chore that never promotes. + +| Flag | Default | Description | +|------|---------|-------------| +| `--premise <text>` | — | Record or update the entry's `Premise` (the assumption to re-check). Omitted → the existing premise is surfaced. | +| `--verified` | off | Stamp `Verified-at`, confirming the premise was re-checked against the code. | +| `--at <YYYY-MM-DD>` | today | Verification date. | + +With no `--premise`/`--verified` it is **read-only** — it surfaces the premise and nudges. Human judgment stays out of the CLI: it surfaces and stamps, it never decides truth. + +```bash +$ straymark followups verify FU-016 --premise "yrs has an independent reference (Yjs)" --verified +✓ FU-016 premise recorded. +✓ FU-016 verified — Verified-at → 2026-06-04. ``` --- diff --git a/docs/i18n/es/README.md b/docs/i18n/es/README.md index adcc020b..2d201c76 100644 --- a/docs/i18n/es/README.md +++ b/docs/i18n/es/README.md @@ -240,8 +240,8 @@ StrayMark usa tags de versión independientes para cada componente: | Componente | Prefijo de tag | Ejemplo | Incluye | |------------|---------------|---------|---------| -| Framework | `fw-` | `fw-4.35.0` | Plantillas (12 tipos), gobernanza, directivas, plantilla + schema de Charter | -| CLI | `cli-` | `cli-3.36.2` | El binario `straymark` | +| Framework | `fw-` | `fw-4.36.0` | Plantillas (12 tipos), gobernanza, directivas, plantilla + schema de Charter | +| CLI | `cli-` | `cli-3.37.0` | El binario `straymark` | | Loom (EXPERIMENTAL) | `loom-` | `loom-0.4.2` | El servidor de visualización `straymark-loom`, descargado bajo demanda por `straymark loom serve` | Verifica las versiones instaladas con `straymark status` o `straymark about`. diff --git a/docs/i18n/es/adopters/CLI-REFERENCE.md b/docs/i18n/es/adopters/CLI-REFERENCE.md index 9bbe51ca..dbc29585 100644 --- a/docs/i18n/es/adopters/CLI-REFERENCE.md +++ b/docs/i18n/es/adopters/CLI-REFERENCE.md @@ -45,8 +45,8 @@ StrayMark usa **tags de versión independientes** para cada componente: | Componente | Prefijo de tag | Ejemplo | Qué incluye | |------------|---------------|---------|-------------| -| Framework | `fw-` | `fw-4.35.0` | Plantillas (12 tipos), docs de gobernanza, directivas | -| CLI | `cli-` | `cli-3.36.2` | El binario `straymark` | +| Framework | `fw-` | `fw-4.36.0` | Plantillas (12 tipos), docs de gobernanza, directivas | +| CLI | `cli-` | `cli-3.37.0` | El binario `straymark` | | Loom (EXPERIMENTAL) | `loom-` | `loom-0.4.2` | El servidor de visualización `straymark-loom`, descargado bajo demanda por `straymark loom serve` | Framework y CLI se publican de forma independiente. Una actualización del framework no requiere actualización del CLI, y viceversa. @@ -744,6 +744,7 @@ El parsing es **tolerante**: los registros v0 (pre-fw-4.21.0) se leen sin errore - `straymark followups drift` — sincroniza el registro con los AILOGs (reemplazo nativo del `check-followups-drift.sh` adopter-side, ya deprecado) *(cli-3.19.0+)* - `straymark followups recount` — recalcula los contadores propiedad del CLI tras una sesión de triage manual *(cli-3.20.0+)* - `straymark followups promote` — eleva una entrada a un documento TDE *(cli-3.19.0+)* +- `straymark followups verify` — re-verifica la premisa de una hipótesis fechada en tiempo de ejecución *(cli-3.37.0+)* #### `straymark followups list [--bucket <name>] [--status <s>] [--severity <s>] [--label <tag>] [path]` @@ -795,14 +796,35 @@ $ straymark followups recount ✓ Counters recomputed: 0 open / 0 suspected-closed / 2 promoted (total 2). ``` -#### `straymark followups promote <FU-NNN> [--title <title>] [--path <dir>]` +#### `straymark followups promote <FU-NNN> [--title <title>] [--premise-verified] [--path <dir>]` Automatiza la elevación FU → TDE (`FOLLOW-UPS-BACKLOG-PATTERN.md` §Promotion to TDE): crea el documento TDE desde el template del framework con trazabilidad `promoted_from_followup: FU-NNN`, cambia la entrada a `Status: promoted` con `Destination`/`Promoted to` apuntando al id del TDE, y recalcula los contadores. No interactivo (agent-friendly); la descripción del FU se vuelve el título del TDE salvo que `--title` lo sobreescriba. La priorización y la asignación siguen siendo humanas (`AGENT-RULES.md §3`). +Desde **cli-3.37.0** el comando superficie el `Premise` de la entrada (o los `Notes` si falta) con un recordatorio de re-verificación — un follow-up es una *hipótesis fechada* (§Estatus epistémico), así que re-chequea su premisa contra el código antes de construir sobre ella. `--premise-verified` registra que lo hiciste, sellando `Verified-at: <hoy>`. El recordatorio es informativo — la promoción procede de cualquier forma. + ```bash -$ straymark followups promote FU-010 +$ straymark followups promote FU-010 --premise-verified ✓ FU-010 promoted → TDE-2026-06-04-001 TDE created: .straymark/06-evolution/technical-debt/TDE-2026-06-04-001-harden-staging-probe.md + Premise re-verification recorded: Verified-at → 2026-06-04. +``` + +#### `straymark followups verify <FU-NNN> [--premise "..."] [--verified] [--at <YYYY-MM-DD>] [--path <dir>]` *(cli-3.37.0+)* + +Re-verifica la premisa de un follow-up **en tiempo de ejecución** y la registra. Una entrada del registry es una **hipótesis fechada y decadente** (`AIDEC-2026-07-18-001`, de #365): su premisa pudo ser falsa en la captura o haberse vuelto obsoleta, y el único bug real es actuar sobre una sin re-testear su premisa. El registry es un buffer especulativo — la captura barata es su valor — así que la verificación pertenece al momento barato (actuar sobre la entrada), no a la captura. Este verbo cubre el caso común de una entrada actuada como chore que nunca promueve. + +| Flag | Default | Descripción | +|------|---------|-------------| +| `--premise <texto>` | — | Registra o actualiza el `Premise` de la entrada (la suposición a re-chequear). Omitido → se superficie la premisa existente. | +| `--verified` | off | Sella `Verified-at`, confirmando que la premisa se re-chequeó contra el código. | +| `--at <YYYY-MM-DD>` | hoy | Fecha de verificación. | + +Sin `--premise`/`--verified` es **read-only** — superficie la premisa y hace un nudge. El juicio humano queda fuera del CLI: superficie y sella, nunca decide la verdad. + +```bash +$ straymark followups verify FU-016 --premise "yrs tiene una referencia independiente (Yjs)" --verified +✓ FU-016 premise recorded. +✓ FU-016 verified — Verified-at → 2026-06-04. ``` --- diff --git a/docs/i18n/zh-CN/README.md b/docs/i18n/zh-CN/README.md index bb527827..2764809c 100644 --- a/docs/i18n/zh-CN/README.md +++ b/docs/i18n/zh-CN/README.md @@ -258,8 +258,8 @@ StrayMark 为每个组件使用独立的版本标签: | 组件 | 标签前缀 | 示例 | 包含内容 | |------|----------|------|----------| -| Framework | `fw-` | `fw-4.35.0` | 模板(12 种类型)、治理文档、指令、Charter 模板 + schema | -| CLI | `cli-` | `cli-3.36.2` | `straymark` 二进制文件 | +| Framework | `fw-` | `fw-4.36.0` | 模板(12 种类型)、治理文档、指令、Charter 模板 + schema | +| CLI | `cli-` | `cli-3.37.0` | `straymark` 二进制文件 | | Loom(实验性) | `loom-` | `loom-0.4.2` | `straymark-loom` 可视化服务器,由 `straymark loom serve` 按需下载 | 使用 `straymark status` 或 `straymark about` 查看已安装的版本。 diff --git a/docs/i18n/zh-CN/adopters/CLI-REFERENCE.md b/docs/i18n/zh-CN/adopters/CLI-REFERENCE.md index 2478f9f8..a397c7ba 100644 --- a/docs/i18n/zh-CN/adopters/CLI-REFERENCE.md +++ b/docs/i18n/zh-CN/adopters/CLI-REFERENCE.md @@ -45,8 +45,8 @@ StrayMark 为每个组件使用**独立的版本标签**: | 组件 | 标签前缀 | 示例 | 包含内容 | |------|----------|------|----------| -| Framework | `fw-` | `fw-4.35.0` | 模板(12 种类型)、治理文档、指令 | -| CLI | `cli-` | `cli-3.36.2` | `straymark` 二进制文件 | +| Framework | `fw-` | `fw-4.36.0` | 模板(12 种类型)、治理文档、指令 | +| CLI | `cli-` | `cli-3.37.0` | `straymark` 二进制文件 | | Loom(实验性) | `loom-` | `loom-0.4.2` | `straymark-loom` 可视化服务器,由 `straymark loom serve` 按需下载 | Framework 和 CLI 独立发布。Framework 更新不需要 CLI 更新,反之亦然。 @@ -787,6 +787,7 @@ $ straymark charter audit CHARTER-05 --finalize - `straymark followups drift` — 将注册表与 AILOG 同步(已弃用的 adopter 侧 `check-followups-drift.sh` 的原生替代)*(cli-3.19.0+)* - `straymark followups recount` — 手动分诊会话后重新计算 CLI 拥有的计数器 *(cli-3.20.0+)* - `straymark followups promote` — 将条目提升为 TDE 文档 *(cli-3.19.0+)* +- `straymark followups verify` — 在执行时重新验证一个有日期假设的前提 *(cli-3.37.0+)* #### `straymark followups list [--bucket <name>] [--status <s>] [--severity <s>] [--label <tag>] [path]` @@ -838,14 +839,35 @@ $ straymark followups recount ✓ Counters recomputed: 0 open / 0 suspected-closed / 2 promoted (total 2). ``` -#### `straymark followups promote <FU-NNN> [--title <title>] [--path <dir>]` +#### `straymark followups promote <FU-NNN> [--title <title>] [--premise-verified] [--path <dir>]` 自动化 FU → TDE 的提升(`FOLLOW-UPS-BACKLOG-PATTERN.md` §Promotion to TDE):从框架模板创建带 `promoted_from_followup: FU-NNN` 溯源的 TDE 文档,将条目翻转为 `Status: promoted` 并使 `Destination`/`Promoted to` 指向该 TDE id,再重新计算计数器。非交互式(对 agent 友好);除非 `--title` 覆盖,否则 FU 描述将成为 TDE 标题。优先级排序与分配仍由人工决定(`AGENT-RULES.md §3`)。 +自 **cli-3.37.0** 起,该命令会浮现条目的 `Premise`(缺失则回退到 `Notes`)并附上重新验证提醒 —— 一个 follow-up 是一个*有日期的假设*(§认识论地位),所以在其之上构建之前,先针对代码重新核查它的前提。`--premise-verified` 记录你已这样做,并盖上 `Verified-at: <今天>`。该提醒是信息性的 —— 提升无论如何都会进行。 + ```bash -$ straymark followups promote FU-010 +$ straymark followups promote FU-010 --premise-verified ✓ FU-010 promoted → TDE-2026-06-04-001 TDE created: .straymark/06-evolution/technical-debt/TDE-2026-06-04-001-harden-staging-probe.md + Premise re-verification recorded: Verified-at → 2026-06-04. +``` + +#### `straymark followups verify <FU-NNN> [--premise "..."] [--verified] [--at <YYYY-MM-DD>] [--path <dir>]` *(cli-3.37.0+)* + +在**执行时**重新验证一个 follow-up 的前提并记录它。一个注册表条目是一个**有日期、会衰减的假设**(`AIDEC-2026-07-18-001`,来自 #365):它的前提在捕获时可能就为假,或自那以后已经过时,而唯一真正的 bug 是在不重新测试其前提的情况下对它采取行动。注册表是一个推测性缓冲区 —— 廉价捕获是它的价值 —— 所以验证属于那个廉价的时刻(对条目采取行动时),而不是捕获时。此动词覆盖了一个条目作为杂务被执行、却从不提升的常见情形。 + +| Flag | 默认 | 描述 | +|------|------|------| +| `--premise <文本>` | — | 记录或更新条目的 `Premise`(需重新核查的假设)。省略 → 浮现现有前提。 | +| `--verified` | 关 | 盖上 `Verified-at`,确认前提已针对代码重新核查。 | +| `--at <YYYY-MM-DD>` | 今天 | 验证日期。 | + +不带 `--premise`/`--verified` 时它是**只读的** —— 浮现前提并做提示。人的判断留在 CLI 之外:它浮现并盖印,从不裁定真伪。 + +```bash +$ straymark followups verify FU-016 --premise "yrs 有一个独立的参照物(Yjs)" --verified +✓ FU-016 premise recorded. +✓ FU-016 verified — Verified-at → 2026-06-04. ``` ---