From 116d2d73037f3067c0e7b3e57a13179d63e22e35 Mon Sep 17 00:00:00 2001 From: Maxim Svistunov Date: Tue, 5 May 2026 15:05:52 +0200 Subject: [PATCH 1/5] LCORE-1736: add feature design configuration files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a two-tier configuration for the feature design process: - docs/contributing/feature-design.config — team-policy conventions (mostly read-only for individual contributors). Defines section inclusion (yes / no / if_applicable), naming patterns, branching policy, decision-presentation cadence, PoC behavior, JIRA conventions including the e2e-kickoff + step-definitions defaults, reviewer defaults (@sbunciak strategic, @tisnik technical), config-application UX, and the new remind_about_google_doc_after_merge setting. - .feature-design.config.local.example — template for per-developer overrides. The actual .feature-design.config.local at the repo root is gitignored. Settings unset locally fall through to the team file. The third value `if_applicable` joins `yes`/`no` for include flags. It signals "the agent decides based on whether the feature actually has this concern" — useful for sections like security, observability, capacity planning, latency/cost, etc. --- .feature-design.config.local.example | 31 +++++ .gitignore | 4 +- docs/contributing/feature-design.config | 175 ++++++++++++++++++++++++ 3 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 .feature-design.config.local.example create mode 100644 docs/contributing/feature-design.config diff --git a/.feature-design.config.local.example b/.feature-design.config.local.example new file mode 100644 index 000000000..868239461 --- /dev/null +++ b/.feature-design.config.local.example @@ -0,0 +1,31 @@ +# Feature design — personal overrides (example) +# ============================================================================= +# +# Copy this file to `.feature-design.config.local` (gitignored) and override +# any setting from `docs/contributing/feature-design.config`. Keys you don't +# set fall through to the team policy. +# +# Suitable per-dev overrides include: +# - pr_template_output_path (where you keep PR-body drafts) +# - default_poc_ambition (some prefer minimal, some ambitious) +# - decision_presentation_cadence (some prefer everything per_decision) +# - confidence_format (numeric vs qualitative preference) +# +# Settings you should NOT override here (they're conventions, not preferences): +# - feature_dir, *_filename, jira_dir_path, ticket_placeholder_format +# - require_e2e_kickoff_jira, require_e2e_step_definitions_jira +# - default_strategic_reviewer, default_technical_reviewer +# - any include_*_section setting that's part of the team's doc shape + +# Example: keep PR-body drafts in your home dir instead of /tmp. +# pr_template_output_path = ~/work/pr-drafts/{prefix}-{ticket}-pr.txt + +# Example: prefer to be asked at every decision (strategic + technical) +# rather than batching technical decisions. +# decision_presentation_cadence = per_decision + +# Example: use qualitative confidence labels instead of percentages. +# confidence_format = qualitative + +# Example: less ambitious PoCs by default. +# default_poc_ambition = moderate diff --git a/.gitignore b/.gitignore index 75e21dc91..0910a547b 100644 --- a/.gitignore +++ b/.gitignore @@ -196,4 +196,6 @@ requirements.*.backup local-run.yaml # Sisyphus planning files -.sisyphus/ \ No newline at end of file +.sisyphus/ +# Per-developer feature design overrides (see docs/contributing/feature-design.config) +.feature-design.config.local diff --git a/docs/contributing/feature-design.config b/docs/contributing/feature-design.config new file mode 100644 index 000000000..6511251e4 --- /dev/null +++ b/docs/contributing/feature-design.config @@ -0,0 +1,175 @@ +# Feature design — team policy configuration +# ============================================================================= +# +# This file defines the team-level conventions for the feature design process +# (spikes, spec docs, JIRA filing). Skills (`/spike`, `/spec-doc`, +# `/spike-finalize`, `/file-jiras`) and templates honor these settings. +# +# Individual contributors should NOT change settings here. Personal +# preferences go in `.feature-design.config.local` (gitignored) and override +# values from this file. +# +# Format: plaintext, freeform, LLM-readable. `key = value` with `#` comments. +# Three-valued booleans (`yes`/`no`/`if_applicable`) are preferred over plain +# `yes`/`no` where relevant. `if_applicable` means the agent decides based on +# whether the feature actually has the concern in question. +# +# When a skill starts, it should announce which config files it read so that +# devs can find this file. See `R. Config-application UX` below. + +# ─── A. Paths & naming ───────────────────────────────────────────────────── +# All feature design artifacts (spike doc, spec doc, PoC results, JIRAs) +# live under one feature directory. Filenames mirror the feature name. + +feature_dir = docs/design/{feature}/ +spike_doc_filename = {feature}-spike.md +spec_doc_filename = {feature}.md +poc_dir_name = poc-results +jira_dir_path = {feature_dir}/jiras/ +ticket_placeholder_format = LCORE-???? +default_project_prefix = LCORE +ticket_browse_url_format = https://redhat.atlassian.net/browse/{key} +github_branch_link_format = https://github.com/{user}/{repo}/blob/{branch}/{path}?plain=1#L{start}-L{end} + +# ─── B. Branching ────────────────────────────────────────────────────────── + +branch_off = upstream/main +branch_name_pattern = lcore-{ticket}-spike-{slug} +auto_fetch_upstream_before_branch = yes +on_dirty_working_tree = ask # ask | worktree | move_aside | stop +worktree_path_pattern = ../stack.worktrees/{branch} +move_aside_path_pattern = ../stack-wip-stash/{description}/ + +# ─── C. Spike doc — sections ─────────────────────────────────────────────── +# Required sections are always present. `if_applicable` sections are added +# by the agent based on whether the feature actually has that concern. + +require_overview_section = yes +require_decisions_section = yes +require_proposed_jiras_section = yes + +include_strategic_decisions_section = yes +include_technical_decisions_section = yes +include_stakeholder_decisions_section = if_applicable # when feature originated from a named team +include_out_of_scope_section = yes +include_poc_findings_section = if_applicable # surprises discovered while building the PoC +include_incidental_findings_section = if_applicable # unrelated bugs noticed during the spike +include_proposed_incidental_jiras_section = if_applicable # filings for incidental findings +include_external_input_section = if_applicable # items needing input from outside the team +include_appendix_files_changed = if_applicable +include_appendix_repro_commands = if_applicable +include_glossary = if_applicable + +# ─── D. Spike doc — content rules ────────────────────────────────────────── + +confidence_format = numeric # numeric (e.g., "75%") | qualitative (Low/Med/High) | none +require_confidence_per_recommendation = yes # each recommendation must state its confidence +options_table_required_per_decision = yes # at least 2 options compared per decision +proposed_jira_ordering = dependency_first # dependency_first | by_subsystem | as_authored +require_e2e_kickoff_jira = yes # the "feature files first, no impl" Story +e2e_kickoff_position = first +require_e2e_step_definitions_jira = yes # the counterpart Task; blocked-by the kickoff + impl tickets +default_jira_type = Task # Task | Story +incidental_findings_become_separate_jiras = yes + +# ─── E. Spec doc — structural (always-on or always-required) ─────────────── + +require_what_section = yes +require_why_section = yes +require_requirements_section = yes +require_use_cases_section = yes +require_architecture_section = yes +require_implementation_suggestions = yes +include_open_questions = yes +include_changelog = yes +include_acceptance_test_surface = yes # feeds the e2e-kickoff JIRA + +# ─── F. Spec doc — aspect sections (per-feature concerns) ────────────────── +# These are concerns that may or may not apply to a given feature. The agent +# decides whether to include based on whether the feature actually has the +# concern. + +include_latency_and_cost_section = if_applicable +include_observability_section = if_applicable +include_capacity_planning_section = if_applicable +include_failure_modes_section = if_applicable +include_security_considerations = if_applicable +include_migration_backcompat = if_applicable +include_telemetry_data_privacy_section = if_applicable +include_feature_flags_rollout_section = if_applicable +include_runbook_oncall_section = if_applicable +include_internationalization_section = if_applicable +include_api_versioning_section = if_applicable +include_rate_limiting_quotas_section = if_applicable + +# ─── F'. Spec doc — architecture sub-sections ────────────────────────────── + +arch_overview_with_diagram = yes +arch_trigger_mechanism = if_applicable +arch_storage_data_model = if_applicable +arch_configuration = if_applicable +arch_api_changes = if_applicable +arch_error_handling = if_applicable +arch_security_considerations = if_applicable +arch_migration_backcompat = if_applicable + +# ─── G. Spec doc — content rules ─────────────────────────────────────────── + +requirements_numbered_with_R_prefix = yes +use_cases_numbered_with_U_prefix = yes +open_questions_traceability_required = yes # each item links back to spike decision or PoC finding +spike_doc_link_in_metadata = yes +test_patterns_section_inline = yes # `no` would link to a project-conventions doc instead +require_feature_specific_test_section = yes + +# ─── H. Decision presentation cadence ────────────────────────────────────── + +decision_presentation_cadence = mixed # batch | per_decision | mixed + # mixed = per_decision for strategic, batch for technical + +# ─── I. PoC behavior ─────────────────────────────────────────────────────── + +default_poc_ambition = ambitious # minimal | moderate | ambitious | maximal +poc_validation_against_real_services = ask # always | never | ask +poc_findings_must_link_to_jira = yes +require_poc_readme = yes +remove_poc_dir_before_merge = ask # ask | yes | no (decided at /spike-finalize) + +# ─── J. Reviewer defaults ────────────────────────────────────────────────── + +default_strategic_reviewer = @sbunciak +default_technical_reviewer = @tisnik +review_link_format = github_branch_url_plain + +# ─── K. /spike-finalize skill behavior ───────────────────────────────────── + +auto_replace_jira_placeholders = yes # LCORE-???? → real keys after filing +verify_spike_spec_doc_drift = yes +verify_no_orphan_jira_references = yes +remind_about_google_doc_after_merge = yes # after spike+spec PR is merged, prompt to create Google Docs versions + +# ─── L. PR template ──────────────────────────────────────────────────────── + +pr_template_uses_branch_url = yes # `no` for commit URL +pr_template_includes_tools_used_section = yes +pr_template_includes_checklist = yes +pr_title_max_chars = 70 +include_pre_merge_cleanup_section = yes # what to remove from the branch before merging +pr_template_output_path = /tmp/{prefix}-{ticket}-pr-template.txt # dev-overridable + +# ─── M. Output style ─────────────────────────────────────────────────────── + +table_max_columns_for_chat = 6 # avoid horizontal scroll in narrow terminals +state_confidence_on_recommendations = yes + +# ─── R. Config-application UX ────────────────────────────────────────────── +# How the skill announces and applies this configuration at session start +# and during work. + +config_announcement_at_start = notable # silent | notable | full + # notable = list config files read, + # actively-honored non-default settings + # for the current task type, plus any + # items changed since last session. +agent_may_suggest_config_changes_during_work = yes # one-shot suggestions allowed mid-session +config_state_file = .claude/feature-design.last-seen # mtime+hash for change detection From 2860c0b0030bc76f7601c7bc07a1fd84dfaf10bd Mon Sep 17 00:00:00 2001 From: Maxim Svistunov Date: Tue, 5 May 2026 15:06:15 +0200 Subject: [PATCH 2/5] LCORE-1736: spike + spec doc templates and howtos honor the new config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apply the conventions from docs/contributing/feature-design.config to the templates, howtos, and the top-level contributing guide. Spike template (templates/spike-template.md): - Three audience sections (Strategic / Technical / Stakeholder); the Stakeholder section is `if_applicable` and removed when the feature did not originate from a named team. - Confidence required per recommendation (numeric or qualitative per config). - Out-of-scope section is required. - E2E kickoff Story (write feature files, no implementation) and step-definitions Task counterpart are pre-filled stubs as the first two proposed JIRAs (per `require_e2e_kickoff_jira` and `require_e2e_step_definitions_jira`). - New sections (`if_applicable`): PoC findings, incidental findings, proposed incidental JIRAs, external-input-needed, glossary. Spec doc template (templates/spec-doc-template.md): - Acceptance test surface section (always present) — feeds the e2e kickoff JIRA's feature-file authoring. - Aspect-specific concerns regrouped: Latency/Cost, Observability, Capacity planning, Failure modes, Security, Migration/backcompat, Telemetry/data privacy, Feature flags/rollout, Runbook/oncall, Internationalization, API versioning, Rate limiting/quotas — all `if_applicable`. - Architecture sub-sections (Trigger mechanism, Storage, Configuration, API changes, Error handling, Security, Migration) marked `if_applicable` rather than always-present. - Open Questions traceability requirement: each item must trace back to its origin (spike decision, PoC finding, or reviewer comment). Howtos: - howto-run-a-spike.md gains a Configuration paragraph, three-audience guidance, confidence and out-of-scope requirements, the e2e-kickoff convention, a new step 11 ("Finalize after merge") pointing at /spike-finalize, and an updated checklist. - howto-write-a-spec-doc.md gains a Configuration paragraph and describes the new Acceptance test surface and aspect-specific concerns sections; Open Questions traceability is documented. - howto-organize-poc-output.md is rewritten from a rigid numbered-file scheme to principles. Covers two common PoC shapes (code PoC vs data/experimental) without prescribing filenames. Top-level guide (docs/contributing_guide.md): - Adds step 6 (`/spike-finalize`) to the Feature design process flow. - Points readers at the new feature-design.config and .feature-design.config.local files. --- .../contributing/howto-organize-poc-output.md | 130 +++++++++---- docs/contributing/howto-run-a-spike.md | 58 +++++- docs/contributing/howto-write-a-spec-doc.md | 30 ++- .../templates/spec-doc-template.md | 88 +++++++-- docs/contributing/templates/spike-template.md | 176 ++++++++++++++++-- docs/contributing_guide.md | 12 ++ 6 files changed, 422 insertions(+), 72 deletions(-) diff --git a/docs/contributing/howto-organize-poc-output.md b/docs/contributing/howto-organize-poc-output.md index b22fe2dfd..9a7a3b180 100644 --- a/docs/contributing/howto-organize-poc-output.md +++ b/docs/contributing/howto-organize-poc-output.md @@ -1,53 +1,109 @@ # How to organize PoC output When a spike includes a proof-of-concept, the validation results should be -structured so that reviewers can quickly understand what was tested and what was -found. +structured so that reviewers can quickly understand what was tested and what +was found. This guide is intentionally **principles-first**, not +prescriptive about filenames — different PoC shapes warrant different +artifacts. Use the ones that fit; ignore the ones that don't. -## Directory structure +## Where it goes -Place results in `docs/design//poc-results/`. +Place results in `docs/design//poc-results/`. The directory is +expected to be removed before the spike PR is merged +(see [howto-run-a-spike.md](howto-run-a-spike.md), step 10); reviewers +read it during review and the spike doc preserves the salient findings. -Name files with a numeric prefix that reflects reading order. Order them by -usefulness for the human reviewer: +## Principles -```text -poc-results/ -├── 01-poc-report.txt — findings, methodology, implications -├── 02-conversation-log.txt — human-readable record of the PoC -├── 03-token-usage.txt — quantitative data -├── 04-events.json — structured event data -├── 05-summaries.txt — extracted outputs -├── ... -└── NN-raw-data.json — full machine-readable data -``` +1. **A reviewer reading nothing but a top-level report should grasp the + essentials.** Whatever you call this file (`README.md`, `01-poc-report.md`, + `summary.txt` — pick what fits), it must be the first thing a reviewer + opens, and it must stand alone. + +2. **Order files by usefulness for the human reviewer**, not by the order + you produced them. If naming conventions help (numeric prefixes, + descriptive names), use them — but don't reorder for the sake of + uniformity. + +3. **Separate human-readable summary from machine-readable raw data.** A + summary that interleaves prose findings with 50KB of raw JSON is + unreviewable. + +4. **Plain text where humans read; structured formats where machines read.** + Markdown / `.txt` for prose; `.json` / `.yaml` / `.csv` for data. + +5. **Show, don't just claim.** When a PoC proves "X works", include + evidence: command output, response payload, before/after diff, + screenshot, etc. + +6. **Cross-reference the spike doc.** Each significant finding in the + spike doc's "PoC results" or "Findings discovered during the PoC" + section should link back to a specific file in `poc-results/`. + +## Two common PoC shapes + +### Code PoC (mechanism validation) + +The PoC is code that demonstrates a mechanism end-to-end (e.g., a +synthesizer that produces a config file consumed by a downstream service). -Not all files apply to every PoC, use ones that make sense. +Typical artifacts: -## What a good report file contains +- **Top-level report** — what was tested, what worked, what surprised you +- **Sample input(s)** — the config file(s) the PoC was driven with +- **Sample output(s)** — what the code produced (synthesized files, API + responses, log excerpts) +- **Repro instructions** — exact commands to reproduce the PoC, with the + environment variables required -The report file (`01-poc-report.txt`) is the most important output. A -reviewer who reads only this file should understand everything significant. +### Data / experimental PoC -Include: +The PoC runs a controlled experiment and produces measurements (e.g., +quality of summarization across N queries with thresholds at +{3, 5, 10}). -- **Glossary**: Define terms specific to the PoC. -- **PoC design**: What was tested, how, what parameters. -- **Results**: What happened, with numbers. -- **Findings**: What the results mean for the production design — what was - proved, disproved, or surprising. -- **Implications**: How the findings influence the design decisions in the - spike doc and spec doc. +Typical artifacts: -## What NOT to include in the merge +- **Top-level report** — methodology, results, findings, implications for + the production design +- **Conversation / interaction log** — human-readable record of what + happened during the run +- **Quantitative data** — numbers (token usage, latency, accuracy) +- **Structured event data** — `.json` or `.csv` for downstream analysis +- **Extracted outputs** — model outputs, summaries, etc., as text + +## What a good top-level report contains + +Whatever its filename, it should include: + +- **Glossary**: terms specific to this PoC (omit if not needed). +- **Design**: what was tested, how, with what parameters. +- **Results**: what happened, with concrete numbers / outputs. +- **Findings**: what the results mean for the production design — what + was proved, disproved, or surprising. Each finding worth carrying + forward should also appear in the spike doc's "Findings discovered + during the PoC" section. +- **Implications**: how the findings change the recommended design or + proposed JIRAs. If a finding doesn't change anything, say so explicitly. + +## Multiple PoC runs + +If the PoC was run multiple times with different parameters, give each run +its own descriptive sub-directory: + +``` +poc-results/ +├── README.md # one report for the whole spike +├── run-5-queries/ +└── run-50-queries/ +``` -PoC results are removed before merging the spike PR (see -[howto-run-a-spike.md](howto-run-a-spike.md), step 10). They serve their -purpose during review and are preserved in git history. +Avoid timestamp-named sub-directories — they don't tell a reader what +varied between runs. -## Naming conventions +## Removed before merge -- Use plain English filenames, not timestamps or hashes. -- Prefer `.txt` for human-readable content, `.json` for structured data. -- If there are multiple PoC runs, use separate directories or name them - descriptively: `poc-results-5-query/`, `poc-results-50-query/`. +PoC results are removed from the branch before the spike PR is merged. They +serve their purpose during review and persist in git history (or a tag, if +explicitly preserved). The spike doc's "PoC results" and "Findings +discovered during the PoC" sections capture what survives the merge. diff --git a/docs/contributing/howto-run-a-spike.md b/docs/contributing/howto-run-a-spike.md index aea36ed46..54b66908c 100644 --- a/docs/contributing/howto-run-a-spike.md +++ b/docs/contributing/howto-run-a-spike.md @@ -8,6 +8,14 @@ project. also use `/spike LCORE-1234` or `/spike 1234` (defaults to LCORE) to have Claude Code fetch the respective JIRA ticket using `dev-tools/fetch-jira.sh`. +## Configuration + +Team-policy conventions for the feature design process live in +[`feature-design.config`](feature-design.config). Personal overrides go in +`.feature-design.config.local` at the repo root (gitignored). Skills +(including `/spike`) read both at the start of each session and announce +which files were loaded. + ## Outputs A spike produces: @@ -86,13 +94,31 @@ Key principles: - **Decisions up front, background below.** The first sections should be the decisions that need confirmation. Background (current architecture, API research, etc.) goes in later sections and is linked from the decisions. -- **Split decisions by audience.** Strategic decisions (approach, model, - threshold strategy) go in a section for the decision-makers and relevant - stakeholders. Technical decisions (storage schema, field naming, buffer - calculation) go in a section for the tech lead and relevant team members. -- **Proposed JIRAs** follow the decisions. Each JIRA should have: Description, - Scope, Acceptance Criteria, and an Agentic tool instruction pointing to the - spec doc. Use [jira-ticket-template.md](templates/jira-ticket-template.md). +- **Split decisions by audience.** The template provides three audience + sections: **Strategic** (PM/owner — approach, scope, deprecation timeline), + **Technical** (tech lead — schema, merge semantics, secrets handling), + and **Stakeholder** (the team that requested the feature, if any — + decisions only they are positioned to make). The Stakeholder section is + `if_applicable` per [`feature-design.config`](feature-design.config); add + it when the feature originated from a named team, remove it otherwise. +- **State confidence per recommendation.** Each recommendation includes a + confidence value (numeric or qualitative per + [`feature-design.config`](feature-design.config)). Reviewers prioritize + attention based on it. +- **Out-of-scope section is required.** What this spike deliberately does + not address. Each item explains why and (where possible) names the + follow-up ticket. +- **Proposed JIRAs** follow the decisions. Each JIRA should have: + Description, Scope, Acceptance Criteria, and an Agentic tool instruction + pointing to the spec doc. Use + [jira-ticket-template.md](templates/jira-ticket-template.md). +- **The first proposed JIRA is the e2e kickoff Story** — write the behave + `.feature` files for the feature, no step implementation. This kicks off + the work *before* implementation lands so the test shape isn't shaped by + the implementation. The counterpart Task (implement step definitions, + blocked by the kickoff and the implementation tickets) is also included + by default. Both are stubs in the spike-template; remove only with + documented rationale in the Out-of-scope section. ### 6. Write the spec doc @@ -182,6 +208,18 @@ The spike doc stays in the repo because it records decision rationale, PoC evidence, and the design space explored — context that the spec doc doesn't capture. +### 11. Finalize after merge + +Run `/spike-finalize` (Claude Code shortcut) after the spike PR is merged: + +- Verify spike doc and spec doc don't drift. +- Check for any orphan `LCORE-????` references that should be replaced + with filed ticket keys. +- Prompt to create Google Docs versions of the spike and/or spec docs for + team-wide reading (controlled by + `remind_about_google_doc_after_merge` in + [`feature-design.config`](feature-design.config)). + ## Checklist ``` @@ -190,11 +228,15 @@ capture. [ ] Existing approaches researched [ ] Design alternatives documented with pros/cons [ ] PoC built and validated (if applicable) -[ ] Spike doc written (decisions up front, background below) +[ ] Spike doc written (decisions up front, background below, audience split) +[ ] Confidence stated per recommendation +[ ] Out-of-scope section present +[ ] E2E kickoff JIRA + step-definitions counterpart included as proposed JIRAs [ ] Spec doc written (with accepted recommendations) [ ] PR opened with structured reviewer asks [ ] Reviewer feedback incorporated [ ] JIRAs filed under parent ticket [ ] PoC code and experiment data removed before merge [ ] Spike doc and spec doc remain in merge +[ ] /spike-finalize run after merge ``` diff --git a/docs/contributing/howto-write-a-spec-doc.md b/docs/contributing/howto-write-a-spec-doc.md index f73a534ba..cfb1d1bc3 100644 --- a/docs/contributing/howto-write-a-spec-doc.md +++ b/docs/contributing/howto-write-a-spec-doc.md @@ -6,6 +6,13 @@ JIRAs reference it. Agentic coding tools read it for guidance. **Claude Code shortcut**: `/spec-doc` creates one interactively. +## Configuration + +Team-policy conventions for the spec doc shape (which sections are required, +which are `if_applicable`, etc.) live in +[`feature-design.config`](feature-design.config). Personal overrides go in +`.feature-design.config.local` at the repo root (gitignored). + ## When to write one - As part of a spike (see [howto-run-a-spike.md](howto-run-a-spike.md), step 6). @@ -33,15 +40,30 @@ easy to provide clear acceptance criteria. **Architecture**: Flow diagram, then subsections for each component. Include where things live (file paths), function signatures, schemas, configuration. +Architecture sub-sections marked `if_applicable` in +[`feature-design.config`](feature-design.config) (Trigger mechanism, Storage +/ data model, API changes, etc.) are present only when the feature actually +has the concern. Delete unused sub-sections. + +**Acceptance test surface**: Maps each requirement (R1..Rn) to an observable +behavior. This section drives the e2e-kickoff JIRA's feature files: the +person writing `.feature` files reads this section to author Gherkin +scenarios. + +**Aspect-specific concerns**: Sections like Latency and Cost, Observability, +Capacity planning, Failure modes, Security considerations, +Migration / backwards compatibility, Telemetry / data privacy, Feature +flags / rollout, Runbook / oncall, Internationalization, API versioning, +Rate limiting / quotas. All `if_applicable` — include only when the +feature genuinely has the concern. Delete sub-sections that don't apply. **Implementation Suggestions**: File paths, insertion points, code patterns, test patterns. Be specific — this section is read by both humans and agentic coding tools. -**Latency and Cost**: How the feature affects performance. Include if -applicable to the feature. - -**Open Questions**: Things explicitly deferred, and why. +**Open Questions**: Things explicitly deferred, and why. Each item must +trace back to its origin (a spike decision, a PoC finding, or a reviewer +comment) so the rationale survives over time. **Changelog**: Record significant changes after initial creation. Date, what changed, why. diff --git a/docs/contributing/templates/spec-doc-template.md b/docs/contributing/templates/spec-doc-template.md index 4da0b0b5c..1edf2a7c6 100644 --- a/docs/contributing/templates/spec-doc-template.md +++ b/docs/contributing/templates/spec-doc-template.md @@ -43,19 +43,23 @@ TODO: Flow diagram showing the request/response path with the new feature. TODO: flow diagram ``` -TODO: Add subsections below for each relevant component. Delete any that don't apply, add feature-specific ones. +TODO: Add subsections below for each relevant component. Architecture +sub-sections marked `if_applicable` in +`docs/contributing/feature-design.config` should be present only when the +feature actually has that concern. Delete unused sub-sections; add +feature-specific ones. ### Trigger mechanism -TODO: When and how the feature activates. +REMOVE IF NOT APPLICABLE. When and how the feature activates. ### Storage / data model changes -TODO: Schema changes, which backends need updates. +REMOVE IF NOT APPLICABLE. Schema changes, which backends need updates. ### Configuration -TODO: YAML config example and configuration class. +REMOVE IF NOT APPLICABLE. YAML config example and configuration class. ``` yaml TODO: config example @@ -67,19 +71,79 @@ TODO: configuration class ### API changes -TODO: New or changed fields in request/response models. +REMOVE IF NOT APPLICABLE. New or changed fields in request/response models. ### Error handling -TODO: How errors are surfaced — new error types, HTTP status codes, recovery behavior. +REMOVE IF NOT APPLICABLE. How errors are surfaced — new error types, HTTP status codes, recovery behavior. ### Security considerations -TODO: Auth, access control, data sensitivity implications. Remove if not applicable. +REMOVE IF NOT APPLICABLE. Auth, access control, data sensitivity implications. ### Migration / backwards compatibility -TODO: Schema migrations, API versioning, feature flags for gradual rollout. Remove if not applicable. +REMOVE IF NOT APPLICABLE. Schema migrations, API versioning, feature flags for gradual rollout. + +## Acceptance test surface + +Maps each requirement (R1..Rn) to one or more observable behaviors. This +section is the source-of-truth that drives the e2e-kickoff JIRA's feature +files. Authors of `.feature` files read this section to write Gherkin +scenarios. + +| Req | Observable behavior | Verified by | +|-----|---------------------|-------------| +| R1 | TODO | TODO | + +## Aspect-specific concerns + +REMOVE ANY SUB-SECTION THAT DOES NOT APPLY. These sections cover concerns +that may or may not be relevant to a given feature. The defaults in +`docs/contributing/feature-design.config` are `if_applicable` — include +only when the feature genuinely has the concern. + +### Latency and Cost + +How the feature affects per-request performance and cost. + +### Observability + +What is logged, what is measured, what is traced. New dashboards / alerts. + +### Capacity planning + +How much load the feature handles before degrading; what scaling decisions +are tied to it. + +### Failure modes + +Non-obvious ways the feature can fail, and what happens when it does. + +### Telemetry / data privacy + +What data is collected, where it goes, how user privacy is preserved. + +### Feature flags / rollout + +Gradual rollout strategy if this feature lands behind a flag. + +### Runbook / oncall implications + +What oncall needs to know; new alerts, new failure modes, recovery +procedures. + +### Internationalization + +i18n / l10n implications, if any. + +### API versioning + +If the feature changes a public API, how the version bump is handled. + +### Rate limiting / quotas + +If the feature introduces or interacts with rate limits or quotas. ## Implementation Suggestions @@ -115,10 +179,12 @@ TODO: Describe any feature-specific test considerations (e.g., tests that need a ## Open Questions for Future Work -TODO: Things explicitly deferred and why. +Things explicitly deferred and why. **Each item must trace back to its +origin**: a spike decision, a PoC finding, or a reviewer comment, so that +the rationale survives over time. -- TODO -- TODO +- TODO: question — origin (e.g., "Deferred from spike Decision T7" or + "Surfaced during PoC, blocked on external dependency on TODO") ## Changelog diff --git a/docs/contributing/templates/spike-template.md b/docs/contributing/templates/spike-template.md index 630339c34..75803a8e4 100644 --- a/docs/contributing/templates/spike-template.md +++ b/docs/contributing/templates/spike-template.md @@ -10,12 +10,12 @@ TODO (example, delete): [conversation-compaction-spike.md](../../design/conversa **PoC validation**: TODO -## Decisions for TODO specify reviewer(s) +## Strategic decisions — for TODO specify reviewer(s) (default: @sbunciak) -These are the high-level decisions that determine scope, approach, and cost. -Each has a recommendation — please confirm or override. +High-level decisions that determine scope, approach, and cost. Each has a +recommendation — please confirm or override. -### Decision 1: TODO title +### Decision S1: TODO title TODO: Context, options table, recommendation. Link to the relevant background section(s) below. @@ -26,46 +26,170 @@ TODO: Context, options table, recommendation. Link to the relevant background se **Recommendation**: TODO -## Technical decisions for TODO specify reviewer(s) +**Confidence**: TODO (e.g., 75% — see `confidence_format` in +`docs/contributing/feature-design.config`) + +## Technical decisions — for TODO specify reviewer(s) (default: @tisnik) Architecture-level and implementation-level decisions. -### Decision N: TODO title +### Decision T1: TODO title TODO: Context, options table, recommendation. Link to the relevant background section(s) below. +| Option | Description | +|--------|-------------| +| A | | +| B | | + +**Recommendation**: TODO + +**Confidence**: TODO + +## Stakeholder decisions — for TODO specify reviewer(s) from requesting team + +REMOVE THIS WHOLE SECTION IF NOT APPLICABLE. Include this section only when +the feature originated from a specific team or stakeholder (controlled by +`include_stakeholder_decisions_section = if_applicable` in +`docs/contributing/feature-design.config`). Decisions that the requesting +team is uniquely positioned to weigh in on go here. + +### Decision SH1: TODO title + +TODO: Context, options table, recommendation. + **Recommendation**: TODO +**Confidence**: TODO + +## Out of scope + +What this spike deliberately does *not* address. Each item should explain +why it's deferred and (where possible) reference a follow-up ticket or +existing JIRA that will pick it up. + +- TODO: deferred item — why +- TODO: deferred item — why + ## Proposed JIRAs -TODO: One subsection per JIRA. Each JIRA's agentic tool instruction should point to the spec doc (the permanent reference), not this spike doc. +Order tickets to reflect dependency / kickoff sequence: the first ticket is +what kicks off the work; later tickets follow the implementation order. +Each JIRA's agentic tool instruction should point to the **spec doc** (the +permanent reference), not this spike doc. + +The first two stubs below are required-by-default per project convention +(`require_e2e_kickoff_jira = yes`, +`require_e2e_step_definitions_jira = yes`). Customize them for the feature +or remove if explicitly not applicable; document the removal rationale in +`Out of scope` above. + + + +### LCORE-???? E2E feature files for TODO feature (no step implementation) + +**User story**: As a Lightspeed Core e2e engineer, I want the behave +feature files for TODO feature scenarios written before the feature +implementation lands, so that the test shape reflects the feature's +intended behavior rather than the chosen implementation, and any +architectural gaps surface early. + +**Description**: Author behave `.feature` files under `tests/e2e/features/` +that describe the behaviors required of TODO feature. Step definitions +(Python glue) are explicitly **not** part of this ticket — they are +covered by a later sibling ticket (LCORE-????). + +**Scope**: +- `.feature` files covering R1..Rn from the spec doc +- Additions to `tests/e2e/test_list.txt` +- Author from spec doc requirements only; do not read implementation code + +**Acceptance criteria**: +- behave parses every new `.feature` file without syntax errors +- behave marks all new scenario steps as `undefined` +- `uv run make test-e2e` remains green (new scenarios skipped/undefined, not failing) + +**Blocks**: LCORE-???? (step-definitions counterpart) + +**Agentic tool instruction**: + +```text +Read "Requirements" and "Acceptance test surface" in +docs/design//.md. +Do NOT read other JIRAs' scope sections or the implementation code while +authoring; the point of this ticket is feature files uncontaminated by +implementation detail. +Key files to create: tests/e2e/features/-*.feature plus +additions to tests/e2e/test_list.txt. Do NOT create step definitions. +``` + + + +### LCORE-???? Implement behave step definitions for TODO feature files + +**Description**: Implement Python step definitions under +`tests/e2e/features/steps/` for the `.feature` files authored in +LCORE-???? (kickoff). Take the Gherkin as-is; if a scenario cannot be +implemented faithfully, raise it against the spec doc rather than +quietly weakening the test. + +**Blocked by**: +- LCORE-???? (E2E feature files kickoff) +- TODO list implementation tickets that must exist before step defs run + +**Agentic tool instruction**: + +```text +Read "Architecture" and "Requirements" in +docs/design//.md. +Take feature files from tests/e2e/features/-*.feature as-is; +do not modify Gherkin to accommodate implementation constraints. +To verify: `uv run make test-e2e` runs every new scenario green. +``` - + ### LCORE-???? TODO fill in title TODO: Use the format from `docs/contributing/templates/jira-ticket-template.md`. Change type above to Story if user-facing. **Description**: TODO -**Scope**: TODO +**Scope**: - TODO -**Acceptance criteria**: TODO +**Acceptance criteria**: - TODO -**Agentic tool instruction**: TODO +**Agentic tool instruction**: ```text Read the "[section]" section in docs/design//.md. Key files: [files]. ``` +## Proposed incidental JIRAs + +REMOVE THIS WHOLE SECTION IF NOT APPLICABLE (controlled by +`include_proposed_incidental_jiras_section = if_applicable`). Tickets for +unrelated bugs or improvements noticed *during* the spike that aren't part +of the feature itself but should be tracked. + + + +### LCORE-???? TODO incidental finding title + +**Description**: TODO + ## PoC results -TODO: If a PoC was built, document what it does, what it proved, and how it diverges from the production design. +REMOVE THIS WHOLE SECTION IF NO PoC WAS BUILT. If a PoC was built, document +what it does, what it proved, and how it diverges from the production +design. PoC code and evidence live under +`docs/design//poc-results/` and are removed before merge per +`docs/contributing/howto-organize-poc-output.md`. ### What the PoC does @@ -76,10 +200,38 @@ TODO: If a PoC was built, document what it does, what it proved, and how it dive TODO +### Findings discovered during the PoC + +REMOVE THIS SUBSECTION IF NO INTERESTING FINDINGS. Surprises uncovered +while building the PoC that the implementation JIRAs need to address. + +- TODO: finding — implication for the design — JIRA reference + +## Incidental findings + +REMOVE THIS WHOLE SECTION IF NO INCIDENTAL FINDINGS. Unrelated bugs or +improvements noticed during this spike. File these as separate JIRAs (see +`Proposed incidental JIRAs` above). + +- TODO + +## External input needed + +REMOVE THIS WHOLE SECTION IF NOT APPLICABLE. Items where reviewers need to +get input from people outside the immediate team (other teams, external +maintainers, downstream consumers). Each item should name who to ask. + +- TODO: item — who to ask + ## Background sections TODO: Research and analysis that supports the decisions above. These sections are linked from the decisions, not read front-to-back. Common topics: current architecture, existing approaches, design alternatives. Add or remove as needed. +## Glossary + +REMOVE THIS WHOLE SECTION IF NOT NEEDED. Define terms specific to this +spike that a reader unfamiliar with the feature would benefit from. + ## Appendix A TODO: Supporting material — external references, responses to suggestions from team members. Add appendices as needed. diff --git a/docs/contributing_guide.md b/docs/contributing_guide.md index f3c74f7fd..e38121f80 100644 --- a/docs/contributing_guide.md +++ b/docs/contributing_guide.md @@ -152,6 +152,12 @@ automate parts of the process. The underlying skill definitions are in 5. **Update spike doc with filed ticket numbers** — replace `LCORE-????` placeholders with actual ticket keys. +6. **Finalize after merge** (`/spike-finalize`) — once the spike+spec PR is + merged, run the finalize skill: it verifies the spike doc and spec doc + don't drift, checks for orphan `LCORE-????` references, and reminds you + to create Google Docs versions of the spike and spec docs for wider + team consumption. + If the feature is well-understood and doesn't need research, skip step 1 and start at step 2. @@ -160,6 +166,12 @@ Templates for all of the above are in the spike, see [how to organize PoC output](contributing/howto-organize-poc-output.md). +**Configuration**: team-policy conventions for the feature design process +live in [`docs/contributing/feature-design.config`](contributing/feature-design.config). +Personal overrides go in `.feature-design.config.local` at the repo root +(gitignored). Skills (`/spike`, `/spec-doc`, `/spike-finalize`) read both +at the start of each session and announce which files were loaded. + **CLI tools** (work without Claude Code): - `dev-tools/fetch-jira.sh ` — fetch JIRA ticket content and child issues - `dev-tools/file-jiras.sh --spike-doc --feature-ticket ` — parse and file JIRAs From e0b7f019492f2b260018faf915962192ea41090d Mon Sep 17 00:00:00 2001 From: Maxim Svistunov Date: Tue, 5 May 2026 15:06:33 +0200 Subject: [PATCH 3/5] LCORE-1736: /spike + new /spike-finalize skills honor the config /spike (.claude/commands/spike.md): - Reads docs/contributing/feature-design.config and (if present) .feature-design.config.local at session start. - Announces config files loaded, plus actively-honored non-default settings and items changed since last session, per `config_announcement_at_start` (default `notable`). - Maintains a state file at `config_state_file` (default `.claude/feature-design.last-seen`) for change detection. - May propose one-shot or persistent config changes mid-session if `agent_may_suggest_config_changes_during_work = yes` (default). - Honors `on_dirty_working_tree` (default `ask`): describes the situation and asks whether to use a worktree, move untracked files aside, stop, or proceed. Confirms branch name before creating. - Honors `decision_presentation_cadence` (default `mixed`): per-decision for strategic, batched for technical. - Includes the e2e kickoff Story and step-definitions Task as the first two proposed JIRAs by default. - Uses TaskCreate/TaskUpdate to track spike phases. - Reminds the user about /spike-finalize at PR-open time. /spike-finalize (.claude/commands/spike-finalize.md, new): - Replaces LCORE-???? placeholders in the spike doc with real keys read from the filed-tickets metadata under jiras/. - Verifies the spike doc and spec doc don't drift on the resolved decisions. - Greps for orphan LCORE-???? references across both docs. - Reminds about removing poc-results/ if it wasn't already cleaned up. - Reminds the user to create Google Docs versions of the spike and spec docs (per `remind_about_google_doc_after_merge = yes`). --- .claude/commands/spike-finalize.md | 103 +++++++++++++++++++++++++++++ .claude/commands/spike.md | 75 ++++++++++++++++++++- 2 files changed, 175 insertions(+), 3 deletions(-) create mode 100644 .claude/commands/spike-finalize.md diff --git a/.claude/commands/spike-finalize.md b/.claude/commands/spike-finalize.md new file mode 100644 index 000000000..c97fdfab8 --- /dev/null +++ b/.claude/commands/spike-finalize.md @@ -0,0 +1,103 @@ +Finalize a spike after its PR has been merged: replace placeholders, verify drift, prompt about Google Docs + +You are finalizing a spike whose PR has been merged. The spike doc and spec +doc now live in the repo permanently; PoC code and evidence have been +removed. Implementation JIRAs have been filed under the parent feature +ticket. + +Follow the process in `docs/contributing/howto-run-a-spike.md`, step 11 +("Finalize after merge"). + +## Configuration + +Read `docs/contributing/feature-design.config` and (if present) +`.feature-design.config.local`. Honor: +- `auto_replace_jira_placeholders` +- `verify_spike_spec_doc_drift` +- `verify_no_orphan_jira_references` +- `remind_about_google_doc_after_merge` +- `config_announcement_at_start` + +Announce config files read at session start, per +`config_announcement_at_start` (same behavior as `/spike`). + +## Inputs + +The user will identify the feature, e.g., by directory name +(`docs/design//`) or by spike ticket key. From this: +- Locate the spike doc (`-spike.md`) and spec doc (`.md`). +- Locate the parsed JIRAs directory (`docs/design//jiras/`) if + it exists. + +## Steps + +### 1. Replace LCORE-???? placeholders + +If `auto_replace_jira_placeholders = yes`: + +- For each filed ticket file in `docs/design//jiras/`, read the + `` metadata. +- Find the corresponding `LCORE-????` placeholder in the spike doc by + matching the ticket title (`### LCORE-???? `) to the filed + ticket's title. +- Replace `LCORE-????` with the real key in the spike doc. +- Show a diff to the user before writing. + +If a placeholder cannot be matched to a filed ticket, list the unmatched +items and ask the user to resolve manually. + +### 2. Verify spike ↔ spec doc don't drift + +If `verify_spike_spec_doc_drift = yes`: + +- Read both docs. +- Identify decisions in the spike doc that should be reflected in the spec + doc (look at "Strategic decisions", "Technical decisions", + "Stakeholder decisions" sections). +- Cross-check that the spec doc's Requirements / Architecture / + Implementation Suggestions reflect the *resolved* decisions (i.e., the + recommendations the reviewers accepted). +- Report any apparent drift to the user — don't fix automatically; + document drift requires human judgment. + +### 3. Verify no orphan JIRA references + +If `verify_no_orphan_jira_references = yes`: + +- Grep for `LCORE-????` in the spike doc and the spec doc. Any remaining + matches are unresolved placeholders. +- Grep for `LCORE-` references; for each found key, confirm the ticket + exists (via `dev-tools/fetch-jira.sh <key>` if needed). Report any that + return errors. + +### 4. PoC artifacts cleanup check + +Confirm `docs/design/<feature>/poc-results/` was removed before merge (per +`remove_poc_dir_before_merge` and the howto step 10). If it still exists, +remind the user; do not delete automatically. + +### 5. Google Docs reminder + +If `remind_about_google_doc_after_merge = yes`: + +Print a reminder, in this shape (adapt wording as appropriate): + +> Now that the spike+spec PR has merged, consider creating Google Docs +> versions of: +> - the spike doc at `docs/design/<feature>/<feature>-spike.md` +> - the spec doc at `docs/design/<feature>/<feature>.md` +> +> Google Docs versions are easier for the wider team to read and comment +> on. Markdown → Google Doc conversion: copy the rendered Markdown into +> a new Doc, or use a converter; either way, link the resulting docs +> back from the JIRA feature ticket so they're discoverable. + +Do NOT attempt to create the Google Docs yourself; this is a manual +step the user takes. + +### 6. Summary + +Print a short end-of-session summary listing what was changed +(placeholder replacements, files updated), what was flagged (drift, +orphan refs, missing cleanup), and what's left for the user (Google Docs +creation, any flagged items needing manual resolution). diff --git a/.claude/commands/spike.md b/.claude/commands/spike.md index c860eb625..40a516df0 100644 --- a/.claude/commands/spike.md +++ b/.claude/commands/spike.md @@ -5,6 +5,32 @@ You are starting a spike for a feature in the Lightspeed Core project. Follow the process in `docs/contributing/howto-run-a-spike.md`. Use the templates it references. +## Configuration + +Read `docs/contributing/feature-design.config` (team policy) and, if +present, `.feature-design.config.local` at the repo root (per-developer +overrides). The local file's settings override the team file's; keys not +set in the local file fall through. + +At the start of the session, announce the configuration in the manner +specified by `config_announcement_at_start`: +- `silent`: no announcement. +- `notable` (default): list which config files were read; list any + actively-honored non-default settings relevant to the spike workflow + (e.g., reviewers, default PoC ambition, decision presentation cadence); + list any settings changed since the last session, computed against the + state file at `config_state_file` (compare mtime + content hash). +- `full`: print the resolved (team + local) config in full. + +After announcing, update the state file with the current mtime and hash +of each config file. + +If `agent_may_suggest_config_changes_during_work` is `yes`, you may +propose one-shot or persistent config changes mid-session when they would +help the current work — but always ask the user before persisting. + +## Fetching the JIRA ticket + If the user provides a JIRA ticket number (e.g., "1234" or "LCORE-1234"), fetch the ticket content by running `sh dev-tools/fetch-jira.sh <number>`. The output includes child issues — decide which linked tickets to fetch @@ -12,9 +38,52 @@ for additional context. Otherwise, the user will provide context about the feature directly. +## Branch and working tree + +Before creating the spike branch: + +1. Confirm the proposed branch name with the user (per + `branch_name_pattern`). +2. Check the working tree. If it's not clean, honor `on_dirty_working_tree`: + - `ask` (default): describe the situation and ask the user whether to + use a worktree (per `worktree_path_pattern`), move untracked files + aside (per `move_aside_path_pattern`), stop and let the user clean + up manually, or proceed anyway. Wait for an answer before acting. + - `worktree` / `move_aside` / `stop`: act per the policy. +3. Create the branch off `branch_off` (default `upstream/main`) after + confirmation. + +## Drafting the spike doc + When proposing JIRAs in the spike doc, specify the type for each ticket using `<!-- type: Task -->` or `<!-- type: Story -->` (see the JIRA ticket -template). Use `dev-tools/file-jiras.sh --help` for filing details. +template). Include the e2e kickoff Story and step-definitions counterpart +Task as the first two proposed JIRAs by default (per +`require_e2e_kickoff_jira` and `require_e2e_step_definitions_jira`). + +Use `dev-tools/file-jiras.sh --help` for filing details. + +## Decision presentation + +Honor `decision_presentation_cadence`: +- `per_decision`: ask the user at every decision before moving on. +- `batch`: present all decisions in one summary near the end and let the + user confirm/override the batch. +- `mixed` (default): per-decision for strategic decisions; batched for + technical decisions. + +State a confidence value with each recommendation (per +`require_confidence_per_recommendation` and `confidence_format`). + +## Use task tracking + +Use `TaskCreate` / `TaskUpdate` to track the spike phases (set up → +research → design alternatives → PoC → spike doc → spec doc → JIRAs). +Spikes are multi-phase; tracking improves continuity and reviewability. + +## End-of-session reminder -At decision points, present what you've found and ask the user before proceeding. -The user makes the decisions — you assist with the research and documenting. +When the spike PR is opened (step 7 of the howto), remind the user that +`/spike-finalize` exists and what conditions trigger it: decisions +confirmed by reviewers, JIRAs filed via `/file-jiras`, ready to merge the +spike PR. From 2189f54dcb71bcbdf6b2c42588add731a50304fd Mon Sep 17 00:00:00 2001 From: Maxim Svistunov <makssvistunov@gmail.com> Date: Wed, 6 May 2026 17:59:22 +0200 Subject: [PATCH 4/5] =?UTF-8?q?LCORE-1736:=20Phase=200=20=E2=80=94=20addit?= =?UTF-8?q?ional=20process=20refinements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six small refinements to the feature design process, applied before opening the LCORE-1736 PR. Each is small; together they cover the follow-up feedback from the review of the original LCORE-1736 changeset. 1. Trim ### Test patterns subsection in spec-doc-template The 5-bullet generic list (pytest framework, AsyncMock pattern, etc.) duplicated the project-wide testing conventions in CLAUDE.md. Replaced with a one-line pointer to CLAUDE.md and a TODO for feature-specific test considerations only. 2. Trim ### Config pattern subsection in spec-doc-template Same shape of duplication: the ConfigurationBase / extra="forbid" / Field()/@model_validator note is in CLAUDE.md's Configuration section. Replaced with a pointer plus a TODO for feature-specific config schemas. 3. Add "Tools used to create PR" section to spike-pr-template Spike PRs are typically heavy on AI assistance; transparency warrants the same Assisted-by/Generated-by note that the project's default PR template carries. Adopted just this section from the project default; deliberately did NOT pull in the broader project PR template's Type-of-change/Checklist/Testing sections (those don't fit the spike PR shape, and the spike-pr template already carries its own structured asks). 4. Two new aspect sections in spec-doc-template (per A5 defaults) - "Migration tool patterns": invocation/semantics of any user-facing migration tool that ships with the feature - "Rollout / deployment plan": rollout sequence (distinct from the existing "Feature flags / rollout" which is the flag mechanism) Both registered as `if_applicable` in feature-design.config. 5. Spike-type-specific PoC notes (per A5 defaults) Added two short subsections to howto-organize-poc-output.md: - "Performance-focused spikes": include benchmark methodology, raw measurements, baseline comparison - "Security-focused spikes": include threat model, attack scenarios, coordinate with security reviewer on what's public vs restricted 6. Branch-naming consolidation feature-design.config is now the canonical source for the spike-specific branch name pattern. Renamed the placeholder from `{slug}` to `{short-description}` for clarity. Updated howto-run-a-spike.md step 1 to point at the config rather than restate the convention. Project CLAUDE.md retains the broader non-spike branch convention (`lcore-XXXX-short-description`); the spike pattern is now its extension. 7. Spike↔spec doc coupling exhortation Added to /spike and /spec-doc skills: whenever a non-trivial update is made to either doc (decision change, PoC finding integrated, reviewer override, open question resolved), the agent must check whether the other doc needs a corresponding update and propose it in the same turn. Drift is the most common process failure that /spike-finalize has to fix retroactively; cheaper to prevent. --- .claude/commands/spec-doc.md | 8 ++++ .claude/commands/spike.md | 8 ++++ docs/contributing/feature-design.config | 4 +- docs/contributing/howto-run-a-spike.md | 6 ++- .../templates/spec-doc-template.md | 37 +++++++++++++------ .../templates/spike-pr-template.md | 7 ++++ 6 files changed, 56 insertions(+), 14 deletions(-) diff --git a/.claude/commands/spec-doc.md b/.claude/commands/spec-doc.md index bcd2cb2e7..5f5b0b66c 100644 --- a/.claude/commands/spec-doc.md +++ b/.claude/commands/spec-doc.md @@ -19,3 +19,11 @@ The user may also provide a spike doc path or feature description directly. Place the spec doc at `docs/design/<feature>/<feature>.md`. Confirm the feature name and path with the user. + +## Keep spike doc and spec doc coupled + +If a corresponding spike doc exists, treat the two as a coupled pair. +Whenever you make a non-trivial update to the spec doc — a decision +recommendation changes, an open question gets resolved, a reviewer +comment is incorporated — **check whether the spike doc needs a +corresponding update**. If yes, propose the update in the same turn. diff --git a/.claude/commands/spike.md b/.claude/commands/spike.md index 40a516df0..c967cec38 100644 --- a/.claude/commands/spike.md +++ b/.claude/commands/spike.md @@ -81,6 +81,14 @@ Use `TaskCreate` / `TaskUpdate` to track the spike phases (set up → research → design alternatives → PoC → spike doc → spec doc → JIRAs). Spikes are multi-phase; tracking improves continuity and reviewability. +## Keep spike doc and spec doc coupled + +Treat the spike doc and the spec doc as a coupled pair. Whenever you make +a non-trivial update to one — a decision recommendation changes, a PoC +finding is integrated, the user overrides a default, a reviewer comment +is incorporated — **check whether the other needs a corresponding +update**. If yes, propose the update in the same turn. + ## End-of-session reminder When the spike PR is opened (step 7 of the howto), remind the user that diff --git a/docs/contributing/feature-design.config b/docs/contributing/feature-design.config index 6511251e4..dcffe8c2d 100644 --- a/docs/contributing/feature-design.config +++ b/docs/contributing/feature-design.config @@ -34,7 +34,7 @@ github_branch_link_format = https://github.com/{user}/{rep # ─── B. Branching ────────────────────────────────────────────────────────── branch_off = upstream/main -branch_name_pattern = lcore-{ticket}-spike-{slug} +branch_name_pattern = lcore-{ticket}-spike-{short-description} auto_fetch_upstream_before_branch = yes on_dirty_working_tree = ask # ask | worktree | move_aside | stop worktree_path_pattern = ../stack.worktrees/{branch} @@ -93,6 +93,8 @@ include_latency_and_cost_section = if_applicable include_observability_section = if_applicable include_capacity_planning_section = if_applicable include_failure_modes_section = if_applicable +include_migration_tool_patterns_section = if_applicable # invocation/semantics of any user-facing migration tool +include_rollout_deployment_plan_section = if_applicable # rollout sequence; distinct from feature-flag mechanism include_security_considerations = if_applicable include_migration_backcompat = if_applicable include_telemetry_data_privacy_section = if_applicable diff --git a/docs/contributing/howto-run-a-spike.md b/docs/contributing/howto-run-a-spike.md index 54b66908c..519df8a18 100644 --- a/docs/contributing/howto-run-a-spike.md +++ b/docs/contributing/howto-run-a-spike.md @@ -36,8 +36,10 @@ A spike produces: ### 1. Set up -- Create a feature branch: `lcore-XXXX-spike-short-description` off - `upstream/main`. +- Create a feature branch following `branch_name_pattern` from + [`feature-design.config`](feature-design.config) (default + `lcore-{ticket}-spike-{short-description}`) off `branch_off` (default + `upstream/main`). ### 2. Research diff --git a/docs/contributing/templates/spec-doc-template.md b/docs/contributing/templates/spec-doc-template.md index 1edf2a7c6..a833a363b 100644 --- a/docs/contributing/templates/spec-doc-template.md +++ b/docs/contributing/templates/spec-doc-template.md @@ -120,6 +120,21 @@ are tied to it. Non-obvious ways the feature can fail, and what happens when it does. +### Migration tool patterns + +If the feature changes a user-facing artifact (config file shape, data +schema, API contract), describe any migration tool that ships with the +feature: invocation, semantics (lossless vs lossy), what it does and +doesn't migrate, and the deprecation timeline for the old form. + +### Rollout / deployment plan + +If the feature is being rolled out gradually, describe the rollout shape: +phased enablement, feature flags, canary deployment, rollback procedure, +who is notified at each stage. Distinct from `Feature flags / rollout` +above which is about the *flag mechanism*; this is about the *rollout +sequence*. + ### Telemetry / data privacy What data is collected, where it goes, how user privacy is preserved. @@ -161,21 +176,21 @@ TODO: Where the feature hooks into existing code — function name, what's avail ### Config pattern -All config classes extend `ConfigurationBase` which sets `extra="forbid"`. -Use `Field()` with defaults, title, and description. Add -`@model_validator(mode="after")` for cross-field validation if needed. - -Example config files go in `examples/`. +Follow the project's Configuration conventions (see +[CLAUDE.md](../../../CLAUDE.md) — Configuration section). Document +feature-specific config schemas (Pydantic classes, YAML examples) in +this section. ### Test patterns -- Framework: pytest + pytest-asyncio + pytest-mock. unittest is banned by ruff. -- Mock Llama Stack client: `mocker.AsyncMock(spec=AsyncLlamaStackClient)`. -- Patch at module level: `mocker.patch("utils.module.function_name", ...)`. -- Async mocking pattern: see `tests/unit/utils/test_shields.py`. -- Config validation tests: see `tests/unit/models/config/`. +Follow the project's Testing Framework Requirements (see +[CLAUDE.md](../../../CLAUDE.md) — Testing Framework section). Document +**only feature-specific test considerations** here — e.g., tests that +need a running service, special fixtures, concurrency testing, +property-based tests for a particular invariant. -TODO: Describe any feature-specific test considerations (e.g., tests that need a running service, special fixtures, concurrency testing). +TODO: feature-specific test considerations (delete this section if +there are none beyond the project defaults). ## Open Questions for Future Work diff --git a/docs/contributing/templates/spike-pr-template.md b/docs/contributing/templates/spike-pr-template.md index 798fc39d0..3a55e13cd 100644 --- a/docs/contributing/templates/spike-pr-template.md +++ b/docs/contributing/templates/spike-pr-template.md @@ -25,5 +25,12 @@ TODO: Tag the decision-makers. List strategic decisions with links to specific l _**Doc structure note:** The decision and JIRA sections of the spike doc are where your input is needed. They link to background sections later in the doc — read those if you need more context on a specific point, but it is optional._ +### Tools used to create PR + +Identify any AI code assistants used in this PR (for transparency and review context). + +- Assisted-by: TODO (e.g., Claude Opus 4.7, CodeRabbit, Ollama, etc., N/A if not used) +- Generated by: TODO (e.g., tool name and version; N/A if not used) + Closes LCORE-XXXX Related: LCORE-XXXX From 472286aa3debf9b1e07d5438571ec40e0a0ec2ec Mon Sep 17 00:00:00 2001 From: Maxim Svistunov <makssvistunov@gmail.com> Date: Wed, 6 May 2026 18:05:43 +0200 Subject: [PATCH 5/5] LCORE-1736: backport conversation-compaction reference spike to current conventions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Retroactive update of the reference spike doc (docs/design/conversation-compaction/conversation-compaction-spike.md) so that it teaches the conventions documented in docs/contributing/feature-design.config and docs/contributing/templates/spike-template.md. Changes that were safe to apply: 1. Audience-section header rename - "Decisions for @ptisnovs and @sbunciak" → "Strategic decisions — for @ptisnovs and @sbunciak" - "Technical decisions for @ptisnovs" → "Technical decisions — for @ptisnovs" 2. Confidence value added for Decision 2 The conversation transcript explicitly states: "Confidence: 85% that additive-first is better for production". Added as a quoted provenance line under the Decision 2 recommendation. Confidence values for other decisions could not be reliably recovered from the transcript and are left absent rather than fabricated. 3. JIRA placeholders → real ticket keys (LCORE-1569..LCORE-1575) The original 7 proposed JIRAs were filed as LCORE-1569..LCORE-1575 but the spike doc retained the LCORE-???? placeholders. Replaced each placeholder with the filed key. Noted the title rename for LCORE-1574 (filed as "Integration tests" rather than the original "Verify test coverage"). 4. E2E kickoff Story + step-definitions Task stubs added at the top of Proposed JIRAs Reflect the post-spike convention. Stubs include a reconciliation note pointing at the existing LCORE-1673 ("E2E tests for conversation compaction") which holds e2e work as a single ticket; reconciliation between LCORE-1673 and these stubs is pending coordination (left to the user / @ptisnovs). 5. Header note in the Overview section explaining the retroactive update. Changes deliberately not applied (per honest assessment): - Out-of-scope section: the spike conversation transcript did not contain explicit defer/scope statements that could be reliably attributed to the spike author. Adding speculative content would risk misrepresenting the original spike. - Confidence values for Decisions other than Decision 2: not recoverable from the transcript without intensive search; better absent than fabricated. - Heading-level demotion (H1→H2 throughout): purely structural; the doc as it stands is readable and aligned in spirit with the new template even if the literal heading levels differ. The spike doc remains the deliverable for LCORE-1314; this update adjusts how it presents itself, not what it decided. --- .../conversation-compaction-spike.md | 164 +++++++++++++++--- 1 file changed, 142 insertions(+), 22 deletions(-) diff --git a/docs/design/conversation-compaction/conversation-compaction-spike.md b/docs/design/conversation-compaction/conversation-compaction-spike.md index 936af4d21..05497f4e0 100644 --- a/docs/design/conversation-compaction/conversation-compaction-spike.md +++ b/docs/design/conversation-compaction/conversation-compaction-spike.md @@ -8,7 +8,7 @@ This document is the deliverable for LCORE-1314. It presents the design options **PoC validation**: A working proof-of-concept was built and tested with 50 queries across 4 compaction cycles. Results in [PoC results](#poc-results). -# Decisions for @ptisnovs and @sbunciak +# Strategic decisions — for @ptisnovs and @sbunciak These are the high-level decisions that determine scope, approach, and cost. Each has a recommendation — please confirm or override. @@ -39,6 +39,8 @@ See [PoC results](#poc-results) for the experimental evidence. **Recommendation**: **Additive**, with recursive as a fallback when total summary size approaches the context limit. +**Confidence**: 85%. + ## Decision 3: Which model for summarization? | Option | Description | Cost | Quality | @@ -83,7 +85,7 @@ Example for a 128K context window at 70% threshold: **Recommendation**: **A**. lightspeed-stack controls the conversation flow, has the domain knowledge (Red Hat support), and doesn't require upstream coordination. Llama Stack upstream has no active work here — see [Appendix A](#llama-stack-upstream). -# Technical decisions for @ptisnovs +# Technical decisions — for @ptisnovs These are implementation-level decisions. They don't affect scope or cost significantly but determine how the code is structured. @@ -174,7 +176,127 @@ Should the client be notified that compaction is in progress (before the summari Each JIRA includes an agentic tool instruction that an assignee can optionally feed to Claude Code or similar. -### LCORE-????: Add token estimation to lightspeed-stack +<!-- type: Story --> +<!-- key: LCORE-???? --> +### LCORE-???? E2E feature files for conversation compaction (no step implementation) + +**User story**: As a Lightspeed Core e2e engineer, I want the behave +feature files for conversation-compaction scenarios written before the +feature implementation lands, so that the test shape reflects the +feature's intended behavior rather than the chosen implementation, and +any architectural gaps surface early. + +**Description**: Author behave `.feature` files under `tests/e2e/features/` +that describe the behaviors required of conversation compaction. Step +definitions (Python glue) are explicitly **not** part of this ticket — +they are covered by a later sibling ticket (LCORE-???? — Implement step +definitions). The feature files can be submitted for review and land +before implementation of the feature itself begins. + +**Scope**: +- `.feature` files covering, at minimum, these acceptance-criteria + surfaces from the spec doc: + - When estimated tokens approach the context window limit, older + messages are summarized (not just truncated). + - Summary preserves user/assistant attribution. + - Summarization threshold is configurable or auto-determined based + on model context window. + - Summarization is incremental (summary updated, not recomputed + from scratch). + - Full conversation history remains accessible (UI/audit) — only + LLM context uses the summary. + - Assistant correctly recalls and references prior context after + summarization. + - `context_status` field on responses reflects `"full"` vs + `"summarized"`. +- Additions to `tests/e2e/test_list.txt` so behave discovers the new + files. +- Gherkin scenarios authored from the spec doc only; author must avoid + reading the implementation JIRAs' scope sections while drafting + scenarios. + +**Acceptance criteria**: +- behave parses every new `.feature` file without syntax errors. +- behave marks all new scenario steps as `undefined` (step definitions + land in LCORE-????). +- `uv run make test-e2e` remains green (new scenarios are skipped or + reported undefined, not failing). +- Any ambiguity or architectural tension uncovered while authoring is + captured either as a comment in the spec doc or as a new sub-JIRA. + +**Blocks**: LCORE-???? (Implement behave step definitions for +conversation compaction feature files). + +**Agentic tool instruction**: +```text +Read "Acceptance Criteria" and the relevant decisions sections in +docs/design/conversation-compaction/conversation-compaction.md and this +spike doc. +Do NOT read the other JIRAs' scope sections or the implementation code +while authoring; the point of this ticket is to produce feature files +uncontaminated by implementation detail. +Key files to create: tests/e2e/features/conversation-compaction-*.feature +plus additions to tests/e2e/test_list.txt. Do NOT create step +definitions in tests/e2e/features/steps/. +To verify: `uv run behave --dry-run tests/e2e/features/conversation-compaction-*.feature` +parses successfully; `uv run make test-e2e` still green with the new +scenarios reported as undefined. +``` + +<!-- type: Task --> +<!-- key: LCORE-???? --> +### LCORE-???? Implement behave step definitions for conversation compaction feature files + +**Description**: Implement the Python step definitions +(`@given`/`@when`/`@then` functions) under `tests/e2e/features/steps/` +for the `.feature` files authored in LCORE-???? (E2E feature files +kickoff). After this ticket lands, the scenarios transition from +`undefined` to fully executing. + +The feature files are taken as-is — do not modify the Gherkin to make +implementation easier. If a scenario cannot be implemented faithfully, +raise it against the spec doc (and possibly back to LCORE-???? kickoff) +rather than quietly weakening the test. + +**Scope**: +- Step definitions for every step pattern in the new `.feature` files. +- Fixtures or helpers under `tests/e2e/features/steps/` as needed + (e.g., temp-dir config authoring, subprocess start/stop for LCORE, + HTTP client helpers reusing existing `tests/e2e/` patterns, + conversation-state manipulation to simulate near-threshold contexts). +- CI wiring so the new scenarios run as part of `uv run make test-e2e`. + +**Acceptance criteria**: +- behave reports zero `undefined` steps across the new `.feature` + files. +- `uv run make test-e2e` runs the new scenarios and they pass. +- No Gherkin edit was made to accommodate implementation constraints + (or if any edit was made, it is documented in a PR comment with + explicit rationale). + +**Blocked by**: +- LCORE-???? (E2E feature files for conversation compaction — the + `.feature` files being implemented against). +- LCORE-1569 (Add token estimation), LCORE-1570 (Implement conversation + summarization module), LCORE-1571 (Extend conversation cache for + summaries), LCORE-1572 (Integrate compaction into the query flow), + LCORE-1573 (Update response model and API) — the feature under test + must exist. + +**Agentic tool instruction**: +```text +Read "Architecture" and "Requirements" in +docs/design/conversation-compaction/conversation-compaction.md. +Key files to create: tests/e2e/features/steps/conversation-compaction*.py +(or extend existing step-definition modules if patterns reuse cleanly). +Do not modify tests/e2e/features/conversation-compaction-*.feature — +take the Gherkin as-is. If a scenario genuinely cannot be implemented +faithfully, file a sub-ticket rather than changing the Gherkin quietly. +To verify: `uv run make test-e2e` runs every new scenario green and +behave reports zero undefined steps. +``` + +### LCORE-1569: Add token estimation to lightspeed-stack **Description**: Add the ability to estimate token counts before sending requests to the LLM. This is the prerequisite for the compaction trigger — we need to know when conversation history is approaching the context window limit. @@ -200,7 +322,7 @@ Add config fields following the pattern in models/config.py around line 1418 (ConversationHistoryConfiguration). ``` -### LCORE-????: Implement conversation summarization module +### LCORE-1570: Implement conversation summarization module **Description**: Create the core summarization logic — given a list of conversation turns and a prompt, call the LLM and return a summary string. Includes the domain-specific summarization prompt for Red Hat product support. @@ -228,7 +350,7 @@ docs/design/conversation-compaction/conversation-compaction.md. Key files: src/utils/ (new module), src/models/config.py. ``` -### LCORE-????: Extend conversation cache for summaries +### LCORE-1571: Extend conversation cache for summaries **Description**: Add summary storage to the conversation cache so summaries persist across requests and survive restarts. @@ -255,7 +377,7 @@ Key files: src/cache/, src/models/. Follow existing cache backend patterns (test_sqlite_cache.py, test_postgres_cache.py). ``` -### LCORE-????: Integrate compaction into the query flow +### LCORE-1572: Integrate compaction into the query flow **Description**: Wire the token estimator, summarization module, and summary cache into the actual request path so compaction triggers automatically. @@ -288,7 +410,7 @@ The insertion point is in prepare_responses_params(), after conversation_id is resolved but before ResponsesApiParams is built. ``` -### LCORE-????: Update response model and API +### LCORE-1573: Update response model and API **Description**: Add a `context_status` field (or equivalent, per Decision 7) to the response so clients know whether compaction occurred. @@ -312,34 +434,32 @@ docs/design/conversation-compaction/conversation-compaction.md. Key files: src/models/responses.py (around line 410, the existing truncated field). ``` -### LCORE-????: Verify test coverage for compaction +### LCORE-1574: Integration tests for conversation compaction -**Description**: Review all compaction-related code and verify that unit tests, integration tests, and E2E tests cover the critical paths. Add any missing tests. +**Description**: Integration tests covering the compaction flow with mocked Llama Stack. **Scope**: -- Review all compaction-related code for test gaps. -- Add missing unit tests: trigger logic, token estimation, partitioning, summarization, summary storage. -- Add missing integration tests: full compaction flow with mocked Llama Stack. -- Add missing E2E tests: conversations that exceed context window, verify compaction kicks in. +- Test compaction trigger logic with mocked Llama Stack client. +- Test summary injection as marked conversation item. +- Test additive summarization (multiple compaction cycles). +- Test per-conversation blocking lock behavior. **Acceptance criteria**: -- Every public function in `token_estimator.py` and `compaction.py` has at least one unit test. -- At least one integration test exercises the full compaction flow end-to-end. -- At least one E2E test verifies that a long conversation triggers compaction and continues. +- Full compaction flow exercised end-to-end with mocked Llama Stack. +- Tests cover trigger, partitioning, summarization, marker injection, and context selection. **Agentic tool instruction**: ``` -Read the "Appendix A: PoC Evidence" section in -docs/design/conversation-compaction/conversation-compaction.md -and the full experiment data in docs/design/conversation-compaction/poc-results/. -Key test files: tests/unit/utils/, tests/integration/endpoints/, -tests/e2e/features/. +Read the "Architecture" section in +docs/design/conversation-compaction/conversation-compaction.md. +Key files to create or modify: tests/integration/endpoints/. +To verify: run pytest tests/integration/ -k compaction and confirm all pass. ``` -### LCORE-????: Coordinate with UI team on compaction indicator +### LCORE-1575: Coordinate with UI team on compaction indicator **Description**: Define the API contract for communicating compaction status to the UI. Two signals: (1) `context_status` field in the response, and (2) a `compaction_started` streaming event emitted before the summarization call.