@llman-sdd/core 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/package.json +1 -1
  2. package/src/archive/freeze.ts +6 -4
  3. package/src/archive/sevenzip.ts +35 -6
  4. package/src/context/indexStore.ts +6 -12
  5. package/src/git/spawnGit.ts +0 -8
  6. package/src/index.ts +39 -5
  7. package/src/init/defaultConfig.ts +2 -2
  8. package/src/init/init.ts +46 -56
  9. package/src/report/collect.ts +3 -3
  10. package/src/report/graph.ts +22 -34
  11. package/src/report/show.ts +14 -37
  12. package/src/report/specs.ts +19 -19
  13. package/src/review/review.ts +34 -9
  14. package/src/spec/ir.ts +7 -0
  15. package/src/spec/parser.ts +9 -4
  16. package/src/templates/embedded.ts +68 -0
  17. package/src/templates/engine.ts +3 -2
  18. package/src/validation/validate.ts +3 -5
  19. package/templates/en/agents-root-stub.md +1 -1
  20. package/templates/en/skills/llman-sdd-apply-cycle.md +7 -7
  21. package/templates/en/skills/llman-sdd-apply.md +12 -12
  22. package/templates/en/skills/llman-sdd-arch-review.md +2 -2
  23. package/templates/en/skills/llman-sdd-archive.md +12 -12
  24. package/templates/en/skills/llman-sdd-continue.md +8 -8
  25. package/templates/en/skills/llman-sdd-draft.md +5 -5
  26. package/templates/en/skills/llman-sdd-explore.md +5 -5
  27. package/templates/en/skills/llman-sdd-ff.md +7 -7
  28. package/templates/en/skills/llman-sdd-graph.md +10 -10
  29. package/templates/en/skills/llman-sdd-onboard.md +7 -7
  30. package/templates/en/skills/llman-sdd-propose.md +14 -14
  31. package/templates/en/skills/llman-sdd-quick.md +6 -6
  32. package/templates/en/skills/llman-sdd-research.md +2 -2
  33. package/templates/en/skills/llman-sdd-show.md +4 -4
  34. package/templates/en/skills/llman-sdd-specs-compact.md +6 -6
  35. package/templates/en/skills/llman-sdd-validate.md +5 -5
  36. package/templates/en/skills/llman-sdd-verify.md +7 -7
  37. package/templates/en/skills/llman-sdd-wayfinder.md +7 -7
  38. package/templates/en/units/migrate-prompt.md +5 -5
  39. package/templates/en/units/skills/ethics-governance.md +1 -1
  40. package/templates/en/units/skills/git-native-flow.md +2 -2
  41. package/templates/en/units/skills/stage-guard.md +1 -1
  42. package/templates/en/units/skills/structured-protocol.md +5 -5
  43. package/templates/en/units/skills/validation-hints.md +2 -2
  44. package/templates/en/units/workflow/archive-freeze-guidance.md +3 -3
  45. package/templates/shared/review.html +2 -2
  46. package/templates/zh-Hans/agents-root-stub.md +1 -1
  47. package/templates/zh-Hans/skills/llman-sdd-apply-cycle.md +7 -7
  48. package/templates/zh-Hans/skills/llman-sdd-apply.md +12 -12
  49. package/templates/zh-Hans/skills/llman-sdd-arch-review.md +2 -2
  50. package/templates/zh-Hans/skills/llman-sdd-archive.md +12 -12
  51. package/templates/zh-Hans/skills/llman-sdd-continue.md +8 -8
  52. package/templates/zh-Hans/skills/llman-sdd-draft.md +5 -5
  53. package/templates/zh-Hans/skills/llman-sdd-explore.md +5 -5
  54. package/templates/zh-Hans/skills/llman-sdd-ff.md +7 -7
  55. package/templates/zh-Hans/skills/llman-sdd-graph.md +10 -10
  56. package/templates/zh-Hans/skills/llman-sdd-onboard.md +7 -7
  57. package/templates/zh-Hans/skills/llman-sdd-propose.md +14 -14
  58. package/templates/zh-Hans/skills/llman-sdd-quick.md +6 -6
  59. package/templates/zh-Hans/skills/llman-sdd-research.md +2 -2
  60. package/templates/zh-Hans/skills/llman-sdd-show.md +4 -4
  61. package/templates/zh-Hans/skills/llman-sdd-specs-compact.md +6 -6
  62. package/templates/zh-Hans/skills/llman-sdd-validate.md +5 -5
  63. package/templates/zh-Hans/skills/llman-sdd-verify.md +7 -7
  64. package/templates/zh-Hans/skills/llman-sdd-wayfinder.md +7 -7
  65. package/templates/zh-Hans/units/migrate-prompt.md +5 -5
  66. package/templates/zh-Hans/units/skills/ethics-governance.md +1 -1
  67. package/templates/zh-Hans/units/skills/git-native-flow.md +2 -2
  68. package/templates/zh-Hans/units/skills/stage-guard.md +1 -1
  69. package/templates/zh-Hans/units/skills/structured-protocol.md +5 -5
  70. package/templates/zh-Hans/units/skills/validation-hints.md +2 -2
  71. package/templates/zh-Hans/units/workflow/archive-freeze-guidance.md +3 -3
@@ -3,8 +3,9 @@
3
3
  * aligned with v1 — rules = @human scenarios; enforced = rules carrying an
4
4
  * @req link that has an executable acceptance scenario; pending = the rest.
5
5
  */
6
- import type { CapabilityDoc, ScenarioIR } from '../spec/ir.ts';
6
+ import type { CapabilityDoc } from '../spec/ir.ts';
7
7
  import type { SpecEntry } from '../validation/validate.ts';
8
+ import { pad } from './collect.ts';
8
9
 
