diff --git a/.straymark/07-ai-audit/agent-logs/AILOG-2026-09-17-003-followups-declare.md b/.straymark/07-ai-audit/agent-logs/AILOG-2026-09-17-003-followups-declare.md new file mode 100644 index 0000000..74fbb26 --- /dev/null +++ b/.straymark/07-ai-audit/agent-logs/AILOG-2026-09-17-003-followups-declare.md @@ -0,0 +1,100 @@ +--- +id: AILOG-2026-09-17-003 +title: followups declare — supported writer for follow-up work classification (#432, #431) +status: accepted +created: 2026-09-17 +agent: claude-opus-5-1m +confidence: high +review_required: false +risk_level: low +eu_ai_act_risk: not_applicable +nist_genai_risks: [human_ai_config] +iso_42001_clause: [] +files_modified: + - cli/src/followups.rs + - cli/src/commands/followups/declare.rs + - cli/src/commands/followups/new.rs + - cli/src/commands/followups/status.rs + - cli/src/commands/followups/mod.rs + - cli/src/main.rs + - cli/src/validation.rs + - cli/tests/followups_test.rs + - cli/tests/validate_test.rs + - dist/.claude/skills/straymark-followups/SKILL.md (+ codex/agent/qoder/qwen mirrors) + - dist/.straymark/00-governance/FOLLOW-UPS-BACKLOG-PATTERN.md (+ es, zh-CN) + - dist/.straymark/templates/follow-ups-backlog.md + - docs/adopters/CLI-REFERENCE.md (+ es, zh-CN) + - docs/adopters/BATON.md (+ es, zh-CN) + - experiment-baton/07-track-c-adopter-kit.md + - cli/Cargo.toml, Cargo.lock, dist/dist-manifest.yml, version tables and footers, CHANGELOG.md, CLAUDE.md +observability_scope: none +tags: [followups, baton, adopter-feedback, cli] +related: + - 07-ai-audit/agent-logs/AILOG-2026-07-26-001-followups-mutation-creation-verbs.md +--- + +# AILOG: `followups declare` (#432, #431) + +## Summary + +Adds the missing supported writer for a follow-up's declared work classification. `straymark +followups declare FU-NNN --work-verb [--design-provenance

]` writes an existing entry's +declaration, and `followups new` takes the same flags. Also fixes the CLI half of #431: +`straymark validate` warned on the registry template's commented example line in every adopter. + +## Context + +Estoa (#432) found two rules in tension. The registry is CLI-owned ("never hand-edit an entry"), +yet Track C asks follow-ups to declare `Work verb` / `Design provenance`, and no verb wrote those +bullets. The adopter left four entries undeclared rather than hand-edit the registry or put the +declaration in `Notes`, which is the correct call and the one this change makes unnecessary. + +## Actions Performed + +1. `followups::Declaration`: the validated declaration, built only from the controlled vocabulary. + `design_provenance` is accepted only with `implement`, as the ratification specifies. The + writer is strict; `validate` and Baton stay lenient readers. +2. `followups::set_entry_declaration`: replaces both bullets **as a unit**. They go where the old + ones were, else after `Cost` (the template position), else after the last bullet. The trailing + newlines are preserved as in `set_entry_field`. +3. `followups declare`: new subcommand. It is a no-op when the declaration is unchanged, refuses + invalid input before writing, and writes through `write_recounted` like every other verb. +4. `followups new --work-verb … [--design-provenance …]`; `followups status FU-NNN` shows the + declaration. `Entry` parses the two fields. +5. `check_followups_work_verb` ignores HTML comments and fenced blocks (#431). Before, the stock + template produced 2 advisory warnings in every adopter's `validate`. +6. Skill (all agent mirrors, regenerated by `gen_minimal_skills` and copied for qoder/qwen), + pattern doc ×3, template note, CLI-REFERENCE ×3, BATON.md ×3 and the Track C kit document the + writer. Versions bumped to fw-4.45.0 / cli-3.49.0. The stale CLI rows in the version tables + (cli-3.45.0) are corrected on the way. + +## Decisions Made + +- **Name `declare`**, not a generic `set-field`. Declaration is the ratified concept (#332); a + generic field setter would reopen hand-editing by another route. +- **Unit semantics.** Omitting `--design-provenance` removes a previous one. Otherwise + re-declaring `implement/upstream` as `design` would leave a contradictory provenance behind, the + same "agreement is on the whole declaration" rule adopted for Baton's task inheritance in + PR #430. `note` / `set-status` / `new` (the AILOG in `related`) set the write-path precedent + this verb follows. +- **No `--clear`.** Undeclaring an entry has no reported need, and "undeclared" is the default + state anyway. +- Not in scope: `drift --apply` still extracts entries undeclared. Inferring a verb from the source + AILOG would be the heuristic the #332 decision removed. + +## Impact + +- **Functionality**: adopters can declare follow-ups without hand-editing the registry; `validate` + is quiet on the stock template. +- **Performance / Security / Privacy / Environmental**: N/A. + +## Verification + +- [x] `cargo test -p straymark-cli`: 778 passed. The new tests cover `new` with a declaration and + rejected declarations leaving the registry untouched; `declare` set/replace/remove, no-op and + the neighbouring entry kept intact; validate on the shipped template and on a live invalid + value; a declaration round trip; the vocabulary. +- [x] Installed CLI 3.48 emits 2 warnings on the shipped template; this branch emits 0. +- [x] `gen_minimal_skills --check` and the qoder/qwen mirror tests pass. +- [x] Clippy: no new warnings for `straymark-cli` (18/24, same as `main`). +- [x] `straymark validate`: 0 errors. diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d90a98..fbc7e50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,26 @@ and this project uses [independent versioning](README.md#versioning) for Framewo --- +## Framework 4.45.0 / CLI 3.49.0 — 2026-09-17 + +Adopter report from Estoa (#432, Track C of Baton): the follow-ups registry is CLI-owned ("never hand-edit an entry"), and Track C asks each follow-up to declare its `Work verb` / `Design provenance`, but no verb could write those fields. An adopter honouring both rules was left with undeclared entries. This release adds the missing writer. + +### Added (CLI) + +- **`straymark followups declare FU-NNN --work-verb [--design-provenance

]`** (#432): writes an existing entry's declared work classification, the bullets Baton's router reads (#332). + - The vocabulary is validated: `design | implement | audit | operate`; provenance `new | upstream`, accepted only with `implement`. Invalid input is refused before anything is written. + - The declaration is written **as a unit**: both bullets are replaced together, and omitting `--design-provenance` removes a previous provenance instead of pairing a stale one with the new verb. Re-declaring the same value is a no-op. +- **`followups new --work-verb … [--design-provenance …]`**: declares an entry at creation. The bullets land after `Cost`, as in the template's entry shape. +- `followups status FU-NNN` shows the declaration. + +### Fixed (CLI) + +- **`straymark validate` no longer warns on the registry template's example line** (#431). The shipped `follow-ups-backlog.md` documents the entry shape inside an HTML comment whose `- **Work verb**: design | implement | audit | operate` line tripped `FOLLOWUP-WORK-VERB` / `FOLLOWUP-DESIGN-PROVENANCE` in every adopter's registry. The check now reads only live entries and skips HTML comments and fenced blocks. + +### Changed (Framework) + +- The `straymark-followups` skill (all agent mirrors), `FOLLOW-UPS-BACKLOG-PATTERN.md` (EN/es/zh-CN) and the registry template's "never hand-edit" note now include `declare` and the declaration flags of `new` as the supported way to declare a follow-up. The skill adds a short "declare the work classification" step that says to leave an entry undeclared rather than guess, and never to put a declaration in `Notes`. + ## Framework 4.44.0 / CLI 3.48.0 — 2026-08-14 Third and closing PR of CHARTER-02 (#419): a remediation AILOG used to be able to close a Critical finding with prose alone — no mechanical check preventing recurrence, and nothing asked for one. This release makes the absence of a guard a first-class, validatable fact instead of an invisible omission. diff --git a/CLAUDE.md b/CLAUDE.md index 85b22aa..11125db 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -285,7 +285,8 @@ Loom releases are GitHub-release-only (no crates.io while experimental). Tag for | `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 followups note FU-NNN "" [--source ID]` | Append a dated annotation to an entry's `Notes` in one validated edit (#355) | | `straymark followups set-status FU-NNN ` | Change an entry's status **and** recompute the CLI-owned counters in the same step — no `recount` to forget (#355) | -| `straymark followups new --title … --origin "CHARTER-NN §Scope" [--bucket …] [--premise …]` | Create an entry declared ex-ante, at Charter-declaration time, with an atomically-assigned id (#360) | +| `straymark followups new --title … --origin "CHARTER-NN §Scope" [--bucket …] [--premise …] [--work-verb … [--design-provenance …]]` | Create an entry declared ex-ante, at Charter-declaration time, with an atomically-assigned id (#360); optionally declared (#432) | +| `straymark followups declare FU-NNN --work-verb [--design-provenance

]` | Write an entry's declared work classification (Baton #332) as one validated unit — the supported writer for the `Work verb` / `Design provenance` bullets (#432) | | `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 4346995..7a95ad7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2574,7 +2574,7 @@ dependencies = [ [[package]] name = "straymark-cli" -version = "3.48.0" +version = "3.49.0" dependencies = [ "anyhow", "arborist-metrics", diff --git a/README.md b/README.md index 4a74059..ae53e59 100644 --- a/README.md +++ b/README.md @@ -278,8 +278,8 @@ StrayMark uses independent version tags for each component: | Component | Tag prefix | Example | Includes | | --- | --- | --- | --- | -| Framework | `fw-` | `fw-4.44.0` | Templates (12 types), governance, directives, Charter template + schema | -| CLI | `cli-` | `cli-3.45.0` | The `straymark` binary | +| Framework | `fw-` | `fw-4.45.0` | Templates (12 types), governance, directives, Charter template + schema | +| CLI | `cli-` | `cli-3.49.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 0ec5802..bb3dd46 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "straymark-cli" -version = "3.48.0" +version = "3.49.0" edition = "2021" description = "CLI for StrayMark — the cognitive discipline your AI-assisted projects need" license = "MIT" diff --git a/cli/src/commands/followups/declare.rs b/cli/src/commands/followups/declare.rs new file mode 100644 index 0000000..d729094 --- /dev/null +++ b/cli/src/commands/followups/declare.rs @@ -0,0 +1,68 @@ +//! `straymark followups declare FU-NNN --work-verb … [--design-provenance …]` +//! — write an existing entry's declared work classification (Baton #332). +//! +//! The registry is CLI-owned ("never hand-edit an entry"), and Track C asks +//! follow-ups to declare `Work verb` / `Design provenance` — yet no verb could +//! write them: `new` had no flags, `note` only appends to `Notes` (not the +//! slot Baton reads), and `drift --apply` extracts without them. An adopter +//! honouring both rules was left with undeclared entries (Estoa, #432). +//! +//! The declaration is written as a unit: both bullets are replaced together, +//! so omitting `--design-provenance` removes a previous one instead of letting +//! a stale provenance pair with the new verb. The vocabulary is validated here +//! (the strict writer); `validate` and Baton stay lenient readers. + +use anyhow::{anyhow, bail, Result}; +use colored::Colorize; + +use crate::commands::followups::note::guard_parse_warnings; +use crate::followups::{self, Declaration}; + +pub fn run(path: &str, fu_id: &str, work_verb: &str, design_provenance: Option<&str>) -> Result<()> { + let declaration = Declaration::new(work_verb, design_provenance)?; + + let resolved = crate::utils::resolve_project_root(path) + .ok_or_else(|| anyhow!("StrayMark not installed. Run 'straymark init' first."))?; + let registry_path = followups::registry_path(&resolved.path); + 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)?; + guard_parse_warnings(®istry)?; + + let entry = followups::find_entry_unique(®istry, fu_id)?.clone(); + let describe = |verb: Option<&str>, provenance: Option<&str>| match (verb, provenance) { + (None, _) => "undeclared".to_string(), + (Some(v), None) => v.to_string(), + (Some(v), Some(p)) => format!("{v} / {p}"), + }; + let previous = describe(entry.work_verb.as_deref(), entry.design_provenance.as_deref()); + let next = describe( + Some(&declaration.work_verb), + declaration.design_provenance.as_deref(), + ); + + if declaration.matches(&entry) { + println!( + " {} {} is already declared `{}` — nothing to change.", + "OK".green().bold(), + entry.fu_id, + next + ); + return Ok(()); + } + + let body = followups::set_entry_declaration(®istry.body, &entry, &declaration); + followups::write_recounted(®istry_path, ®istry.frontmatter_raw, &body)?; + + crate::utils::success(&format!( + "{}: {} → {}", + entry.fu_id, + previous.dimmed(), + next.bold() + )); + Ok(()) +} diff --git a/cli/src/commands/followups/mod.rs b/cli/src/commands/followups/mod.rs index ca04893..a3f448e 100644 --- a/cli/src/commands/followups/mod.rs +++ b/cli/src/commands/followups/mod.rs @@ -14,7 +14,10 @@ //! annotate, re-state and create entries through the same surgical helpers the //! rest of the namespace writes with, recomputing the CLI-owned counters in the //! same step so the edit-then-`recount` desync window does not exist. +//! `declare` (#432) does the same for an entry's declared work classification +//! (Baton #332), the one declaration slot that still had no writer. +pub mod declare; pub mod drift; pub mod install_merge_driver; pub mod list; diff --git a/cli/src/commands/followups/new.rs b/cli/src/commands/followups/new.rs index 5bf75c6..e8d6443 100644 --- a/cli/src/commands/followups/new.rs +++ b/cli/src/commands/followups/new.rs @@ -36,6 +36,8 @@ pub struct NewArgs<'a> { pub trigger: Option<&'a str>, pub destination: Option<&'a str>, pub cost: Option<&'a str>, + pub work_verb: Option<&'a str>, + pub design_provenance: Option<&'a str>, pub premise: Option<&'a str>, } @@ -66,6 +68,16 @@ pub fn run(args: NewArgs<'_>) -> Result<()> { if status == FuStatus::Promoted { bail!("An entry cannot be created as `promoted` — use `followups promote` on an existing entry."); } + // Declared work classification (Baton #332, #432). Validated before any + // write: the registry only ever receives a well-formed declaration. + let declaration = match (args.work_verb, args.design_provenance) { + (Some(verb), provenance) => Some(followups::Declaration::new(verb, provenance)?), + (None, Some(_)) => bail!( + "--design-provenance needs --work-verb implement: provenance qualifies an \ + implementation, it is not a declaration on its own." + ), + (None, None) => None, + }; let resolved = utils::resolve_project_root(args.path) .ok_or_else(|| anyhow!("StrayMark not installed. Run 'straymark init' first."))?; @@ -95,6 +107,7 @@ pub fn run(args: NewArgs<'_>) -> Result<()> { args.trigger, args.destination, args.cost, + declaration.as_ref(), args.premise, ¬es, ); diff --git a/cli/src/commands/followups/status.rs b/cli/src/commands/followups/status.rs index f227eee..98b03d2 100644 --- a/cli/src/commands/followups/status.rs +++ b/cli/src/commands/followups/status.rs @@ -218,6 +218,8 @@ fn print_entry_detail(registry: &Registry, id: &str) -> Result<()> { print_field("Trigger", entry.trigger.as_deref()); print_field("Destination", entry.destination.as_deref()); print_field("Cost", entry.cost.as_deref()); + print_field("Work verb", entry.work_verb.as_deref()); + print_field("Design provenance", entry.design_provenance.as_deref()); if !entry.labels.is_empty() { print_field("Labels", Some(&entry.labels.join(", "))); } diff --git a/cli/src/followups.rs b/cli/src/followups.rs index b1d6ee1..b15adf8 100644 --- a/cli/src/followups.rs +++ b/cli/src/followups.rs @@ -150,6 +150,11 @@ pub struct Entry { /// `followups verify`/`promote --premise-verified`. Absent = never /// re-checked since capture (the default, honest state). pub verified_at: Option, + /// Declared work classification (Baton #332): `design` | `implement` | + /// `audit` | `operate`. Absent = undeclared (the honest default). + pub work_verb: Option, + /// `new` | `upstream` — only meaningful with `implement`. + pub design_provenance: 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 @@ -408,6 +413,8 @@ fn parse_entries( promoted_to: None, premise: None, verified_at: None, + work_verb: None, + design_provenance: None, span_start: abs_start, span_end: abs_end, }; @@ -448,6 +455,10 @@ fn parse_entries( "verified-at" | "verified at" | "verified_at" => { entry.verified_at = some_nonempty(value) } + "work verb" | "work-verb" | "work_verb" => entry.work_verb = some_nonempty(value), + "design provenance" | "design-provenance" | "design_provenance" => { + entry.design_provenance = some_nonempty(value) + } _ => {} // unknown field — lenient, preserved in the raw body } } @@ -1389,6 +1400,114 @@ pub fn set_entry_field(body: &str, entry: &Entry, field: &str, value: &str) -> S out } +/// Controlled vocabulary of `Work verb` (Baton #332, ratified in +/// `experiment-baton/06-work-verb-schema-ratification.md`). +pub const WORK_VERBS: &[&str] = &["design", "implement", "audit", "operate"]; +/// Controlled vocabulary of `Design provenance`. +pub const DESIGN_PROVENANCES: &[&str] = &["new", "upstream"]; + +/// An entry's declared work classification, validated at construction so a +/// writer can only ever put a well-formed declaration in the registry. The +/// reader (`validate`, Baton) stays lenient — this is the one strict side. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Declaration { + pub work_verb: String, + pub design_provenance: Option, +} + +impl Declaration { + pub fn new(work_verb: &str, design_provenance: Option<&str>) -> Result { + let verb = work_verb.trim().to_lowercase(); + if !WORK_VERBS.contains(&verb.as_str()) { + bail!( + "Unknown work verb '{}'. Valid: {}.", + work_verb.trim(), + WORK_VERBS.join(" | ") + ); + } + let provenance = match design_provenance.map(|p| p.trim().to_lowercase()) { + None => None, + Some(p) if !DESIGN_PROVENANCES.contains(&p.as_str()) => bail!( + "Unknown design provenance '{}'. Valid: {}.", + p, + DESIGN_PROVENANCES.join(" | ") + ), + Some(_) if verb != "implement" => bail!( + "--design-provenance only applies to `implement` (it says whether the design being \ + implemented is new or already decided upstream); `{}` takes none.", + verb + ), + Some(p) => Some(p), + }; + Ok(Self { + work_verb: verb, + design_provenance: provenance, + }) + } + + /// Whether `entry` already carries exactly this declaration. + pub fn matches(&self, entry: &Entry) -> bool { + entry.work_verb.as_deref() == Some(self.work_verb.as_str()) + && entry.design_provenance.as_deref() == self.design_provenance.as_deref() + } + + /// The entry bullets encoding this declaration, in template order. + fn bullets(&self) -> Vec { + let mut out = vec![format!("- **Work verb**: {}", self.work_verb)]; + if let Some(p) = &self.design_provenance { + out.push(format!("- **Design provenance**: {}", p)); + } + out + } +} + +/// Replace an entry's declared work classification **as a unit**: the +/// `Work verb` and `Design provenance` bullets are removed and the new +/// declaration's bullets written in their place. Replacing only the verb would +/// let a stale provenance from an earlier declaration pair with the new verb. +/// New bullets go where the old ones were, else after `Cost` (the template +/// position), else after the last bullet. +pub fn set_entry_declaration(body: &str, entry: &Entry, declaration: &Declaration) -> String { + let block = &body[entry.span_start..entry.span_end]; + let is_declaration = |l: &str| { + parse_field_line(l).is_some_and(|(field, _)| { + matches!( + field.to_lowercase().as_str(), + "work verb" | "work-verb" | "work_verb" | "design provenance" + | "design-provenance" | "design_provenance" + ) + }) + }; + let mut lines: Vec = block.lines().map(|s| s.to_string()).collect(); + let previous = lines.iter().position(|l| is_declaration(l)); + lines.retain(|l| !is_declaration(l)); + let insert_at = previous.unwrap_or_else(|| { + let after = |field: &str| { + lines.iter().rposition(|l| { + parse_field_line(l).is_some_and(|(f, _)| field.is_empty() || f.eq_ignore_ascii_case(field)) + }) + }; + after("Cost") + .or_else(|| after("")) + .map(|i| i + 1) + .unwrap_or(lines.len()) + }); + for (offset, line) in declaration.bullets().into_iter().enumerate() { + lines.insert(insert_at + offset, line); + } + let mut new_block = lines.join("\n"); + // Same trailing-newline preservation as `set_entry_field`. + let trailing = block.len() - block.trim_end_matches('\n').len(); + while new_block.len() - new_block.trim_end_matches('\n').len() < trailing { + new_block.push('\n'); + } + let mut out = String::with_capacity(body.len() + 64); + out.push_str(&body[..entry.span_start]); + out.push_str(&new_block); + out.push_str(&body[entry.span_end..]); + out +} + /// The five canonical buckets (schema v1 `buckets` enum). Stable at N=91 /// entries in the reference adopter — no sixth has been needed. pub const CANONICAL_BUCKETS: &[&str] = &[ @@ -1463,6 +1582,7 @@ pub fn render_declared_entry( trigger: Option<&str>, destination: Option<&str>, cost: Option<&str>, + declaration: Option<&Declaration>, premise: Option<&str>, notes: &str, ) -> String { @@ -1488,6 +1608,12 @@ pub fn render_declared_entry( field(destination), field(cost), ); + if let Some(d) = declaration { + for line in d.bullets() { + block.push_str(&line); + block.push('\n'); + } + } if let Some(p) = premise.map(str::trim).filter(|s| !s.is_empty()) { block.push_str(&format!("- **Premise**: {}\n", p)); } @@ -2400,6 +2526,7 @@ Done. None, None, Some("S"), + None, Some("the Redis adapter has no CI coverage today"), "Created by `straymark followups new` 2026-07-26.", ); @@ -2427,8 +2554,35 @@ Done. #[test] fn render_declared_entry_omits_premise_when_absent() { - let block = render_declared_entry(1, "T", "CHARTER-01 §Scope", "open", None, None, None, None, "n"); + let block = render_declared_entry(1, "T", "CHARTER-01 §Scope", "open", None, None, None, None, None, "n"); assert!(!block.contains("Premise")); + assert!(!block.contains("Work verb"), "undeclared unless asked"); + } + + #[test] + fn declaration_round_trips_through_the_parser() { + let declaration = Declaration::new(" Implement ", Some("UPSTREAM")).unwrap(); + let block = render_declared_entry( + 12, "T", "CHARTER-01 §Scope", "open", None, None, Some("S"), Some(&declaration), None, "n", + ); + assert!(block.contains("- **Cost**: S\n- **Work verb**: implement\n- **Design provenance**: upstream\n")); + let reg = parse(V0_REGISTRY); + let reparsed = parse(&assemble( + ®.frontmatter_raw, + &insert_into_bucket(®, "ready", &block), + )); + let entry = find_entry(&reparsed, "FU-012").unwrap(); + assert!(declaration.matches(entry)); + assert_eq!(entry.work_verb.as_deref(), Some("implement")); + assert_eq!(entry.design_provenance.as_deref(), Some("upstream")); + } + + #[test] + fn declaration_rejects_out_of_vocabulary_and_misplaced_provenance() { + assert!(Declaration::new("refactor", None).is_err()); + assert!(Declaration::new("implement", Some("maybe")).is_err()); + assert!(Declaration::new("design", Some("new")).is_err()); + assert!(Declaration::new("operate", None).is_ok()); } #[test] diff --git a/cli/src/main.rs b/cli/src/main.rs index 0a8fa13..1140a36 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -582,6 +582,14 @@ enum FollowupsCommands { /// Effort estimate, free-form (default: TBD) #[arg(long)] cost: Option, + /// Declared work classification (Baton #332): design | implement | + /// audit | operate. Omit to leave the entry undeclared. + #[arg(long = "work-verb")] + work_verb: Option, + /// new | upstream — only with `--work-verb implement` (is the design + /// being implemented new, or already decided upstream?) + #[arg(long = "design-provenance", requires = "work_verb")] + design_provenance: Option, /// The load-bearing assumption this entry rests on — what a future /// reader must re-check before acting (AIDEC-2026-07-18-001) #[arg(long)] @@ -590,6 +598,23 @@ enum FollowupsCommands { #[arg(long = "path", default_value = ".")] path: String, }, + /// Declare an existing entry's work classification (Baton #332, #432): + /// writes the `Work verb` / `Design provenance` bullets as one unit, with + /// the vocabulary validated. Omitting --design-provenance removes a + /// previous one, so a stale provenance never pairs with a new verb. + Declare { + /// Entry identifier (FU-NNN or just NNN) + fu_id: String, + /// design | implement | audit | operate + #[arg(long = "work-verb")] + work_verb: String, + /// new | upstream — only with `--work-verb implement` + #[arg(long = "design-provenance")] + design_provenance: Option, + /// Project directory (default: current directory) + #[arg(long = "path", default_value = ".")] + path: String, + }, } /// Sub-analyses under `straymark analyze`. @@ -1169,6 +1194,8 @@ fn main() { trigger, destination, cost, + work_verb, + design_provenance, premise, path, } => commands::followups::new::run(commands::followups::new::NewArgs { @@ -1180,8 +1207,21 @@ fn main() { trigger: trigger.as_deref(), destination: destination.as_deref(), cost: cost.as_deref(), + work_verb: work_verb.as_deref(), + design_provenance: design_provenance.as_deref(), premise: premise.as_deref(), }), + FollowupsCommands::Declare { + fu_id, + work_verb, + design_provenance, + path, + } => commands::followups::declare::run( + &path, + &fu_id, + &work_verb, + design_provenance.as_deref(), + ), }, Commands::Architecture { command } => match command { ArchitectureCommands::Generate { path, force, out } => { diff --git a/cli/src/validation.rs b/cli/src/validation.rs index 675682c..2152f35 100644 --- a/cli/src/validation.rs +++ b/cli/src/validation.rs @@ -399,18 +399,29 @@ fn check_charter_work_verb(raw_yaml: &serde_yaml::Value, path: &Path, result: &m /// Advisory check for `**Work verb**:` / `**Design provenance**:` lines in the /// follow-ups backlog (Baton #332, same vocabulary as `check_charter_work_verb`). -/// Anti-noise: only flags values *present but outside* the controlled vocabulary. +/// Anti-noise: only flags values *present but outside* the controlled vocabulary, +/// and only in live entries — the shipped registry documents the entry shape in +/// an HTML comment whose example line lists the whole vocabulary (#431). fn check_followups_work_verb(straymark_dir: &Path, result: &mut ValidationResult) { - const WORK_VERBS: &[&str] = &["design", "implement", "audit", "operate"]; - const PROVENANCES: &[&str] = &["new", "upstream"]; + use crate::followups::{DESIGN_PROVENANCES as PROVENANCES, WORK_VERBS}; let backlog = straymark_dir.join("follow-ups-backlog.md"); let Ok(content) = std::fs::read_to_string(&backlog) else { return; // No backlog — nothing to check. }; + let mut in_comment = false; + let mut in_fence = false; for (line_no, line) in content.lines().enumerate() { - let trimmed = line.trim(); + let visible = outside_html_comments(line, &mut in_comment); + let trimmed = visible.trim(); + if trimmed.starts_with("```") || trimmed.starts_with("~~~") { + in_fence = !in_fence; + continue; + } + if in_fence { + continue; + } for (prefix, valid, rule) in [ ("- **Work verb**:", WORK_VERBS, "FOLLOWUP-WORK-VERB"), ("- **Design provenance**:", PROVENANCES, "FOLLOWUP-DESIGN-PROVENANCE"), @@ -439,6 +450,30 @@ fn check_followups_work_verb(straymark_dir: &Path, result: &mut ValidationResult } } +/// The part of `line` outside HTML comments. `in_comment` carries an open +/// `") else { + return out; + }; + rest = &rest[end + 3..]; + *in_comment = false; + } else { + let Some(start) = rest.find("\n\n## Bucket: ready\n\n### FU-001 — Live entry\n- **Status**: open\n- **Work verb**: refactor\n", + ) + .unwrap(); + + let mut cmd = cargo_bin_cmd!("straymark"); + cmd.arg("validate") + .arg(dir.path().to_str().unwrap()) + .assert() + .success() // advisory + .stdout(predicate::str::contains("FOLLOWUP-WORK-VERB")) + .stdout(predicate::str::contains("refactor")) + .stdout(predicate::str::contains("design | implement").not()); +} diff --git a/dist/.agent/skills/straymark-followups/SKILL.md b/dist/.agent/skills/straymark-followups/SKILL.md index e7650f4..b10c307 100644 --- a/dist/.agent/skills/straymark-followups/SKILL.md +++ b/dist/.agent/skills/straymark-followups/SKILL.md @@ -1,11 +1,11 @@ --- name: straymark-followups -description: Maintain the follow-ups backlog registry — the canonical answer to "what's pending?". Session-start glance, pre-commit drift --apply, post-Charter-close triage (note / set-status), ex-ante creation at Charter declaration (new), and operator-gated promote. Thin wrapper over the straymark followups CLI; never edits CLI-owned counters by hand. +description: Maintain the follow-ups backlog registry — the canonical answer to "what's pending?". Session-start glance, pre-commit drift --apply, post-Charter-close triage (note / set-status), ex-ante creation at Charter declaration (new), work-classification declaration (declare), and operator-gated promote. Thin wrapper over the straymark followups CLI; never edits CLI-owned counters by hand. --- # StrayMark Follow-ups Registry Skill -Maintain the central follow-ups registry (`.straymark/follow-ups-backlog.md`) — the first-class artifact that aggregates `§Follow-ups` and `R (new, not in Charter)` entries across AILOGs *(first-class since fw-4.21.0 / cli-3.19.0)*. The agent is the registry's **primary maintainer**; this skill drives the three directives of `AGENT-RULES.md §13` by delegating every mutation to the CLI (`straymark followups list/status/drift/note/set-status/new/promote`). The skill contains no extraction or counting logic of its own — parsing, schema validation, counter recomputation, and FU → TDE elevation all live in the CLI. +Maintain the central follow-ups registry (`.straymark/follow-ups-backlog.md`) — the first-class artifact that aggregates `§Follow-ups` and `R (new, not in Charter)` entries across AILOGs *(first-class since fw-4.21.0 / cli-3.19.0)*. The agent is the registry's **primary maintainer**; this skill drives the three directives of `AGENT-RULES.md §13` by delegating every mutation to the CLI (`straymark followups list/status/drift/note/set-status/new/declare/promote`). The skill contains no extraction or counting logic of its own — parsing, schema validation, counter recomputation, and FU → TDE elevation all live in the CLI. > See `.straymark/00-governance/FOLLOW-UPS-BACKLOG-PATTERN.md` and `STRAYMARK.md §16` for the pattern; `AGENT-RULES.md §13` for the shipped directives this skill wraps. @@ -77,6 +77,19 @@ straymark followups new --title "" \ The command prints the assigned `FU-NNN`. **Cite that id in the Charter body** — never a guessed id: the entry now exists, so a later `drift --apply` cannot hand the same number to a different entry. +### 3c. Declare the work classification (cli-3.49.0+) + +When an entry's kind of work is clear, declare it — the `Work verb` / `Design provenance` bullets are the signal Baton routes on (#332), and an undeclared entry routes conservatively to the frontier tier: + +```bash +straymark followups new … --work-verb implement --design-provenance new # at creation +straymark followups declare FU-NNN --work-verb audit # on an existing entry +``` + +- Vocabulary: `design | implement | audit | operate`. `--design-provenance new|upstream` only applies to `implement` (`upstream` = instrumenting a design already decided elsewhere, which routes as mechanical work). Defining a bounded foundational contract is `implement`, not `design`. +- `declare` writes the declaration **as a unit**: omitting `--design-provenance` removes a previous one. +- Leave an entry undeclared rather than guess. Never put a declaration in `Notes` — Baton does not read it there. + ### 4. Report result Surface the CLI output verbatim (counters, alerts, created TDE paths). Example after a pre-commit sync: @@ -92,7 +105,7 @@ StrayMark: registry synced — commit it together with the AILOG. ## What this skill does NOT do - **It does not edit the frontmatter counters** (`total_open`, `total_promoted`, `total_suspected_closed`, …). They are CLI-owned: `straymark followups recount` (or any write command) recomputes them. Hand-editing them is a §13 violation. -- **It does not hand-edit entries.** `note` / `set-status` / `new` (cli-3.39.0+) are the write path; hand-editing a CLI-parsed registry is what those verbs exist to replace. +- **It does not hand-edit entries.** `note` / `set-status` / `new` (cli-3.39.0+) and `declare` (cli-3.49.0+) are the write path; hand-editing a CLI-parsed registry is what those verbs exist to replace. - **It does not promote without the operator.** `straymark followups promote` is proposed, never auto-run — prioritization and assignment stay human (`AGENT-RULES.md §3`). - **It does not delete `suspected-closed` entries.** The operator confirms (→ `closed`) or reopens them at the next triage. - **It does not re-scan AILOGs to answer "what's pending?"** when the registry exists — the registry is canonical; `drift` tells you when it is not trustworthy. diff --git a/dist/.claude/skills/straymark-followups/SKILL.md b/dist/.claude/skills/straymark-followups/SKILL.md index 3f9935f..04ff2d4 100644 --- a/dist/.claude/skills/straymark-followups/SKILL.md +++ b/dist/.claude/skills/straymark-followups/SKILL.md @@ -1,12 +1,12 @@ --- name: straymark-followups -description: Maintain the follow-ups backlog registry — the canonical answer to "what's pending?". Session-start glance, pre-commit drift --apply, post-Charter-close triage (note / set-status), ex-ante creation at Charter declaration (new), and operator-gated promote. Thin wrapper over the straymark followups CLI; never edits CLI-owned counters by hand. +description: Maintain the follow-ups backlog registry — the canonical answer to "what's pending?". Session-start glance, pre-commit drift --apply, post-Charter-close triage (note / set-status), ex-ante creation at Charter declaration (new), work-classification declaration (declare), and operator-gated promote. Thin wrapper over the straymark followups CLI; never edits CLI-owned counters by hand. allowed-tools: Read, Glob, Bash(git diff *, git log *, git status *, ls *, straymark followups *) --- # StrayMark Follow-ups Registry Skill -Maintain the central follow-ups registry (`.straymark/follow-ups-backlog.md`) — the first-class artifact that aggregates `§Follow-ups` and `R (new, not in Charter)` entries across AILOGs *(first-class since fw-4.21.0 / cli-3.19.0)*. The agent is the registry's **primary maintainer**; this skill drives the three directives of `AGENT-RULES.md §13` by delegating every mutation to the CLI (`straymark followups list/status/drift/note/set-status/new/promote`). The skill contains no extraction or counting logic of its own — parsing, schema validation, counter recomputation, and FU → TDE elevation all live in the CLI. +Maintain the central follow-ups registry (`.straymark/follow-ups-backlog.md`) — the first-class artifact that aggregates `§Follow-ups` and `R (new, not in Charter)` entries across AILOGs *(first-class since fw-4.21.0 / cli-3.19.0)*. The agent is the registry's **primary maintainer**; this skill drives the three directives of `AGENT-RULES.md §13` by delegating every mutation to the CLI (`straymark followups list/status/drift/note/set-status/new/declare/promote`). The skill contains no extraction or counting logic of its own — parsing, schema validation, counter recomputation, and FU → TDE elevation all live in the CLI. > See `.straymark/00-governance/FOLLOW-UPS-BACKLOG-PATTERN.md` and `STRAYMARK.md §16` for the pattern; `AGENT-RULES.md §13` for the shipped directives this skill wraps. @@ -78,6 +78,19 @@ straymark followups new --title "" \ The command prints the assigned `FU-NNN`. **Cite that id in the Charter body** — never a guessed id: the entry now exists, so a later `drift --apply` cannot hand the same number to a different entry. +### 3c. Declare the work classification (cli-3.49.0+) + +When an entry's kind of work is clear, declare it — the `Work verb` / `Design provenance` bullets are the signal Baton routes on (#332), and an undeclared entry routes conservatively to the frontier tier: + +```bash +straymark followups new … --work-verb implement --design-provenance new # at creation +straymark followups declare FU-NNN --work-verb audit # on an existing entry +``` + +- Vocabulary: `design | implement | audit | operate`. `--design-provenance new|upstream` only applies to `implement` (`upstream` = instrumenting a design already decided elsewhere, which routes as mechanical work). Defining a bounded foundational contract is `implement`, not `design`. +- `declare` writes the declaration **as a unit**: omitting `--design-provenance` removes a previous one. +- Leave an entry undeclared rather than guess. Never put a declaration in `Notes` — Baton does not read it there. + ### 4. Report result Surface the CLI output verbatim (counters, alerts, created TDE paths). Example after a pre-commit sync: @@ -93,7 +106,7 @@ StrayMark: registry synced — commit it together with the AILOG. ## What this skill does NOT do - **It does not edit the frontmatter counters** (`total_open`, `total_promoted`, `total_suspected_closed`, …). They are CLI-owned: `straymark followups recount` (or any write command) recomputes them. Hand-editing them is a §13 violation. -- **It does not hand-edit entries.** `note` / `set-status` / `new` (cli-3.39.0+) are the write path; hand-editing a CLI-parsed registry is what those verbs exist to replace. +- **It does not hand-edit entries.** `note` / `set-status` / `new` (cli-3.39.0+) and `declare` (cli-3.49.0+) are the write path; hand-editing a CLI-parsed registry is what those verbs exist to replace. - **It does not promote without the operator.** `straymark followups promote` is proposed, never auto-run — prioritization and assignment stay human (`AGENT-RULES.md §3`). - **It does not delete `suspected-closed` entries.** The operator confirms (→ `closed`) or reopens them at the next triage. - **It does not re-scan AILOGs to answer "what's pending?"** when the registry exists — the registry is canonical; `drift` tells you when it is not trustworthy. diff --git a/dist/.codex/skills/straymark-followups/SKILL.md b/dist/.codex/skills/straymark-followups/SKILL.md index e7650f4..b10c307 100644 --- a/dist/.codex/skills/straymark-followups/SKILL.md +++ b/dist/.codex/skills/straymark-followups/SKILL.md @@ -1,11 +1,11 @@ --- name: straymark-followups -description: Maintain the follow-ups backlog registry — the canonical answer to "what's pending?". Session-start glance, pre-commit drift --apply, post-Charter-close triage (note / set-status), ex-ante creation at Charter declaration (new), and operator-gated promote. Thin wrapper over the straymark followups CLI; never edits CLI-owned counters by hand. +description: Maintain the follow-ups backlog registry — the canonical answer to "what's pending?". Session-start glance, pre-commit drift --apply, post-Charter-close triage (note / set-status), ex-ante creation at Charter declaration (new), work-classification declaration (declare), and operator-gated promote. Thin wrapper over the straymark followups CLI; never edits CLI-owned counters by hand. --- # StrayMark Follow-ups Registry Skill -Maintain the central follow-ups registry (`.straymark/follow-ups-backlog.md`) — the first-class artifact that aggregates `§Follow-ups` and `R (new, not in Charter)` entries across AILOGs *(first-class since fw-4.21.0 / cli-3.19.0)*. The agent is the registry's **primary maintainer**; this skill drives the three directives of `AGENT-RULES.md §13` by delegating every mutation to the CLI (`straymark followups list/status/drift/note/set-status/new/promote`). The skill contains no extraction or counting logic of its own — parsing, schema validation, counter recomputation, and FU → TDE elevation all live in the CLI. +Maintain the central follow-ups registry (`.straymark/follow-ups-backlog.md`) — the first-class artifact that aggregates `§Follow-ups` and `R (new, not in Charter)` entries across AILOGs *(first-class since fw-4.21.0 / cli-3.19.0)*. The agent is the registry's **primary maintainer**; this skill drives the three directives of `AGENT-RULES.md §13` by delegating every mutation to the CLI (`straymark followups list/status/drift/note/set-status/new/declare/promote`). The skill contains no extraction or counting logic of its own — parsing, schema validation, counter recomputation, and FU → TDE elevation all live in the CLI. > See `.straymark/00-governance/FOLLOW-UPS-BACKLOG-PATTERN.md` and `STRAYMARK.md §16` for the pattern; `AGENT-RULES.md §13` for the shipped directives this skill wraps. @@ -77,6 +77,19 @@ straymark followups new --title "" \ The command prints the assigned `FU-NNN`. **Cite that id in the Charter body** — never a guessed id: the entry now exists, so a later `drift --apply` cannot hand the same number to a different entry. +### 3c. Declare the work classification (cli-3.49.0+) + +When an entry's kind of work is clear, declare it — the `Work verb` / `Design provenance` bullets are the signal Baton routes on (#332), and an undeclared entry routes conservatively to the frontier tier: + +```bash +straymark followups new … --work-verb implement --design-provenance new # at creation +straymark followups declare FU-NNN --work-verb audit # on an existing entry +``` + +- Vocabulary: `design | implement | audit | operate`. `--design-provenance new|upstream` only applies to `implement` (`upstream` = instrumenting a design already decided elsewhere, which routes as mechanical work). Defining a bounded foundational contract is `implement`, not `design`. +- `declare` writes the declaration **as a unit**: omitting `--design-provenance` removes a previous one. +- Leave an entry undeclared rather than guess. Never put a declaration in `Notes` — Baton does not read it there. + ### 4. Report result Surface the CLI output verbatim (counters, alerts, created TDE paths). Example after a pre-commit sync: @@ -92,7 +105,7 @@ StrayMark: registry synced — commit it together with the AILOG. ## What this skill does NOT do - **It does not edit the frontmatter counters** (`total_open`, `total_promoted`, `total_suspected_closed`, …). They are CLI-owned: `straymark followups recount` (or any write command) recomputes them. Hand-editing them is a §13 violation. -- **It does not hand-edit entries.** `note` / `set-status` / `new` (cli-3.39.0+) are the write path; hand-editing a CLI-parsed registry is what those verbs exist to replace. +- **It does not hand-edit entries.** `note` / `set-status` / `new` (cli-3.39.0+) and `declare` (cli-3.49.0+) are the write path; hand-editing a CLI-parsed registry is what those verbs exist to replace. - **It does not promote without the operator.** `straymark followups promote` is proposed, never auto-run — prioritization and assignment stay human (`AGENT-RULES.md §3`). - **It does not delete `suspected-closed` entries.** The operator confirms (→ `closed`) or reopens them at the next triage. - **It does not re-scan AILOGs to answer "what's pending?"** when the registry exists — the registry is canonical; `drift` tells you when it is not trustworthy. diff --git a/dist/.qoder/skills/straymark-followups/SKILL.md b/dist/.qoder/skills/straymark-followups/SKILL.md index 3f9935f..04ff2d4 100644 --- a/dist/.qoder/skills/straymark-followups/SKILL.md +++ b/dist/.qoder/skills/straymark-followups/SKILL.md @@ -1,12 +1,12 @@ --- name: straymark-followups -description: Maintain the follow-ups backlog registry — the canonical answer to "what's pending?". Session-start glance, pre-commit drift --apply, post-Charter-close triage (note / set-status), ex-ante creation at Charter declaration (new), and operator-gated promote. Thin wrapper over the straymark followups CLI; never edits CLI-owned counters by hand. +description: Maintain the follow-ups backlog registry — the canonical answer to "what's pending?". Session-start glance, pre-commit drift --apply, post-Charter-close triage (note / set-status), ex-ante creation at Charter declaration (new), work-classification declaration (declare), and operator-gated promote. Thin wrapper over the straymark followups CLI; never edits CLI-owned counters by hand. allowed-tools: Read, Glob, Bash(git diff *, git log *, git status *, ls *, straymark followups *) --- # StrayMark Follow-ups Registry Skill -Maintain the central follow-ups registry (`.straymark/follow-ups-backlog.md`) — the first-class artifact that aggregates `§Follow-ups` and `R (new, not in Charter)` entries across AILOGs *(first-class since fw-4.21.0 / cli-3.19.0)*. The agent is the registry's **primary maintainer**; this skill drives the three directives of `AGENT-RULES.md §13` by delegating every mutation to the CLI (`straymark followups list/status/drift/note/set-status/new/promote`). The skill contains no extraction or counting logic of its own — parsing, schema validation, counter recomputation, and FU → TDE elevation all live in the CLI. +Maintain the central follow-ups registry (`.straymark/follow-ups-backlog.md`) — the first-class artifact that aggregates `§Follow-ups` and `R (new, not in Charter)` entries across AILOGs *(first-class since fw-4.21.0 / cli-3.19.0)*. The agent is the registry's **primary maintainer**; this skill drives the three directives of `AGENT-RULES.md §13` by delegating every mutation to the CLI (`straymark followups list/status/drift/note/set-status/new/declare/promote`). The skill contains no extraction or counting logic of its own — parsing, schema validation, counter recomputation, and FU → TDE elevation all live in the CLI. > See `.straymark/00-governance/FOLLOW-UPS-BACKLOG-PATTERN.md` and `STRAYMARK.md §16` for the pattern; `AGENT-RULES.md §13` for the shipped directives this skill wraps. @@ -78,6 +78,19 @@ straymark followups new --title "" \ The command prints the assigned `FU-NNN`. **Cite that id in the Charter body** — never a guessed id: the entry now exists, so a later `drift --apply` cannot hand the same number to a different entry. +### 3c. Declare the work classification (cli-3.49.0+) + +When an entry's kind of work is clear, declare it — the `Work verb` / `Design provenance` bullets are the signal Baton routes on (#332), and an undeclared entry routes conservatively to the frontier tier: + +```bash +straymark followups new … --work-verb implement --design-provenance new # at creation +straymark followups declare FU-NNN --work-verb audit # on an existing entry +``` + +- Vocabulary: `design | implement | audit | operate`. `--design-provenance new|upstream` only applies to `implement` (`upstream` = instrumenting a design already decided elsewhere, which routes as mechanical work). Defining a bounded foundational contract is `implement`, not `design`. +- `declare` writes the declaration **as a unit**: omitting `--design-provenance` removes a previous one. +- Leave an entry undeclared rather than guess. Never put a declaration in `Notes` — Baton does not read it there. + ### 4. Report result Surface the CLI output verbatim (counters, alerts, created TDE paths). Example after a pre-commit sync: @@ -93,7 +106,7 @@ StrayMark: registry synced — commit it together with the AILOG. ## What this skill does NOT do - **It does not edit the frontmatter counters** (`total_open`, `total_promoted`, `total_suspected_closed`, …). They are CLI-owned: `straymark followups recount` (or any write command) recomputes them. Hand-editing them is a §13 violation. -- **It does not hand-edit entries.** `note` / `set-status` / `new` (cli-3.39.0+) are the write path; hand-editing a CLI-parsed registry is what those verbs exist to replace. +- **It does not hand-edit entries.** `note` / `set-status` / `new` (cli-3.39.0+) and `declare` (cli-3.49.0+) are the write path; hand-editing a CLI-parsed registry is what those verbs exist to replace. - **It does not promote without the operator.** `straymark followups promote` is proposed, never auto-run — prioritization and assignment stay human (`AGENT-RULES.md §3`). - **It does not delete `suspected-closed` entries.** The operator confirms (→ `closed`) or reopens them at the next triage. - **It does not re-scan AILOGs to answer "what's pending?"** when the registry exists — the registry is canonical; `drift` tells you when it is not trustworthy. diff --git a/dist/.qwen/skills/straymark-followups/SKILL.md b/dist/.qwen/skills/straymark-followups/SKILL.md index 3f9935f..04ff2d4 100644 --- a/dist/.qwen/skills/straymark-followups/SKILL.md +++ b/dist/.qwen/skills/straymark-followups/SKILL.md @@ -1,12 +1,12 @@ --- name: straymark-followups -description: Maintain the follow-ups backlog registry — the canonical answer to "what's pending?". Session-start glance, pre-commit drift --apply, post-Charter-close triage (note / set-status), ex-ante creation at Charter declaration (new), and operator-gated promote. Thin wrapper over the straymark followups CLI; never edits CLI-owned counters by hand. +description: Maintain the follow-ups backlog registry — the canonical answer to "what's pending?". Session-start glance, pre-commit drift --apply, post-Charter-close triage (note / set-status), ex-ante creation at Charter declaration (new), work-classification declaration (declare), and operator-gated promote. Thin wrapper over the straymark followups CLI; never edits CLI-owned counters by hand. allowed-tools: Read, Glob, Bash(git diff *, git log *, git status *, ls *, straymark followups *) --- # StrayMark Follow-ups Registry Skill -Maintain the central follow-ups registry (`.straymark/follow-ups-backlog.md`) — the first-class artifact that aggregates `§Follow-ups` and `R (new, not in Charter)` entries across AILOGs *(first-class since fw-4.21.0 / cli-3.19.0)*. The agent is the registry's **primary maintainer**; this skill drives the three directives of `AGENT-RULES.md §13` by delegating every mutation to the CLI (`straymark followups list/status/drift/note/set-status/new/promote`). The skill contains no extraction or counting logic of its own — parsing, schema validation, counter recomputation, and FU → TDE elevation all live in the CLI. +Maintain the central follow-ups registry (`.straymark/follow-ups-backlog.md`) — the first-class artifact that aggregates `§Follow-ups` and `R (new, not in Charter)` entries across AILOGs *(first-class since fw-4.21.0 / cli-3.19.0)*. The agent is the registry's **primary maintainer**; this skill drives the three directives of `AGENT-RULES.md §13` by delegating every mutation to the CLI (`straymark followups list/status/drift/note/set-status/new/declare/promote`). The skill contains no extraction or counting logic of its own — parsing, schema validation, counter recomputation, and FU → TDE elevation all live in the CLI. > See `.straymark/00-governance/FOLLOW-UPS-BACKLOG-PATTERN.md` and `STRAYMARK.md §16` for the pattern; `AGENT-RULES.md §13` for the shipped directives this skill wraps. @@ -78,6 +78,19 @@ straymark followups new --title "" \ The command prints the assigned `FU-NNN`. **Cite that id in the Charter body** — never a guessed id: the entry now exists, so a later `drift --apply` cannot hand the same number to a different entry. +### 3c. Declare the work classification (cli-3.49.0+) + +When an entry's kind of work is clear, declare it — the `Work verb` / `Design provenance` bullets are the signal Baton routes on (#332), and an undeclared entry routes conservatively to the frontier tier: + +```bash +straymark followups new … --work-verb implement --design-provenance new # at creation +straymark followups declare FU-NNN --work-verb audit # on an existing entry +``` + +- Vocabulary: `design | implement | audit | operate`. `--design-provenance new|upstream` only applies to `implement` (`upstream` = instrumenting a design already decided elsewhere, which routes as mechanical work). Defining a bounded foundational contract is `implement`, not `design`. +- `declare` writes the declaration **as a unit**: omitting `--design-provenance` removes a previous one. +- Leave an entry undeclared rather than guess. Never put a declaration in `Notes` — Baton does not read it there. + ### 4. Report result Surface the CLI output verbatim (counters, alerts, created TDE paths). Example after a pre-commit sync: @@ -93,7 +106,7 @@ StrayMark: registry synced — commit it together with the AILOG. ## What this skill does NOT do - **It does not edit the frontmatter counters** (`total_open`, `total_promoted`, `total_suspected_closed`, …). They are CLI-owned: `straymark followups recount` (or any write command) recomputes them. Hand-editing them is a §13 violation. -- **It does not hand-edit entries.** `note` / `set-status` / `new` (cli-3.39.0+) are the write path; hand-editing a CLI-parsed registry is what those verbs exist to replace. +- **It does not hand-edit entries.** `note` / `set-status` / `new` (cli-3.39.0+) and `declare` (cli-3.49.0+) are the write path; hand-editing a CLI-parsed registry is what those verbs exist to replace. - **It does not promote without the operator.** `straymark followups promote` is proposed, never auto-run — prioritization and assignment stay human (`AGENT-RULES.md §3`). - **It does not delete `suspected-closed` entries.** The operator confirms (→ `closed`) or reopens them at the next triage. - **It does not re-scan AILOGs to answer "what's pending?"** when the registry exists — the registry is canonical; `drift` tells you when it is not trustworthy. diff --git a/dist/.straymark/00-governance/AGENT-RULES.md b/dist/.straymark/00-governance/AGENT-RULES.md index b1c03be..66ad5ee 100644 --- a/dist/.straymark/00-governance/AGENT-RULES.md +++ b/dist/.straymark/00-governance/AGENT-RULES.md @@ -418,4 +418,4 @@ When a project accumulates a high volume of AILOGs across multiple Charters and --- -*StrayMark fw-4.44.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.45.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 cc5e6db..af74670 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.44.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.45.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 26de040..9ee30f2 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.44.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.45.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 d74c074..f53ae82 100644 --- a/dist/.straymark/00-governance/FOLLOW-UPS-BACKLOG-PATTERN.md +++ b/dist/.straymark/00-governance/FOLLOW-UPS-BACKLOG-PATTERN.md @@ -271,7 +271,8 @@ straymark followups promote FU-NNN [--premise-verified] # automate FU → TDE 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+) straymark followups note FU-NNN "" [--source CHARTER-NN|AILOG-…] # append a dated annotation to Notes (cli-3.39.0+) straymark followups set-status FU-NNN # change status AND recompute the counters in one step (cli-3.39.0+) -straymark followups new --title "..." --origin "CHARTER-NN §Scope" [--bucket …] [--cost …] [--trigger …] [--premise …] # create an entry declared ex-ante (cli-3.39.0+) +straymark followups new --title "..." --origin "CHARTER-NN §Scope" [--bucket …] [--cost …] [--trigger …] [--premise …] [--work-verb … [--design-provenance …]] # create an entry declared ex-ante (cli-3.39.0+; declaration flags cli-3.49.0+) +straymark followups declare FU-NNN --work-verb [--design-provenance new|upstream] # declare an entry's work classification (cli-3.49.0+) straymark followups merge-driver # git merge driver: structural registry merge (cli-3.41.0+) ``` @@ -285,7 +286,9 @@ straymark followups merge-driver # git merge driver: st - **`set-status`** writes the status and recomputes the counters in the same step. It refuses a status outside the vocabulary — the parser is lenient, so a typo would not fail, it would silently drop the entry from every counter — and redirects `promoted` to `followups promote`, which also writes the TDE that gives the status something to point at. - **`new`** creates an entry whose origin is a **Charter declaration** (`Origin-class: ex-ante-planning`). Both older population paths assume an ex-post origin: `drift --apply` extracts from AILOGs, and a deferral decided at declaration time precedes any AILOG by design. `new` assigns the id atomically and prints it, so the Charter body cites an entry that **exists** instead of a reserved guess that the next `drift --apply` could hand to a different entry. An ex-ante entry carries **no `Source-hash`**: there is no AILOG to hash, and inventing one would make a later `drift --apply` believe it had already extracted something it never saw. -All three refuse to write when the registry has parse warnings: a surgical edit against a structure the parser mis-read can corrupt neighbouring entries. `recount` remains the escape hatch for a bulk manual-triage session — and the idempotent check that these verbs got the arithmetic right. +- **`declare`** *(cli-3.49.0+)* writes an entry's declared work classification — the `Work verb` / `Design provenance` bullets Baton reads (#332) — which no verb could write before, so an adopter following "never hand-edit an entry" had no way to declare a follow-up. The vocabulary is validated (`design | implement | audit | operate`; provenance `new | upstream`, and only with `implement`), and the declaration is written **as a unit**: omitting `--design-provenance` removes a previous one rather than pairing a stale provenance with the new verb. `new` takes the same `--work-verb` / `--design-provenance` flags to declare an entry at creation. + +All four refuse to write when the registry has parse warnings: a surgical edit against a structure the parser mis-read can corrupt neighbouring entries. `recount` remains the escape hatch for a bulk manual-triage session — and the idempotent check that these verbs got the arithmetic right. 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`. @@ -370,4 +373,4 @@ Contributed via [issue #111](https://github.com/StrangeDaysTech/straymark/issues --- -*StrayMark fw-4.44.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.45.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 bddfa63..abc8013 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.44.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.45.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 1fda6e6..41d8728 100644 --- a/dist/.straymark/00-governance/i18n/es/AGENT-RULES.md +++ b/dist/.straymark/00-governance/i18n/es/AGENT-RULES.md @@ -418,4 +418,4 @@ Cuando un proyecto acumula un volumen alto de AILOGs a lo largo de múltiples Ch --- -*StrayMark fw-4.44.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.45.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 18ccb03..6a79e19 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.44.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.45.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 5e1f6c2..d2ff108 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.44.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.45.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 bd7abee..b90c720 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 @@ -269,7 +269,8 @@ straymark followups promote FU-NNN [--premise-verified] # automatiza la promoc 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+) straymark followups note FU-NNN "" [--source CHARTER-NN|AILOG-…] # anexa una anotación fechada a Notes (cli-3.39.0+) straymark followups set-status FU-NNN # cambia el status Y recomputa los contadores en un solo paso (cli-3.39.0+) -straymark followups new --title "..." --origin "CHARTER-NN §Scope" [--bucket …] [--cost …] [--trigger …] [--premise …] # crea una entrada declarada ex-ante (cli-3.39.0+) +straymark followups new --title "..." --origin "CHARTER-NN §Scope" [--bucket …] [--cost …] [--trigger …] [--premise …] [--work-verb … [--design-provenance …]] # crea una entrada declarada ex-ante (cli-3.39.0+; flags de declaración cli-3.49.0+) +straymark followups declare FU-NNN --work-verb [--design-provenance new|upstream] # declara la clasificación de trabajo de una entrada (cli-3.49.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. @@ -282,7 +283,9 @@ straymark followups new --title "..." --origin "CHARTER-NN §Scope" [--bucket - **`set-status`** escribe el status y recomputa los contadores en el mismo paso. Rechaza un status fuera del vocabulario — el parser es indulgente, así que un typo no fallaría: sacaría la entrada de todos los contadores en silencio — y redirige `promoted` a `followups promote`, que además escribe el TDE que le da a ese status algo a lo que apuntar. - **`new`** crea una entrada cuyo origen es una **declaración de Charter** (`Origin-class: ex-ante-planning`). Las dos rutas anteriores asumen origen ex-post: `drift --apply` extrae de AILOGs, y un diferimiento decidido en tiempo de declaración precede a cualquier AILOG por diseño. `new` asigna el id de forma atómica y lo imprime, así que el cuerpo del Charter cita una entrada que **existe** en vez de una reserva conjeturada que el siguiente `drift --apply` podría entregarle a otra entrada. Una entrada ex-ante no lleva **`Source-hash`**: no hay AILOG que hashear, e inventar uno haría que un `drift --apply` posterior creyera haber extraído algo que nunca vio. -Los tres se niegan a escribir si el registro tiene avisos de parseo: una edición quirúrgica contra una estructura mal leída puede corromper entradas vecinas. `recount` sigue siendo la vía de escape para una sesión de triage manual masivo — y el chequeo idempotente de que estos verbos hicieron bien la aritmética. +- **`declare`** *(cli-3.49.0+)* escribe la clasificación de trabajo declarada de una entrada: las líneas `Work verb` / `Design provenance` que lee Baton (#332). Antes ningún verbo podía escribirlas, así que un adoptante que respetaba "nunca edites una entrada a mano" no tenía forma de declarar un follow-up. El vocabulario se valida (`design | implement | audit | operate`; procedencia `new | upstream`, y solo con `implement`) y la declaración se escribe **como una unidad**: omitir `--design-provenance` elimina la anterior en lugar de emparejar una procedencia obsoleta con el verbo nuevo. `new` acepta los mismos flags `--work-verb` / `--design-provenance` para declarar la entrada al crearla. + +Los cuatro se niegan a escribir si el registro tiene avisos de parseo: una edición quirúrgica contra una estructura mal leída puede corromper entradas vecinas. `recount` sigue siendo la vía de escape para una sesión de triage manual masivo — y el chequeo idempotente de que estos verbos hicieron bien la aritmética. 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`. @@ -356,4 +359,4 @@ Contribuido vía [issue #111](https://github.com/StrangeDaysTech/straymark/issue --- -*StrayMark fw-4.44.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.45.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 6cbbdac..3e26cec 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.44.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.45.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 fec0527..f780b31 100644 --- a/dist/.straymark/00-governance/i18n/zh-CN/AGENT-RULES.md +++ b/dist/.straymark/00-governance/i18n/zh-CN/AGENT-RULES.md @@ -413,4 +413,4 @@ confidence: high | medium | low --- -*StrayMark fw-4.44.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.45.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 543121d..1532e26 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.44.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.45.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 71d4f85..44b2945 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.44.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.45.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 ef3e319..d3da7bd 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 @@ -269,7 +269,8 @@ straymark followups promote FU-NNN [--premise-verified] # 自动化 FU → TDE straymark followups verify FU-NNN [--premise "..."] [--verified] [--at 日期] # 在执行时重新验证一个有日期的假设:浮现/记录前提,盖上 Verified-at(cli-3.37.0+) straymark followups note FU-NNN "<文本>" [--source CHARTER-NN|AILOG-…] # 向 Notes 追加一条带日期的注记(cli-3.39.0+) straymark followups set-status FU-NNN # 修改状态**并**在同一步骤重算计数器(cli-3.39.0+) -straymark followups new --title "..." --origin "CHARTER-NN §Scope" [--bucket …] [--cost …] [--trigger …] [--premise …] # 创建一条事前(ex-ante)声明的条目(cli-3.39.0+) +straymark followups new --title "..." --origin "CHARTER-NN §Scope" [--bucket …] [--cost …] [--trigger …] [--premise …] [--work-verb … [--design-provenance …]] # 创建一条事前(ex-ante)声明的条目(cli-3.39.0+;声明类 flag 自 cli-3.49.0+) +straymark followups declare FU-NNN --work-verb [--design-provenance new|upstream] # 声明某条目的工作分类(cli-3.49.0+) ``` `verify` 与 `promote --premise-verified` 是"认识论地位"纪律的执行时可供性(affordance):它们在投入的那一刻把前提摆在操作员面前,并记录重新核查已经发生。人的判断留在 CLI 之外 —— 它浮现并盖印,从不裁定真伪。 @@ -282,7 +283,9 @@ straymark followups new --title "..." --origin "CHARTER-NN §Scope" [--bucket - **`set-status`** 在同一步骤写入状态并重算计数器。它拒绝词表之外的状态 —— 解析器是宽容的,所以一个拼写错误不会失败,而是会悄悄把该条目从所有计数器中剔除 —— 并把 `promoted` 重定向到 `followups promote`,后者还会写出让该状态有所指的 TDE。 - **`new`** 创建其来源为**Charter 声明**的条目(`Origin-class: ex-ante-planning`)。此前两条填充路径都假定来源是事后的:`drift --apply` 从 AILOG 中提取,而在声明时刻做出的推迟按设计先于任何 AILOG。`new` 原子地分配并打印 id,于是 Charter 正文引用的是一条**已存在**的条目,而不是下一次 `drift --apply` 可能分配给别的条目的预留猜测。事前条目**不携带 `Source-hash`**:没有 AILOG 可供哈希,而编造一个会让后续的 `drift --apply` 以为自己已经提取过它从未见过的东西。 -三者在注册表存在解析告警时都拒绝写入:针对被解析器误读的结构做手术式编辑,可能损坏相邻条目。`recount` 仍是批量手工 triage 的逃生通道 —— 也是这些动词算术是否正确的幂等校验。 +- **`declare`** *(cli-3.49.0+)* 写入条目声明的工作分类 —— 即 Baton 读取的 `Work verb` / `Design provenance` 两行(#332)。此前没有任何动词能写入它们,因此遵守"绝不手工编辑条目"的采用方无法声明一个 follow-up。词表会被校验(`design | implement | audit | operate`;provenance 为 `new | upstream`,且仅适用于 `implement`),并且声明**作为一个整体**写入:省略 `--design-provenance` 会删除先前的值,而不是让过时的 provenance 与新的 verb 配对。`new` 接受同样的 `--work-verb` / `--design-provenance` flag,可在创建时声明条目。 + +四者在注册表存在解析告警时都拒绝写入:针对被解析器误读的结构做手术式编辑,可能损坏相邻条目。`recount` 仍是批量手工 triage 的逃生通道 —— 也是这些动词算术是否正确的幂等校验。 注册表也在 `straymark explore` TUI 中作为一个合成的 **Follow-ups** 分组出现(每个 bucket 一个子节点),并在 `straymark status` 中作为一个计数块出现。 @@ -356,4 +359,4 @@ straymark followups new --title "..." --origin "CHARTER-NN §Scope" [--bucket --- -*StrayMark fw-4.44.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.45.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 b185e2f..0eb3301 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.44.0 | [Strange Days Tech](https://strangedays.tech)* +*StrayMark fw-4.45.0 | [Strange Days Tech](https://strangedays.tech)* diff --git a/dist/.straymark/templates/follow-ups-backlog.md b/dist/.straymark/templates/follow-ups-backlog.md index 8fa4724..ba3906a 100644 --- a/dist/.straymark/templates/follow-ups-backlog.md +++ b/dist/.straymark/templates/follow-ups-backlog.md @@ -50,8 +50,10 @@ cheap moment — not at capture: `straymark followups verify FU-NNN --verified` Never hand-edit an entry: `straymark followups note FU-NNN ""` appends a dated annotation, `straymark followups set-status FU-NNN ` flips the status and recomputes the counters in the same step (no `recount` to forget), -and `straymark followups new` creates one with an atomically-assigned id. A -hand-edit can malform an entry and break `list`/`status`/`drift`. +`straymark followups new` creates one with an atomically-assigned id (with +`--work-verb` / `--design-provenance` to declare it), and `straymark followups +declare FU-NNN --work-verb ` declares an existing one. A hand-edit can +malform an entry and break `list`/`status`/`drift`. --> ## Bucket: ready diff --git a/dist/dist-manifest.yml b/dist/dist-manifest.yml index 51cc86a..b0c07b5 100644 --- a/dist/dist-manifest.yml +++ b/dist/dist-manifest.yml @@ -1,4 +1,4 @@ -version: "4.44.0" +version: "4.45.0" description: "StrayMark distribution manifest" repository: "https://github.com/StrangeDaysTech/straymark" diff --git a/docs/adopters/BATON.md b/docs/adopters/BATON.md index e6fa1c5..4f4636d 100644 --- a/docs/adopters/BATON.md +++ b/docs/adopters/BATON.md @@ -22,7 +22,7 @@ Forward-validation (gate #3 for graduating Baton) needs real governance traffic. 1. **Declare the work class** on new units, exactly as documented in the [CLI Reference](./CLI-REFERENCE.md#straymark-validate): - Charter frontmatter: `work_verb: design | implement | audit | operate` and, only when significant for `implement`, `design_provenance: new | upstream`. - - Follow-up backlog entries: the same optional fields. + - Follow-up backlog entries: the same optional fields, written with `straymark followups declare FU-NNN --work-verb …` or `followups new --work-verb …` *(cli-3.49.0+)* — never by hand-editing the registry. 2. **Work as usual.** Nothing else in your cadence changes; the fields are advisory and absence is silent. 3. **After 2–4 weeks**, run the simplified calibration protocol from the [adopter kit](https://github.com/StrangeDaysTech/straymark/blob/main/experiment-baton/07-track-c-adopter-kit.md) and report back (see [Adopter Feedback](./ADOPTER-FEEDBACK.md)). diff --git a/docs/adopters/CLI-REFERENCE.md b/docs/adopters/CLI-REFERENCE.md index 15e1abb..66a3357 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.44.0` | Templates (12 types), governance docs, directives, Charter template + schema | -| CLI | `cli-` | `cli-3.45.0` | The `straymark` binary | +| Framework | `fw-` | `fw-4.45.0` | Templates (12 types), governance docs, directives, Charter template + schema | +| CLI | `cli-` | `cli-3.49.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. @@ -968,6 +968,7 @@ Parsing is **lenient**: v0 registries (pre-fw-4.21.0) are read without errors; t - `straymark followups note` — append a dated annotation to an entry's `Notes` *(cli-3.39.0+)* - `straymark followups set-status` — change an entry's status and recompute the counters in one step *(cli-3.39.0+)* - `straymark followups new` — create an entry declared **ex-ante**, at Charter-declaration time *(cli-3.39.0+)* +- `straymark followups declare` — declare an entry's work classification (`Work verb` / `Design provenance`, Baton #332) *(cli-3.49.0+)* - `straymark followups merge-driver` — git merge driver that resolves registry conflicts structurally (#391) *(cli-3.41.0+)* #### `straymark followups list [--bucket ] [--status ] [--severity ] [--label ] [path]` @@ -1113,7 +1114,7 @@ echo '.straymark/follow-ups-backlog.md merge=straymark-followups' >> .gitattribu git config merge.straymark-followups.driver 'straymark followups merge-driver %O %A %B' ``` -#### `straymark followups new --title --origin <origin> [--bucket <name>] [--status <s>] [--trigger <t>] [--destination <d>] [--cost <c>] [--premise <p>] [--path <dir>]` *(cli-3.39.0+)* +#### `straymark followups new --title <title> --origin <origin> [--bucket <name>] [--status <s>] [--trigger <t>] [--destination <d>] [--cost <c>] [--work-verb <v> [--design-provenance <p>]] [--premise <p>] [--path <dir>]` *(cli-3.39.0+; declaration flags cli-3.49.0+)* Create an entry whose origin is a **Charter declaration** (ex-ante), before any execution exists (#360). Both older population paths assume an ex-post origin: `drift --apply` extracts from AILOGs, and a deferral decided *at declaration time* — "the Redis CI job is out of scope; register the coverage gap so it is deferred, not silenced" — precedes any AILOG by design. @@ -1127,6 +1128,8 @@ The hazard this closes is correctness, not ergonomics. Lacking a creation verb, | `--status <s>` | `open` | Initial status. | | `--trigger` / `--destination` / `--cost` | `TBD` | The usual entry fields; unset ones are written as `TBD`, matching the template's convention. | | `--premise <p>` | — | The load-bearing assumption the entry rests on, so acting on it later is a seconds-long re-check. | +| `--work-verb <v>` *(cli-3.49.0+)* | — | Declared work classification: `design` · `implement` · `audit` · `operate`. Omit to leave the entry undeclared. See `followups declare` below. | +| `--design-provenance <p>` *(cli-3.49.0+)* | — | `new` · `upstream`, only with `--work-verb implement`. | The entry is written with `Origin-class: ex-ante-planning` and **no `Source-hash`**: there is no AILOG to hash, and inventing one would make a later `drift --apply` believe it had already extracted something it never saw. @@ -1138,7 +1141,22 @@ $ straymark followups new --title "Redis CI job deferred" --origin "CHARTER-06 Next: the id is assigned and written — cite FU-012 in the Charter body now, not a reserved guess. ``` -> **All three refuse to write a registry with parse warnings.** A surgical edit against a structure the parser mis-read can corrupt neighbouring entries, so a malformed entry must be fixed first. `recount` remains the escape hatch for a bulk manual-triage session — and the idempotent check that these verbs got the arithmetic right. +#### `straymark followups declare <FU-NNN> --work-verb <v> [--design-provenance <p>] [--path <dir>]` *(cli-3.49.0+)* + +Write an existing entry's **declared work classification**: the `Work verb` / `Design provenance` bullets that Baton's cost-aware router reads (#332). Before this verb, nothing could write them. `new` had no flags for them, `note` only appends to `Notes` (which Baton does not read), and `drift --apply` extracts entries without them. An adopter following "never hand-edit an entry" therefore had no supported way to declare a follow-up (#432). + +- **Validated vocabulary.** `--work-verb` takes `design` · `implement` · `audit` · `operate`. `--design-provenance` takes `new` · `upstream` and is accepted only with `implement`: it says whether the design being implemented is new or already decided upstream, and `upstream` routes as mechanical work. Invalid input is refused and nothing is written. +- **Written as a unit.** Both bullets are replaced together, where the old ones were or else right after `Cost`, as in the template. Omitting `--design-provenance` **removes** a previous provenance, so a stale one never pairs with a new verb. Re-declaring the same value is a no-op. +- Counters are unaffected, but the write still goes through the same recount path as every other verb. + +```bash +$ straymark followups declare FU-012 --work-verb implement --design-provenance new +✓ FU-012: undeclared → implement / new +``` + +`straymark followups status FU-NNN` shows the declaration. `straymark validate` keeps warning (advisory) on a declared value outside the vocabulary. Since cli-3.49.0 it ignores the registry's commented format example (#431). + +> **All four refuse to write a registry with parse warnings.** A surgical edit against a structure the parser mis-read can corrupt neighbouring entries, so a malformed entry must be fixed first. `recount` remains the escape hatch for a bulk manual-triage session — and the idempotent check that these verbs got the arithmetic right. --- diff --git a/docs/i18n/es/README.md b/docs/i18n/es/README.md index 58cb10a..dbd5922 100644 --- a/docs/i18n/es/README.md +++ b/docs/i18n/es/README.md @@ -241,8 +241,8 @@ StrayMark usa tags de versión independientes para cada componente: | Componente | Prefijo de tag | Ejemplo | Incluye | |------------|---------------|---------|---------| -| Framework | `fw-` | `fw-4.44.0` | Plantillas (12 tipos), gobernanza, directivas, plantilla + schema de Charter | -| CLI | `cli-` | `cli-3.45.0` | El binario `straymark` | +| Framework | `fw-` | `fw-4.45.0` | Plantillas (12 tipos), gobernanza, directivas, plantilla + schema de Charter | +| CLI | `cli-` | `cli-3.49.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/BATON.md b/docs/i18n/es/adopters/BATON.md index 045655e..354e92f 100644 --- a/docs/i18n/es/adopters/BATON.md +++ b/docs/i18n/es/adopters/BATON.md @@ -22,7 +22,7 @@ La validación prospectiva (gate #3 para graduar Baton) necesita tráfico real d 1. **Declara la clase de trabajo** en unidades nuevas, exactamente como documenta la [Referencia de CLI](./CLI-REFERENCE.md#straymark-validate): - Frontmatter del Charter: `work_verb: design | implement | audit | operate` y, solo cuando importa para `implement`, `design_provenance: new | upstream`. - - Entradas del backlog de follow-ups: los mismos campos opcionales. + - Entradas del backlog de follow-ups: los mismos campos opcionales, escritos con `straymark followups declare FU-NNN --work-verb …` o `followups new --work-verb …` *(cli-3.49.0+)* — nunca editando el registro a mano. 2. **Trabaja como siempre.** Nada más de tu cadencia cambia; los campos son advisory y la ausencia es silenciosa. 3. **Tras 2–4 semanas**, corre el protocolo de calibración simplificado del [kit del adoptante](https://github.com/StrangeDaysTech/straymark/blob/main/experiment-baton/07-track-c-adopter-kit.md) y reporta (ver [Adopter Feedback](./ADOPTER-FEEDBACK.md)). diff --git a/docs/i18n/es/adopters/CLI-REFERENCE.md b/docs/i18n/es/adopters/CLI-REFERENCE.md index e2fa8c0..fbe0967 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.44.0` | Plantillas (12 tipos), docs de gobernanza, directivas | -| CLI | `cli-` | `cli-3.45.0` | El binario `straymark` | +| Framework | `fw-` | `fw-4.45.0` | Plantillas (12 tipos), docs de gobernanza, directivas | +| CLI | `cli-` | `cli-3.49.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. @@ -771,6 +771,7 @@ El parsing es **tolerante**: los registros v0 (pre-fw-4.21.0) se leen sin errore - `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 merge-driver` — merge driver de git que resuelve conflictos del registro estructuralmente (#391) *(cli-3.41.0+)* +- `straymark followups declare` — declara la clasificación de trabajo de una entrada (`Work verb` / `Design provenance`, Baton #332) *(cli-3.49.0+)* #### `straymark followups list [--bucket <name>] [--status <s>] [--severity <s>] [--label <tag>] [path]` @@ -903,15 +904,29 @@ echo '.straymark/follow-ups-backlog.md merge=straymark-followups' >> .gitattribu git config merge.straymark-followups.driver 'straymark followups merge-driver %O %A %B' ``` -#### `straymark followups new --title <título> --origin <origen> [--bucket <name>] [--status <s>] [--trigger <t>] [--destination <d>] [--cost <c>] [--premise <p>] [--path <dir>]` *(cli-3.39.0+)* +#### `straymark followups new --title <título> --origin <origen> [--bucket <name>] [--status <s>] [--trigger <t>] [--destination <d>] [--cost <c>] [--work-verb <v> [--design-provenance <p>]] [--premise <p>] [--path <dir>]` *(cli-3.39.0+; flags de declaración cli-3.49.0+)* Crea una entrada cuyo origen es una **declaración de Charter** (ex-ante), antes de que exista ejecución alguna (#360). Las dos rutas de poblado anteriores asumen origen ex-post: `drift --apply` extrae de AILOGs, y un diferimiento decidido *en tiempo de declaración* — "el job de CI de Redis queda fuera de alcance; registra el hueco de cobertura para que quede diferido, no silenciado" — precede a cualquier AILOG por diseño. El riesgo que cierra es de corrección, no de ergonomía. A falta de un verbo de creación, el adoptante que lo reportó forward-referenció `FU-011` en el cuerpo del Charter sin nada que lo reservara; y como los ids se acuñan `max(existente) + 1` en tiempo de extracción, el siguiente `drift --apply` no relacionado le daría `FU-011` a otra entrada, apuntando en silencio las citas del Charter al follow-up equivocado. `new` asigna el id de forma atómica y lo imprime, así que cuando el Charter lo cita la entrada ya existe. -La entrada se escribe con `Origin-class: ex-ante-planning` y **sin `Source-hash`**: no hay AILOG que hashear, e inventar uno haría que un `drift --apply` posterior creyera haber extraído algo que nunca vio. +La entrada se escribe con `Origin-class: ex-ante-planning` y **sin `Source-hash`**: no hay AILOG que hashear, e inventar uno haría que un `drift --apply` posterior creyera haber extraído algo que nunca vio. Con `--work-verb` (y `--design-provenance`, solo junto a `implement`) la entrada nace declarada; el vocabulario se valida igual que en `followups declare`. -> **Los tres se niegan a escribir un registro con avisos de parseo.** Una edición quirúrgica contra una estructura mal leída puede corromper entradas vecinas, así que primero hay que arreglar la entrada malformada. `recount` sigue siendo la vía de escape para una sesión de triage manual masivo — y el chequeo idempotente de que estos verbos hicieron bien la aritmética. +#### `straymark followups declare <FU-NNN> --work-verb <v> [--design-provenance <p>] [--path <dir>]` *(cli-3.49.0+)* + +Escribe la **clasificación de trabajo declarada** de una entrada existente: las líneas `Work verb` / `Design provenance` que lee el router de Baton (#332). Antes ningún verbo podía escribirlas. `new` no tenía flags para ellas, `note` solo añade a `Notes` (que Baton no lee) y `drift --apply` extrae sin ellas. Un adoptante que respetaba "nunca edites una entrada a mano" no tenía, por tanto, una vía soportada para declarar un follow-up (#432). + +- **Vocabulario validado.** `--work-verb` acepta `design` · `implement` · `audit` · `operate`. `--design-provenance` acepta `new` · `upstream` y solo se admite con `implement`: indica si el diseño que se implementa es nuevo o ya se decidió aguas arriba, y `upstream` se rutea como trabajo mecánico. Una entrada inválida se rechaza y no se escribe nada. +- **Se escribe como unidad.** Ambas líneas se reemplazan juntas, donde estaban o, si no, justo después de `Cost`, como en la plantilla. Omitir `--design-provenance` **elimina** una procedencia anterior, para que nunca quede una obsoleta emparejada con un verbo nuevo. Volver a declarar el mismo valor no hace nada. + +```bash +$ straymark followups declare FU-012 --work-verb implement --design-provenance new +✓ FU-012: undeclared → implement / new +``` + +`straymark followups status FU-NNN` muestra la declaración. `straymark validate` sigue avisando (de forma consultiva) ante un valor fuera del vocabulario. Desde cli-3.49.0 ignora el ejemplo de formato comentado del registro (#431). + +> **Los cuatro se niegan a escribir un registro con avisos de parseo.** Una edición quirúrgica contra una estructura mal leída puede corromper entradas vecinas, así que primero hay que arreglar la entrada malformada. `recount` sigue siendo la vía de escape para una sesión de triage manual masivo — y el chequeo idempotente de que estos verbos hicieron bien la aritmética. --- diff --git a/docs/i18n/zh-CN/README.md b/docs/i18n/zh-CN/README.md index 44959bc..9989cfe 100644 --- a/docs/i18n/zh-CN/README.md +++ b/docs/i18n/zh-CN/README.md @@ -259,8 +259,8 @@ StrayMark 为每个组件使用独立的版本标签: | 组件 | 标签前缀 | 示例 | 包含内容 | |------|----------|------|----------| -| Framework | `fw-` | `fw-4.44.0` | 模板(12 种类型)、治理文档、指令、Charter 模板 + schema | -| CLI | `cli-` | `cli-3.45.0` | `straymark` 二进制文件 | +| Framework | `fw-` | `fw-4.45.0` | 模板(12 种类型)、治理文档、指令、Charter 模板 + schema | +| CLI | `cli-` | `cli-3.49.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/BATON.md b/docs/i18n/zh-CN/adopters/BATON.md index 65e47d6..ab50633 100644 --- a/docs/i18n/zh-CN/adopters/BATON.md +++ b/docs/i18n/zh-CN/adopters/BATON.md @@ -22,7 +22,7 @@ Baton 是 StrayMark 的实验性 **Coherence Bridge**:它对照治理与代码 1. **在新单元上声明工作类别**,与 [CLI 参考](./CLI-REFERENCE.md#straymark-validate) 中的文档完全一致: - Charter frontmatter:`work_verb: design | implement | audit | operate`,以及仅当对 `implement` 有意义时的 `design_provenance: new | upstream`。 - - follow-up backlog 条目:相同的可选字段。 + - follow-up backlog 条目:相同的可选字段,通过 `straymark followups declare FU-NNN --work-verb …` 或 `followups new --work-verb …` 写入 *(cli-3.49.0+)* —— 切勿手工编辑注册表。 2. **照常工作。** 你的节奏没有任何其他变化;这些字段只是建议性的,缺省时完全静默。 3. **2–4 周后**,按[采纳者工具包](https://github.com/StrangeDaysTech/straymark/blob/main/experiment-baton/07-track-c-adopter-kit.md)中的简化校准协议执行并反馈(见 [Adopter Feedback](./ADOPTER-FEEDBACK.md))。 diff --git a/docs/i18n/zh-CN/adopters/CLI-REFERENCE.md b/docs/i18n/zh-CN/adopters/CLI-REFERENCE.md index e799652..bea74b5 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.44.0` | 模板(12 种类型)、治理文档、指令 | -| CLI | `cli-` | `cli-3.45.0` | `straymark` 二进制文件 | +| Framework | `fw-` | `fw-4.45.0` | 模板(12 种类型)、治理文档、指令 | +| CLI | `cli-` | `cli-3.49.0` | `straymark` 二进制文件 | | Loom(实验性) | `loom-` | `loom-0.4.2` | `straymark-loom` 可视化服务器,由 `straymark loom serve` 按需下载 | Framework 和 CLI 独立发布。Framework 更新不需要 CLI 更新,反之亦然。 @@ -814,6 +814,7 @@ $ straymark charter audit CHARTER-05 --finalize - `straymark followups promote` — 将条目提升为 TDE 文档 *(cli-3.19.0+)* - `straymark followups verify` — 在执行时重新验证一个有日期假设的前提 *(cli-3.37.0+)* - `straymark followups merge-driver` — 以结构化方式解决注册表冲突的 git merge driver(#391)*(cli-3.41.0+)* +- `straymark followups declare` — 声明条目的工作分类(`Work verb` / `Design provenance`,Baton #332)*(cli-3.49.0+)* #### `straymark followups list [--bucket <name>] [--status <s>] [--severity <s>] [--label <tag>] [path]` @@ -946,15 +947,29 @@ echo '.straymark/follow-ups-backlog.md merge=straymark-followups' >> .gitattribu git config merge.straymark-followups.driver 'straymark followups merge-driver %O %A %B' ``` -#### `straymark followups new --title <标题> --origin <来源> [--bucket <name>] [--status <s>] [--trigger <t>] [--destination <d>] [--cost <c>] [--premise <p>] [--path <dir>]` *(cli-3.39.0+)* +#### `straymark followups new --title <标题> --origin <来源> [--bucket <name>] [--status <s>] [--trigger <t>] [--destination <d>] [--cost <c>] [--work-verb <v> [--design-provenance <p>]] [--premise <p>] [--path <dir>]` *(cli-3.39.0+;声明类 flag 自 cli-3.49.0+)* 创建来源为**Charter 声明**(事前)的条目,此时尚不存在任何执行(#360)。此前两条填充路径都假定来源是事后的:`drift --apply` 从 AILOG 提取,而在**声明时刻**做出的推迟 —— "Redis 的 CI job 不在范围内;登记这个覆盖缺口,使其被推迟而非被消音" —— 按设计先于任何 AILOG。 它关闭的是正确性风险,而非人机工程问题。由于缺少创建动词,提交该报告的采用方在 Charter 正文中前向引用了 `FU-011`,却没有任何东西为其预留;而 id 是在提取时按 `max(既有) + 1` 铸造的,于是下一次无关的 `drift --apply` 会把 `FU-011` 分配给别的条目,悄悄让 Charter 的引用指向错误的 follow-up。`new` 原子地分配并打印 id,因此当 Charter 引用它时该条目已经存在。 -该条目写入时带 `Origin-class: ex-ante-planning` 且**不带 `Source-hash`**:没有 AILOG 可供哈希,而编造一个会让后续的 `drift --apply` 以为自己已经提取过它从未见过的东西。 +该条目写入时带 `Origin-class: ex-ante-planning` 且**不带 `Source-hash`**:没有 AILOG 可供哈希,而编造一个会让后续的 `drift --apply` 以为自己已经提取过它从未见过的东西。使用 `--work-verb`(以及仅与 `implement` 搭配的 `--design-provenance`)可在创建时直接声明该条目;词表校验与 `followups declare` 相同。 -> **三者都拒绝写入存在解析告警的注册表。** 针对被解析器误读的结构做手术式编辑可能损坏相邻条目,因此必须先修好变形的条目。`recount` 仍是批量手工 triage 的逃生通道 —— 也是这些动词算术是否正确的幂等校验。 +#### `straymark followups declare <FU-NNN> --work-verb <v> [--design-provenance <p>] [--path <dir>]` *(cli-3.49.0+)* + +为已有条目写入**声明的工作分类**:即 Baton 成本感知路由器读取的 `Work verb` / `Design provenance` 两行(#332)。此前没有任何动词能写入它们:`new` 没有对应的 flag,`note` 只追加到 `Notes`(Baton 不读取该字段),`drift --apply` 提取时也不带它们。因此遵守"绝不手工编辑条目"的采用方没有受支持的方式来声明一个 follow-up(#432)。 + +- **词表会被校验。** `--work-verb` 接受 `design` · `implement` · `audit` · `operate`。`--design-provenance` 接受 `new` · `upstream`,且只能与 `implement` 一起使用:它说明所实现的设计是新的,还是已在上游确定;`upstream` 按机械性工作路由。无效输入会被拒绝,且不会写入任何内容。 +- **作为整体写入。** 两行一起替换:写在原先的位置,若原先没有,则紧跟在 `Cost` 之后(与模板一致)。省略 `--design-provenance` 会**删除**先前的 provenance,使过时的值不会与新的 verb 配对。重复声明相同的值不会做任何改动。 + +```bash +$ straymark followups declare FU-012 --work-verb implement --design-provenance new +✓ FU-012: undeclared → implement / new +``` + +`straymark followups status FU-NNN` 会显示该声明。对于词表之外的声明值,`straymark validate` 仍会给出(建议性)告警;自 cli-3.49.0 起,它会忽略注册表中被注释掉的格式示例(#431)。 + +> **四者都拒绝写入存在解析告警的注册表。** 针对被解析器误读的结构做手术式编辑可能损坏相邻条目,因此必须先修好变形的条目。`recount` 仍是批量手工 triage 的逃生通道 —— 也是这些动词算术是否正确的幂等校验。 --- diff --git a/experiment-baton/07-track-c-adopter-kit.md b/experiment-baton/07-track-c-adopter-kit.md index d88df6d..63fc14e 100644 --- a/experiment-baton/07-track-c-adopter-kit.md +++ b/experiment-baton/07-track-c-adopter-kit.md @@ -61,7 +61,7 @@ descomentar y llenar: |---|---| | Charter | Frontmatter: `work_verb:` / `design_provenance:` | | Batch (AILOG ledger) | Línea `- **Work verb**:` en la entrada del batch; placement ratificado, aún pendiente en el inventario (#428) | -| Follow-up | Líneas `- **Work verb**:` / `- **Design provenance**:` | +| Follow-up | Líneas `- **Work verb**:` / `- **Design provenance**:`, escritas con `straymark followups declare FU-NNN --work-verb …` o con `followups new --work-verb …` (cli-3.49.0+; nunca a mano ni en `Notes`) | | Task (SpecKit) | Sin slot propio — hereda de los Charters cuyo `originating_spec` resuelve al `spec.md` hermano, si todos declaran lo mismo; vínculo ausente o discrepante → `undeclared` | ### Vocabulario y reglas de decisión (resumen de la ratificación)