9
10
  export interface SpecMorphology {
10
11
  ruleCount: number;
@@ -35,7 +36,7 @@ function morphologyOf(doc: CapabilityDoc): SpecMorphology {
35
36
  return {
36
37
  ruleCount: rules.length,
37
38
  ruleEnforcedCount: enforced.length,
38
- ruleManualCount: rules.filter((r: ScenarioIR) => r.manual).length,
39
+ ruleManualCount: rules.filter((r) => r.manual).length,
39
40
  rulePendingCount: rules.length - enforced.length,
40
41
  acceptanceCount: acceptance.length,
41
42
  orphanAcceptanceCount: orphan.length,
@@ -43,23 +44,22 @@ function morphologyOf(doc: CapabilityDoc): SpecMorphology {
43
44
  }
44
45
 
45
46
  export function collectSpecs(entries: readonly SpecEntry[]): SpecSummary[] {
46
- return entries.map((e) => ({
47
- id: e.doc.header.capability ?? e.fileName,
48
- title: e.doc.header.capability ?? e.fileName,
49
- purpose: e.doc.header.purpose ?? '',
50
- validScope: (e.doc.header.scope ?? '')
51
- .split(',')
52
- .map((s) => s.trim())
53
- .filter((s) => s !== ''),
54
- requirementCount: morphologyOf(e.doc).ruleCount,
55
- health: null,
56
- staleness: null,
57
- morphology: morphologyOf(e.doc),
58
- }));
59
- }
60
-
61
- function pad(s: string, width: number): string {
62
- return s.length >= width ? s : s + ' '.repeat(width - s.length);
47
+ return entries.map((e) => {
48
+ const morphology = morphologyOf(e.doc);
49
+ return {
50
+ id: e.doc.header.capability ?? e.fileName,
51
+ title: e.doc.header.capability ?? e.fileName,
52
+ purpose: e.doc.header.purpose ?? '',
53
+ validScope: (e.doc.header.scope ?? '')
54
+ .split(',')
55
+ .map((s) => s.trim())
56
+ .filter((s) => s !== ''),
57
+ requirementCount: morphology.ruleCount,
58
+ health: null,
59
+ staleness: null,
60
+ morphology,
61
+ };
62
+ });
63
63
  }
64
64
 
65
65
  export function renderSpecsList(summaries: readonly SpecSummary[]): string[] {
@@ -50,15 +50,8 @@ export function buildReview(input: ReviewInput, io: SpecIo): ReviewResult {
50
50
  (c) => c.totalTasks > 0 && c.completedTasks < c.totalTasks,
51
51
  );
52
52
  const signals: ReviewSignal[] = [];
53
- let critical = 0;
54
- let warning = 0;
55
53
  const push = (kind: ReviewKind, capability: string, count: number, detail = ''): void => {
56
54
  signals.push({ kind, capability, count, detail });
57
- if (kind === 'validate') {
58
- critical += count;
59
- } else if (count > 0) {
60
- warning += count;
61
- }
62
55
  };
63
56
 
64
57
  const sweep = validateAllSpecs(entries, io);
@@ -103,13 +96,13 @@ export function buildReview(input: ReviewInput, io: SpecIo): ReviewResult {
103
96
  'locked',
104
97
  '-',
105
98
  0,
106
- `${boundChangeCount} bound change(s); inspect with \`llman sdd change diff <id>\``,
99
+ `${boundChangeCount} bound change(s); inspect with \`llman-sdd change diff <id>\``,
107
100
  );
108
101
  push(
109
102
  'validate',
110
103
  '-',
111
104
  failed.length,
112
- failed.length > 0 ? 'validate --all failed; run `llman sdd validate --all` for details' : 'ok',
105
+ failed.length > 0 ? 'validate --all failed; run `llman-sdd validate --all` for details' : 'ok',
113
106
  );
114
107
 
115
108
  const warningCount = signals
@@ -140,3 +133,35 @@ export function buildReview(input: ReviewInput, io: SpecIo): ReviewResult {
140
133
  exitCode: criticalCount > 0 ? 1 : 0,
141
134
  };
142
135
  }
136
+
137
+ /** `review --export-html`: fill the v1 shared/review.html template (pure —
138
+ * callers read the template; CLI passes it via core's TEMPLATES_ROOT). */
139
+ export function renderReviewHtml(
140
+ template: string,
141
+ result: {
142
+ signals: readonly { kind: string; capability: string; count: number; detail: string }[];
143
+ summary: { criticalCount: number; warningCount: number };
144
+ },
145
+ ): string {
146
+ const esc = (input: string): string =>
147
+ input
148
+ .replaceAll('&', '&amp;')
149
+ .replaceAll('<', '&lt;')
150
+ .replaceAll('>', '&gt;')
151
+ .replaceAll('"', '&quot;');
152
+ let mermaid = 'graph TD\n';
153
+ const sigJson: unknown[] = [];
154
+ result.signals.forEach((s, idx) => {
155
+ const label = esc(
156
+ `${s.capability} [${s.kind}] = ${s.count} — ${s.detail === '' ? 'ok' : s.detail}`,
157
+ );
158
+ mermaid += ` s${idx}["${label}"]\n`;
159
+ sigJson.push({ kind: s.kind, capability: s.capability, count: s.count, detail: s.detail });
160
+ });
161
+ return template
162
+ .replaceAll('__CRITICAL__', String(result.summary.criticalCount))
163
+ .replaceAll('__WARNING__', String(result.summary.warningCount))
164
+ .replaceAll('__SIGNALS__', JSON.stringify(sigJson))
165
+ .replaceAll('__MERMAID__', mermaid)
166
+ .replaceAll('__GENERATED__', new Date().toISOString());
167
+ }
package/src/spec/ir.ts CHANGED
@@ -41,3 +41,10 @@ export interface CapabilityDoc {
41
41
  scenarios: ScenarioIR[];
42
42
  errors: SpecStructuralError[];
43
43
  }
44
+
45
+ /**
46
+ * v1 wording: constraint statements must contain one of these tokens.
47
+ * Shared by the parser (structural error) and validation (verdict gate) so
48
+ * the two MUST-word checks cannot drift apart.
49
+ */
50
+ export const MUST_WORD_RE = /\bMUST\b|\bSHALL\b|必须|不得|禁止/u;
@@ -9,7 +9,13 @@
9
9
  import { AstBuilder, GherkinClassicTokenMatcher, Parser } from '@cucumber/gherkin';
10
10
  import type { GherkinDocument } from '@cucumber/messages';
11
11
 
12
- import type { CapabilityDoc, CapabilityHeader, ScenarioIR, SpecStructuralError } from './ir.ts';
12
+ import {
13
+ MUST_WORD_RE,
14
+ type CapabilityDoc,
15
+ type CapabilityHeader,
16
+ type ScenarioIR,
17
+ type SpecStructuralError,
18
+ } from './ir.ts';
13
19
 
14
20
  export class SpecParseError extends Error {}
15
21
 
@@ -73,7 +79,6 @@ function classify(tags: string[]): {
73
79
  classification: ScenarioIR['classification'];
74
80
  manual: boolean;
75
81
  errors: SpecStructuralError[];
76
- name: string;
77
82
  } {
78
83
  const errors: SpecStructuralError[] = [];
79
84
  const has = (t: string): boolean => tags.includes(t);
@@ -99,7 +104,7 @@ function classify(tags: string[]): {
99
104
  : executable
100
105
  ? 'executable'
101
106
  : 'unclassified';
102
- return { classification, manual, errors, name: label };
107
+ return { classification, manual, errors };
103
108
  }
104
109
 
105
110
  /** Parse one capability .feature source into the single-track IR. */
@@ -148,7 +153,7 @@ export function parseCapability(source: string, fileName = '<inline>'): Capabili
148
153
  text: s.text.trim(),
149
154
  }));
150
155
 
151
- if (kind.classification === 'human' && !/\bMUST\b|\bSHALL\b/u.test(statement)) {
156
+ if (kind.classification === 'human' && !MUST_WORD_RE.test(statement)) {
152
157
  errors.push({
153
158
  code: 'rule:missing-must-word',
154
159
  message: `@human 规则场景描述必须含 MUST/SHALL(scenario: ${scenario.name})`,
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Embedded template table for single-file binaries.
3
+ *
4
+ * Bun 1.4.x offers no embedding that survives our Node >= 24 dual-runtime
5
+ * constraint: `with { type: "text" }` works in compiled output (probed on
6
+ * 1.4.2) but Node cannot load that attribute, and `assets`/`?raw`/`?asset`
7
+ * never land in the bundle — so templates are injected through the same
8
+ * build-time `define` mechanism as LLMAN_SDD_VERSION: build-binary.ts
9
+ * collects packages/core/templates into a root-relative path→content map and
10
+ * sets process.env.LLMAN_SDD_EMBEDDED_TEMPLATES to that JSON. Bun inlines
11
+ * define values as raw expressions — the JSON is a valid object literal, so
12
+ * in the compiled binary the expression IS the table object itself, while a
13
+ * JSON string reaches these callers through the same expression in other
14
+ * engines or when force-set via env. Both forms are accepted below; every
15
+ * non-compiled run (source, npm package, Node) leaves the define unset and
16
+ * falls back to the real filesystem via TEMPLATES_ROOT.
17
+ */
18
+ import type { TemplateIo } from './skills.ts';
19
+
20
+ function isTable(value: unknown): value is Record<string, string> {
21
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
22
+ }
23
+
24
+ /** Normalize a define/raw value into the template table; undefined when bad. */
25
+ export function resolveEmbeddedTable(value: unknown): Record<string, string> | undefined {
26
+ if (value === undefined || value === '') return undefined;
27
+ if (isTable(value)) return value;
28
+ if (typeof value === 'string') {
29
+ try {
30
+ const table: unknown = JSON.parse(value);
31
+ if (isTable(table)) return table;
32
+ } catch {
33
+ // A malformed define must not silently yield a half-broken binary; treat
34
+ // as absent so the missing file surfaces loudly on first read.
35
+ }
36
+ }
37
+ return undefined;
38
+ }
39
+
40
+ /** Read the build-injected table; undefined when absent or malformed. */
41
+ export function embeddedTemplates(): Record<string, string> | undefined {
42
+ return resolveEmbeddedTable(process.env.LLMAN_SDD_EMBEDDED_TEMPLATES);
43
+ }
44
+
45
+ /**
46
+ * Embedded keys are relative to the templates root while callers address
47
+ * files by `join(TEMPLATES_ROOT, rel)`, so the key is the segment after the
48
+ * last `/templates/` boundary — correct for both source-mode (repository
49
+ * path) and $bunfs-mode (`/$bunfs/root/...` → `/templates/...`) roots.
50
+ */
51
+ export function templateKeyFor(path: string): string {
52
+ const marker = '/templates/';
53
+ const idx = path.lastIndexOf(marker);
54
+ return idx === -1 ? path : path.slice(idx + marker.length);
55
+ }
56
+
57
+ /** TemplateIo over the embedded table (no filesystem access). */
58
+ export function makeEmbeddedTemplateIo(table: Record<string, string>): TemplateIo {
59
+ return {
60
+ exists: (p: string): boolean => templateKeyFor(p) in table,
61
+ readText: (p: string): string => {
62
+ const key = templateKeyFor(p);
63
+ const content = table[key];
64
+ if (content === undefined) throw new Error(`embedded template not found: ${key}`);
65
+ return content;
66
+ },
67
+ };
68
+ }
@@ -27,8 +27,9 @@ export function renderWithUnits(
27
27
  throw new Error(`unit nesting exceeded ${MAX_UNIT_NESTING_DEPTH}`);
28
28
  }
29
29
  // minijinja keep_trailing_newline=false: a single trailing newline of the
30
- // template SOURCE is stripped before rendering (v1 parity).
31
- const source = raw.replace(/\n$/u, '').replace(/\r\n$/u, '');
30
+ // template SOURCE is stripped before rendering (v1 parity). \r? first —
31
+ // stripping \n alone would strand a trailing \r for CRLF sources.
32
+ const source = raw.replace(/\r?\n$/u, '');
32
33
  const env = new nunjucks.Environment(null, { autoescape: false });
33
34
  for (const [key, value] of Object.entries(vars)) {
34
35
  env.addGlobal(key, value);
@@ -4,6 +4,7 @@
4
4
  * filesystem access is injected via SpecIo.
5
5
  */
6
6
  import type { CapabilityDoc } from '../spec/ir.ts';
7
+ import { MUST_WORD_RE } from '../spec/ir.ts';
7
8
  import { buildReqRegistry } from '../spec/reqRegistry.ts';
8
9
 
9
10
  export type ValidationLevel = 'ERROR' | 'WARNING' | 'INFO';
@@ -20,9 +21,6 @@ export interface SpecEntry {
20
21
  doc: CapabilityDoc;
21
22
  }
22
23
 
23
- /** v1 wording: constraint statements must contain one of these tokens. */
24
- const MUST_WORD_RE = /\bMUST\b|\bSHALL\b|必须|不得|禁止/u;
25
-
26
24
  export interface SpecIo {
27
25
  exists(path: string): boolean;
28
26
  }
@@ -83,9 +81,9 @@ export function validateCapability(
83
81
  // rule scenarios) — all ERROR level (v1 verdict parity). Header gates and
84
82
  // the MUST-word gate are owned by this layer (mapped below), so the
85
83
  // parser's duplicate findings are skipped here.
86
- const OWNED_BY_THIS_LAYER = new Set(['missing-header:', 'rule:missing-must-word']);
84
+ const OWNED_BY_THIS_LAYER = ['missing-header:', 'rule:missing-must-word'];
87
85
  for (const err of doc.errors) {
88
- if ([...OWNED_BY_THIS_LAYER].some((prefix) => err.code.startsWith(prefix))) continue;
86
+ if (OWNED_BY_THIS_LAYER.some((prefix) => err.code.startsWith(prefix))) continue;
89
87
  items.push({ level: 'ERROR', id: `${cap}/${err.code}`, message: err.message });
90
88
  }
91
89
 
@@ -6,4 +6,4 @@ This project uses llman SDD. Read `llmanspec/config.yaml` for SDD command behavi
6
6
 
7
7
  Use `/llman-sdd-explore` to get started, then follow the pipeline: `/llman-sdd-propose` → `/llman-sdd-apply` → `/llman-sdd-verify` → `/llman-sdd-archive`.
8
8
 
9
- Keep this managed block so `llman sdd init --update` can refresh it.
9
+ Keep this managed block so `llman-sdd init --update` can refresh it.
@@ -16,13 +16,13 @@ End-to-end closed loop for one change (manual). Requires Branch binding and `rea
16
16
 
17
17
  ### 0) Gate + status
18
18
  ```bash
19
- llman sdd show <change-id> --json --type change
19
+ llman-sdd show <change-id> --json --type change
20
20
  ```
21
- > Stage gate: decide from `stage` / `readyToImplement` in `llman sdd show <id> --json --type change`; full decision table lives in llman-sdd-apply.
21
+ > Stage gate: decide from `stage` / `readyToImplement` in `llman-sdd show <id> --json --type change`; full decision table lives in llman-sdd-apply.
22
22
 
23
23
  - Must be on the bound non-default branch.
24
24
  - If `readyToImplement` is not true → STOP (finish Specs landing or `needs_specs_change: false`); **do not** finalize yet.
25
- - Track progress via `tasks.md` checkboxes (or `llman sdd list` task counts); still read `tasks.md`, proposal/design, and live `llmanspec/specs/**` on the bound branch (SSOT).
25
+ - Track progress via `tasks.md` checkboxes (or `llman-sdd list` task counts); still read `tasks.md`, proposal/design, and live `llmanspec/specs/**` on the bound branch (SSOT).
26
26
 
27
27
  ### 1) Loop: implement → test
28
28
  For each incomplete task:
@@ -33,7 +33,7 @@ For each incomplete task:
33
33
 
34
34
  ### 2) Validate
35
35
  ```bash
36
- llman sdd validate <change-id> --strict --no-interactive
36
+ llman-sdd validate <change-id> --strict --no-interactive
37
37
  ```
38
38
  On failure, fix and retry (same self-repair budget as `llman-sdd-apply`: cap 8 rounds).
39
39
 
@@ -42,7 +42,7 @@ Prefer `llman-sdd-verify` (or equivalent dual-axis self-check). CRITICAL → STO
42
42
 
43
43
  ### 4) Archive
44
44
  ```bash
45
- llman sdd change finalize <change-id>
45
+ llman-sdd change finalize <change-id>
46
46
  ```
47
47
  (dirty tree OK; auto merge (squash default) + docs rename + **auto commit** `archive(sdd): <change-id>` in one process. `--no-commit` skips the auto commit for manual/CI histories — then commit with `git add -A && git commit -m "archive(sdd): <change-id>"`.)
48
48
 
@@ -71,5 +71,5 @@ push / hosting PR only when the user explicitly asks.
71
71
  - `ethics.refusal_contract`: after 3 gate/validation failures, report blocker; do not force-archive
72
72
  - `ethics.escalation_policy`: if changing SDD workflow specs/templates, pause for user confirm before archive
73
73
 
74
- > For command details run `llman sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
75
- > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman sdd list --specs` or `llman sdd show <capability>`.
74
+ > For command details run `llman-sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
75
+ > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman-sdd list --specs` or `llman-sdd show <capability>`.
@@ -42,7 +42,7 @@ flowchart LR
42
42
  ## Commit Policy
43
43
 
44
44
  - **Commits on the change branch are free** (no mid-flight archive point; `change finalize` needs no clean tree): segment by task or milestone when it helps review, or keep the working tree dirty and let finalize make ONE close commit — both are first-class. `change checkpoint` no longer exists (calling it exits non-zero and points to finalize), so there is no mid-flight "archive point" to maintain; `change finalize` handles both shapes (it does NOT require a clean tree).
45
- - **Default close-out**: after all tasks pass gates and verify is green, `llman sdd change finalize <id>` auto-commits `archive(sdd): <change-id>` (uncommitted impl diff + frontmatter + archive rename in one commit). Do not run finalize inside the apply loop. `--no-commit` skips the auto commit (manual/CI histories; pre-commit-hook conflicts).
45
+ - **Default close-out**: after all tasks pass gates and verify is green, `llman-sdd change finalize <id>` auto-commits `archive(sdd): <change-id>` (uncommitted impl diff + frontmatter + archive rename in one commit). Do not run finalize inside the apply loop. `--no-commit` skips the auto commit (manual/CI histories; pre-commit-hook conflicts).
46
46
  - **Blocker interrupt**: when you must STOP on a blocker, make ONE work-in-progress commit (e.g. `wip(sdd): <change-id> <summary>`) to preserve the state, then report.
47
47
 
48
48
  ## Steps
@@ -51,18 +51,18 @@ flowchart LR
51
51
  - Read and obey: `llmanspec/config.yaml`, `AGENTS.md` (if present).
52
52
  - `git status --porcelain`:
53
53
  - If working tree is dirty and changes don't belong to the current change: `git stash push -u -m "llman-sdd-apply autopilot backup"`.
54
- - Run `llman sdd validate --all --strict --no-interactive`:
54
+ - Run `llman-sdd validate --all --strict --no-interactive`:
55
55
  - If it fails for reasons unrelated to the current change, stop and report (inconsistent artifacts prevent SSOT-driven implementation).
56
- - **Check spec valid_scope integrity**: use `llman sdd list --specs --json` to list all specs, then for each spec verify every path in its `valid_scope` exists on disk. If any scope file/directory is missing, stop and suggest updating the spec (remove the deleted path from `valid_scope`).
56
+ - **Check spec valid_scope integrity**: use `llman-sdd list --specs --json` to list all specs, then for each spec verify every path in its `valid_scope` exists on disk. If any scope file/directory is missing, stop and suggest updating the spec (remove the deleted path from `valid_scope`).
57
57
 
58
58
  ### 1) Select change id and check prerequisites
59
59
  - If a change id is provided, use it directly.
60
- - Otherwise infer from context; if ambiguous, run `llman sdd list --json` and let user pick.
60
+ - Otherwise infer from context; if ambiguous, run `llman-sdd list --json` and let user pick.
61
61
  - Always announce: "Using change: <id>" and how to override.
62
- - Confirm you are on the non-default feature branch bound via `llman sdd change start <id>` or `change attach <id>` (`--force` only to rebind). Specs/features on the branch are SSOT — do not author under `changes/<id>/specs/`.
62
+ - Confirm you are on the non-default feature branch bound via `llman-sdd change start <id>` or `change attach <id>` (`--force` only to rebind). Specs/features on the branch are SSOT — do not author under `changes/<id>/specs/`.
63
63
  {{ unit("skills/stage-guard") }}
64
- - Use `llman sdd context --task "<goal from proposal>" --paths "<scope from specs>"` to get relevant specs.
65
- - If context is unavailable, run `llman sdd index rebuild` and retry.
64
+ - Use `llman-sdd context --task "<goal from proposal>" --paths "<scope from specs>"` to get relevant specs.
65
+ - If context is unavailable, run `llman-sdd index rebuild` and retry.
66
66
 
67
67
  ### 2) Read SSOT artifacts
68
68
  You must read through:
@@ -89,8 +89,8 @@ For each unchecked task:
89
89
  Run project gate commands (adapt to the actual project):
90
90
  - Relevant test suite: `just test` or `cargo test --all`
91
91
  - Format/lint: `just check` or `just lint` + `just fmt`
92
- - Git-native: stay on the bound feature branch; edit live `llmanspec/specs/<capability>.feature` (flat, or directory `llmanspec/specs/<capability>/` main file; rules `@human`, acceptance `@executable`) as needed; run `llman sdd validate --specs` after spec edits; commit on the branch freely (segmented or leave dirty for finalize). Do not use `change delta` / solidify / feature_delta; `change checkpoint` is removed.
93
- - SDD validation: `llman sdd validate <id> --strict --no-interactive`
92
+ - Git-native: stay on the bound feature branch; edit live `llmanspec/specs/<capability>.feature` (flat, or directory `llmanspec/specs/<capability>/` main file; rules `@human`, acceptance `@executable`) as needed; run `llman-sdd validate --specs` after spec edits; commit on the branch freely (segmented or leave dirty for finalize). Do not use `change delta` / solidify / feature_delta; `change checkpoint` is removed.
93
+ - SDD validation: `llman-sdd validate <id> --strict --no-interactive`
94
94
 
95
95
  **On failure → enter self-healing loop (don't ask "should I continue?"):**
96
96
  1. Parse failure cause (test failure / lint / format / validation error).
@@ -107,7 +107,7 @@ Run project gate commands (adapt to the actual project):
107
107
 
108
108
  **Self-healing cap: 8 rounds**; exceeding this is a blocker: stop and output a blocker report (last failing command + output summary + what you tried).
109
109
 
110
- **Human review checkpoint (after each task batch passes the gates)**: once a batch is green, before starting the next batch or producing the completion report, run `llman sdd review`:
110
+ **Human review checkpoint (after each task batch passes the gates)**: once a batch is green, before starting the next batch or producing the completion report, run `llman-sdd review`:
111
111
 
112
112
  - Exit code zero → continue.
113
113
  - Non-zero exit = CRITICAL findings: STOP, fix, re-run review; MUST NOT enter the next batch or emit the completion report with CRITICAL findings open.
@@ -118,8 +118,8 @@ Then suggest running `llman-sdd-verify` for the verification phase.
118
118
 
119
119
  > 💡 Implementation done → next: `llman-sdd-verify` (verify)
120
120
 
121
- > For command details run `llman sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
122
- > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman sdd list --specs` or `llman sdd show <capability>`.
121
+ > For command details run `llman-sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
122
+ > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman-sdd list --specs` or `llman-sdd show <capability>`.
123
123
 
124
124
  {{ unit("skills/validation-hints") }}
125
125
 
@@ -59,7 +59,7 @@ Run `llman-sdd-explore`'s **grilling branch** (trigger "deep-dig") to walk the d
59
59
  ## Output
60
60
  Candidate list (text; optional HTML report written to OS temp dir, not the repo) + the grilling decision record after the user picks one (write back to proposal; contract edits only via Specs landing into live `.feature`).
61
61
 
62
- > For command details run `llman sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
63
- > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman sdd list --specs` or `llman sdd show <capability>`.
62
+ > For command details run `llman-sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
63
+ > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman-sdd list --specs` or `llman-sdd show <capability>`.
64
64
 
65
65
  {{ unit("skills/structured-protocol") }}
@@ -26,7 +26,7 @@ flowchart LR
26
26
 
27
27
  - **Must pass verify phase all-green first**: don't archive changes that haven't passed verification.
28
28
  - **Must already have Branch binding**: `change start` / `attach` done; otherwise STOP.
29
- - **SSOT validation**: every change must pass `llman sdd validate <id> --strict --no-interactive` before archiving.
29
+ - **SSOT validation**: every change must pass `llman-sdd validate <id> --strict --no-interactive` before archiving.
30
30
  - **Don't ask "should I continue?"**: execute the full batch to completion unless you hit an unresolvable error.
31
31
  - **Close-out MUST NOT default to PR/push**: finalize performs a local merge (squash by default) + rename + one close-out commit (`archive(sdd): <id>`). `git push` / hosting PR are optional — only when the user or project explicitly requires remote review. **Agent MUST NOT** push or open a PR by default on this skill's account.
32
32
 
@@ -37,34 +37,34 @@ flowchart LR
37
37
  - If unexpected changes exist, handle them (stash or report).
38
38
 
39
39
  ### 1) Confirm target changes
40
- - Determine target IDs: single or batch (from user input or `llman sdd list --json`).
40
+ - Determine target IDs: single or batch (from user input or `llman-sdd list --json`).
41
41
  - Always announce: "Archiving IDs: <id1>, <id2>, ...".
42
42
  - Confirm each change has passed verify phase all-green.
43
43
 
44
44
  ### 2) Archive one by one
45
- - **Human review checkpoint (before each id is archived, including batches)**: run `llman sdd review --capability <id>`. Exit code zero → continue; non-zero = CRITICAL findings: STOP, fix, re-run; MUST NOT archive with CRITICAL findings open.
46
- - Validate each first: `llman sdd validate <id> --strict --no-interactive`.
45
+ - **Human review checkpoint (before each id is archived, including batches)**: run `llman-sdd review --capability <id>`. Exit code zero → continue; non-zero = CRITICAL findings: STOP, fix, re-run; MUST NOT archive with CRITICAL findings open.
46
+ - Validate each first: `llman-sdd validate <id> --strict --no-interactive`.
47
47
  - Validation failure → STOP and report; don't skip validation and force archive.
48
- - Optional preview: `llman sdd change archive <id> --dry-run`.
48
+ - Optional preview: `llman-sdd change archive <id> --dry-run`.
49
49
  - Execute archive:
50
- - default: `llman sdd change archive <id>`
51
- - tooling-only: `llman sdd change archive <id> --skip-specs`
50
+ - default: `llman-sdd change archive <id>`
51
+ - tooling-only: `llman-sdd change archive <id> --skip-specs`
52
52
  - **stop immediately on first failure**, report remaining unprocessed IDs.
53
53
  - **Git-native close-out**:
54
54
  - Prerequisites: Branch binding done (`change start` / `attach`); still on the bound branch (or the target branch after the auto merge).
55
55
  - `change archive` / `change finalize` run the **auto merge** (target `--into` > binding `base_branch` > default branch; method squash by default or `ff`; if the target is held by another worktree the merge is skipped with an explicit manual command), **then** rename change docs into `changes/archive/` — rename is never rolled back on merge failure and degradation is reported explicitly.
56
- - Legacy `*.feature.delta.toon` or `spec.toon` under specs is a migration blocker — run `llman sdd project migrate --kind toon2features`.
56
+ - Legacy `*.feature.delta.toon` or `spec.toon` under specs is a migration blocker — run `llman-sdd project migrate --kind toon2features`.
57
57
  - **Default: `change finalize` (one-command close)** — gates → auto merge → docs rename → **auto commit** `archive(sdd): <change-id>` (squash default: impl diff + rename collapse into ONE commit on the target; no manual `git commit` needed; locked-rule edits are a report-only WARNING — warn, never block):
58
58
  ```text
59
59
  1. Implement live specs + code (working tree may stay dirty; commits on the branch are free — segmented or none)
60
- 2. llman sdd change finalize <id> # gates + merge (squash default) + rename + auto commit
60
+ 2. llman-sdd change finalize <id> # gates + merge (squash default) + rename + auto commit
61
61
  3. optional: git commit --amend # adjust the message; git branch -D <feature> # after squash the branch is no longer an ancestor; -d gets refused
62
62
  ```
63
63
  `--no-commit` skips the auto commit (CI / pre-commit-hook conflicts): finalize then leaves the tree dirty and prints the manual `git commit` command. Idempotent retry: a rerun after a failed auto commit detects the already-archived rename and finishes the commit.
64
64
  - **Fallback: plain `change archive <id>`** — same merge + rename, no auto commit; requires a clean tree. `checkpointed`/`checkpoint_sha` fields went away with checkpoint (no mid-flight archive point; `change finalize` needs no clean tree) — nothing to write beforehand, and nothing to review for the snapshot (use `change diff` instead).
65
65
 
66
66
  ### 3) Full validation
67
- - After all archives complete: `llman sdd validate --all --strict --no-interactive`.
67
+ - After all archives complete: `llman-sdd validate --all --strict --no-interactive`.
68
68
  - Confirm post-archive spec artifacts are consistent.
69
69
 
70
70
  ### 4) Commit guidance
@@ -77,8 +77,8 @@ flowchart LR
77
77
 
78
78
  {{ unit("workflow/archive-freeze-guidance") }}
79
79
 
80
- > For command details run `llman sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
81
- > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman sdd list --specs` or `llman sdd show <capability>`.
80
+ > For command details run `llman-sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
81
+ > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman-sdd list --specs` or `llman-sdd show <capability>`.
82
82
 
83
83
  {{ unit("skills/validation-hints") }}
84
84
 
@@ -12,30 +12,30 @@ Use this skill to continue an existing change and create the next missing artifa
12
12
  ## Steps
13
13
  1. Identify the change id:
14
14
  - If provided by the user, use it.
15
- - Otherwise run `llman sdd list --json` and ask which change to continue.
15
+ - Otherwise run `llman-sdd list --json` and ask which change to continue.
16
16
  - Always announce: "Using change: <id>".
17
17
  2. Read the change directory: `llmanspec/changes/<id>/`.
18
- > Stage gate: decide from `stage` / `readyToImplement` in `llman sdd show <id> --json --type change`; full decision table lives in llman-sdd-apply.
18
+ > Stage gate: decide from `stage` / `readyToImplement` in `llman-sdd show <id> --json --type change`; full decision table lives in llman-sdd-apply.
19
19
  3. Determine the next artifact to create (in order):
20
20
  1) `proposal.md`
21
21
  2) `design.md` (only if design tradeoffs matter)
22
22
  3) `tasks.md`
23
- 4) `llman sdd change start <id>` (or `change attach <id>` if the branch already exists) — Branch binding
23
+ 4) `llman-sdd change start <id>` (or `change attach <id>` if the branch already exists) — Branch binding
24
24
  5) Edit live `llmanspec/specs/<capability>.feature` (flat, or directory main file) on the **bound branch** and commit — Specs landing (or set `needs_specs_change: false` when there is no contract edit)
25
25
  4. Create exactly ONE missing artifact (or one live spec/feature edit on the bound branch).
26
26
  - Do NOT implement application code in continue mode.
27
27
  - Do NOT create `*.feature.delta.toon`, `spec.toon`, or files under `changes/<id>/specs/`.
28
28
  - Do NOT edit shared `llmanspec/specs/**` before start/attach.
29
- 5. If all artifacts already exist, suggest next actions from `llman sdd show <id> --json`:
29
+ 5. If all artifacts already exist, suggest next actions from `llman-sdd show <id> --json`:
30
30
  - `readyToImplement=false` → finish Specs landing (or `needs_specs_change: false`); do **not** suggest apply yet
31
31
  - `readyToImplement=true` → Implement: `llman-sdd-apply`
32
32
  - After verify → Archive: `llman-sdd-archive`
33
- - Validate: `llman sdd validate <id> --strict --no-interactive`
34
- - Review: `llman sdd change diff <id>` (read-only)
33
+ - Validate: `llman-sdd validate <id> --strict --no-interactive`
34
+ - Review: `llman-sdd change diff <id>` (read-only)
35
35
 
36
36
  {{ unit("skills/git-native-flow") }}
37
- > For command details run `llman sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
38
- > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman sdd list --specs` or `llman sdd show <capability>`.
37
+ > For command details run `llman-sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
38
+ > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman-sdd list --specs` or `llman-sdd show <capability>`.
39
39
  {{ unit("skills/validation-hints") }}
40
40
 
41
41
  {{ unit("skills/structured-protocol") }}
@@ -31,13 +31,13 @@ flowchart LR
31
31
  - **MUST NOT create tasks/design/specs/attach**: this skill creates only the `proposal.md` draft shell. Full planning artifacts belong to `llman-sdd-propose`.
32
32
  - **MUST NOT run triage or assess change scale**: that is propose's job. If the user wants to start implementing, suggest `llman-sdd-propose`.
33
33
  - **Scope boundary**: if the description clearly involves MUST/SHALL behavioral contract changes or multi-file impact, suggest `llman-sdd-propose` instead of stopping at a draft — but still create the draft shell first so the idea isn't lost.
34
- - **Frontmatter has a fixed schema**: when fleshing out `proposal.md`, only the allowed fields in `llmanspec/AGENTS.md` "Change Proposal Frontmatter SSOT" are accepted (including `depends_on`, `blocks`, `branch`, `base_sha`, `needs_specs_change`). `status`/`title`/`priority`/`author` etc. are rejected by `llman sdd validate` as ERROR. Lifecycle stage is inferred — query it via `llman sdd show`/`list`, never store it in frontmatter. Do not re-declare frontmatter fields in the prose body (no `## Status` block); the body H1 is a human-readable title, not a repeat of the change id.
34
+ - **Frontmatter has a fixed schema**: when fleshing out `proposal.md`, only the allowed fields in `llmanspec/AGENTS.md` "Change Proposal Frontmatter SSOT" are accepted (including `depends_on`, `blocks`, `branch`, `base_sha`, `needs_specs_change`). `status`/`title`/`priority`/`author` etc. are rejected by `llman-sdd validate` as ERROR. Lifecycle stage is inferred — query it via `llman-sdd show`/`list`, never store it in frontmatter. Do not re-declare frontmatter fields in the prose body (no `## Status` block); the body H1 is a human-readable title, not a repeat of the change id.
35
35
 
36
36
  ## Steps
37
37
 
38
38
  ### 0) Preflight
39
39
  - Read `llmanspec/config.yaml` for project context, rules, locale.
40
- - `llmanspec/` must exist; if missing, tell the user to run `llman sdd init`, then STOP.
40
+ - `llmanspec/` must exist; if missing, tell the user to run `llman-sdd init`, then STOP.
41
41
 
42
42
  ### 1) Capture the description
43
43
  - Take the user's description as-is (e.g. "draft: add a export-to-json command", "note down: we should support worktrees for sdd changes").
@@ -45,7 +45,7 @@ flowchart LR
45
45
 
46
46
  ### 2) Create the draft shell
47
47
  ```bash
48
- llman sdd change new --from "<user description>"
48
+ llman-sdd change new --from "<user description>"
49
49
  ```
50
50
  - The CLI generates a legal kebab-case id (sanitized + validated), creates `llmanspec/changes/<derived id>/proposal.md` (a skeleton with `## Why` / `## What Changes` TODO sections), and prints the final id + path.
51
51
  - If the derived id collides with an existing change, the CLI fails non-zero; suggest rephrasing the description or using `--force` to overwrite (rare for drafts).
@@ -58,7 +58,7 @@ llman sdd change new --from "<user description>"
58
58
 
59
59
  > 💡 Draft captured → next: edit `proposal.md`, then `llman-sdd-propose` to formalize.
60
60
 
61
- > For command details run `llman sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
62
- > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman sdd list --specs` or `llman sdd show <capability>`.
61
+ > For command details run `llman-sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
62
+ > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman-sdd list --specs` or `llman-sdd show <capability>`.
63
63
 
64
64
  {{ unit("skills/ethics-governance") }}
@@ -43,9 +43,9 @@ flowchart LR
43
43
  - Willing to hold multiple options and tradeoffs
44
44
 
45
45
  ## Suggested moves
46
- 1. Use `llman sdd context --task "<task>" --paths "<files>"` to quickly locate relevant specs.
46
+ 1. Use `llman-sdd context --task "<task>" --paths "<files>"` to quickly locate relevant specs.
47
47
  - Read the `direct` spec files (these are the contracts you must understand).
48
- - If context is unavailable, rebuild with `llman sdd index rebuild` (default `pageindex`, no model needed) and retry.
48
+ - If context is unavailable, rebuild with `llman-sdd index rebuild` (default `pageindex`, no model needed) and retry.
49
49
  2. Clarify the goal and constraints (ask 1–3 questions).
50
50
  3. **Grilling branch (optional, only when the user explicitly triggers)**: triggers on "deep-dig" / "grill" / "one at a time" / "nail it down". Walks the decision tree one question at a time:
51
51
  - **Ask one question at a time**, with your recommended answer, waiting for feedback before the next.
@@ -54,7 +54,7 @@ flowchart LR
54
54
  - **Write decisions back**: resolved decisions go into the change's `proposal.md` "Open Questions" section (planning shell; OK briefly on the default branch).
55
55
  - **Completion criterion**: every pending decision is resolved or explicitly deferred. When not triggered, the default (ask 1–3 questions) behavior is unchanged.
56
56
  4. If a change id is relevant, read its artifacts under `llmanspec/changes/<id>/`.
57
- - When diagnosing validation errors, prefer `llman sdd validate <spec> --strict --no-check` (fast mode, skips the potentially slow `bdd.run_command`); resolve structural gates first (Gherkin / `@req` linkage / dual-write / req_id uniqueness), then run full mode (`--check` or `cargo test --features bdd`). The `FAIL <item_type>/<id>` lines in the output pin down each failing item.
57
+ - When diagnosing validation errors, prefer `llman-sdd validate <spec> --strict --no-check` (fast mode, skips the potentially slow `bdd.run_command`); resolve structural gates first (Gherkin / `@req` linkage / dual-write / req_id uniqueness), then run full mode (`--check` or `cargo test --features bdd`). The `FAIL <item_type>/<id>` lines in the output pin down each failing item.
58
58
  5. Explore options and tradeoffs (2–3 options).
59
59
  6. Assess change scale (triage) to determine if full SDD is needed.
60
60
  7. When something crystallizes, offer to capture it (don't auto-write):
@@ -72,7 +72,7 @@ If the user asks you to implement while in explore mode, STOP and remind them to
72
72
 
73
73
  > 💡 Explore done → next: `llman-sdd-propose` (propose) or `llman-sdd-quick` (quick path)
74
74
 
75
- > For command details run `llman sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
76
- > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman sdd list --specs` or `llman sdd show <capability>`.
75
+ > For command details run `llman-sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
76
+ > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman-sdd list --specs` or `llman-sdd show <capability>`.
77
77
 
78
78
  {{ unit("skills/structured-protocol") }}
@@ -19,20 +19,20 @@ Run the propose-equivalent path quickly: planning shell → Branch binding → S
19
19
  ## Steps
20
20
 
21
21
  1. Ask the user for a short description, change id (or derive), impacted capability, and confirm the final id.
22
- 2. Ensure `llman sdd init` has been run (`llmanspec/` exists).
22
+ 2. Ensure `llman-sdd init` has been run (`llmanspec/` exists).
23
23
  3. If `llmanspec/changes/<id>/` exists: ask fill-missing vs new id; do not overwrite without confirmation.
24
24
  4. Create the **planning shell** (OK briefly on the default branch):
25
- - `llman sdd change new <id>` (or hand-write) → flesh out `proposal.md`
25
+ - `llman-sdd change new <id>` (or hand-write) → flesh out `proposal.md`
26
26
  - `design.md` (if needed)
27
27
  - `tasks.md`
28
- 5. **Branch binding**: `llman sdd change start <id>` (clean tree on default branch) or create a branch then `change attach <id>`.
28
+ 5. **Branch binding**: `llman-sdd change start <id>` (clean tree on default branch) or create a branch then `change attach <id>`.
29
29
  6. **Specs landing**: on the bound branch, edit live `llmanspec/specs/<capability>.feature` (flat, or directory main file) and commit; or set `needs_specs_change: false` when there is no contract edit.
30
- 7. Validate: `llman sdd validate <id> --strict --no-interactive`.
31
- 8. Confirm `readyToImplement=true` via `llman sdd show <id> --json`, then suggest `llman-sdd-apply` (do not suggest apply before ready).
30
+ 7. Validate: `llman-sdd validate <id> --strict --no-interactive`.
31
+ 8. Confirm `readyToImplement=true` via `llman-sdd show <id> --json`, then suggest `llman-sdd-apply` (do not suggest apply before ready).
32
32
 
33
33
  {{ unit("skills/git-native-flow-brief") }}
34
- > For command details run `llman sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
35
- > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman sdd list --specs` or `llman sdd show <capability>`.
34
+ > For command details run `llman-sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
35
+ > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman-sdd list --specs` or `llman-sdd show <capability>`.
36
36
  {{ unit("skills/validation-hints") }}
37
37
 
38
38
  {{ unit("skills/ethics-governance") }}