spec-ctx 0.1.2 → 0.2.0

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.
package/README.md CHANGED
@@ -75,7 +75,7 @@ You see: a red refusal, the edit, then a green done line.
75
75
 
76
76
  ### 6. Hand off to the next session
77
77
 
78
- `handoff write` puts the state in one file: the change, the done tasks, the current task, and the open questions. The next session starts from it.
78
+ `handoff write` puts the state in one file: the change, the done tasks, the current task, and the open questions. The next session starts from it. The questions live in `.ctx/questions.json`. `handoff ask` adds one and `handoff resolve <n>` answers it.
79
79
 
80
80
  ![The head of the handoff file](docs/demo/clips/6-handoff.svg)
81
81
 
@@ -86,7 +86,7 @@ The transcript of all six clips is in `docs/demo/loop.txt`. The clips run on a c
86
86
  ## Quickstart
87
87
 
88
88
  ```bash
89
- npx -y spec-ctx init --all # config, schema, and three agent skills
89
+ npx -y spec-ctx init --all # config, ID templates, rules, and the agent skill
90
90
  npx -y spec-ctx task next # the next task and the command that proves it
91
91
  npx -y spec-ctx task start <task> # only the spec that this task needs
92
92
  npx -y spec-ctx task done <task> # runs that command. A pass ticks the box.
@@ -120,25 +120,25 @@ test tests/login.test.ts:1 active tests/login.test.ts:1 covers REQ-UA-004
120
120
 
121
121
  ## The life cycle for agents
122
122
 
123
- `init --all` installs three skills. Each one fires at a fixed point of the session.
123
+ `init --all` installs one skill, `specctx-run`. The user types one prompt, such as "build this" or "continue". The skill loops until the change reaches the archive or a human must decide.
124
124
 
125
- - `specctx-bootstrap` fires at the start of a session. It reads the status and the handoff and starts the task.
126
- - `specctx-next` fires after a task closes. It picks the next task and loads its bundle.
127
- - `specctx-done` fires when the work is complete. It runs Verify, closes the task, and writes the handoff.
125
+ - It runs `specctx next --json`. The engine reads the files on disk and prints one action: `plan`, `cite`, `start`, `work`, `fix`, `repair`, `gate`, `archive`, `ask`, or `stop`.
126
+ - It acts on the action with the exact commands, runs `specctx handoff write`, and repeats.
127
+ - It stops twice for a human by default: at the plan, and before archive. A Verify command that fails three times writes a question and stops too.
128
+ - `specctx-bootstrap`, `specctx-next`, and `specctx-done` stay for one release as aliases. Each one says: run `specctx-run`.
128
129
 
129
- The loop that the skills teach:
130
+ The commands the skill runs for one task:
130
131
 
131
132
  ```bash
132
- specctx init --all # config, schema, and the three skills
133
- specctx status # active changes, current task, open questions
134
- specctx task next # the next open task, its REQ IDs, and its Verify command
133
+ specctx init --all # config, ID templates, rules, and the skill
134
+ specctx next --json # the next action, its task, and its command
135
135
  specctx task start <task> # the bundle of that task and its size
136
136
  specctx task done <task> # run Verify, write evidence, set the checkbox
137
- specctx check --strict # IDs, links, coverage, and evidence
137
+ specctx gate --strict # check, baseline, linters, openspec validate, length
138
138
  specctx handoff write # .ctx/handoff.md for the next session
139
139
  ```
140
140
 
141
- The rule: the agent never opens `openspec/specs/` by hand. It uses `task start` or `bundle`. The skills are in [`skills/`](skills/). Install them alone with `npx skills add sonqh/spec-ctx` or `specctx init --skills`.
141
+ The rule: the agent never opens `openspec/specs/` by hand. It uses `task start` or `bundle`. It never ticks a checkbox and never runs `/opsx:apply`. The skill is in [`skills/`](skills/). Install it alone with `npx skills add sonqh/spec-ctx` or `specctx init --skills`.
142
142
 
143
143
  ## Install
144
144
 
@@ -152,27 +152,30 @@ npx -y github:sonqh/spec-ctx#<sha> init --all # from git, for an unreleas
152
152
 
153
153
  The git form builds the package on install with Node only. Pin a commit SHA. A branch name such as `main` also works, but it moves.
154
154
 
155
- The command writes `spec-ctx.toml`, installs the `spec-driven-ids` schema into `openspec/schemas/`, adds its rules to `openspec/config.yaml`, and installs three skills into `.claude/skills/` and `.agents/skills/`.
155
+ The command writes `spec-ctx.toml`, copies the templates with ID placeholders to `openspec/templates/spec-driven-ids/`, adds the spec-ctx `rules` and `operations` to `openspec/config.yaml`, and installs the `specctx-run` skill and its three aliases into `.claude/skills/` and `.agents/skills/`. The project keeps the stock `schema: spec-driven`. Upstream OpenSpec injects the rules into every artifact instruction. It pins the OpenSpec version it finds in `[gate] openspec`. It adds four lines to `.gitignore`: `.ctx/index.json`, `adopt-report.md`, `.ctx/current.json`, and `.ctx/gate-log.jsonl`. The rest of `.ctx/` is meant for git, `questions.json` included.
156
156
 
157
157
  The examples below use `specctx`. With `npx`, write `npx -y spec-ctx` in its place. Each GitHub release also carries a single binary for Linux and macOS.
158
158
 
159
159
  ## Two paths
160
160
 
161
+ [`docs/getting-started.md`](docs/getting-started.md) walks the fresh path on upstream OpenSpec with real output, for a developer who knows OpenSpec.
162
+
161
163
  ### Fresh project
162
164
 
163
165
  ```bash
164
- npx -y @fission-ai/openspec@latest init
166
+ npx -y @fission-ai/openspec@latest init --tools <tool>
165
167
  npx spec-ctx init --all
166
168
  specctx gate --strict
167
169
  ```
168
170
 
171
+ `--tools <tool>` names your agent, such as `claude`, and skips the interactive picker. `--no-animation` keeps logs clean. `init --all` merges the ID rules into an existing `rules` key of `openspec/config.yaml` item by item and prints `merged openspec/config.yaml rules (<n> added)`.
172
+
169
173
  ### Existing OpenSpec project
170
174
 
171
175
  ```bash
172
176
  npx spec-ctx init --all
173
177
  specctx adopt --dry-run # the ID that each header gets. Writes nothing.
174
178
  specctx adopt # writes the IDs into main specs and active deltas
175
- specctx task backfill --manual "adopted"
176
179
  specctx baseline write
177
180
  specctx gate --strict
178
181
  ```
@@ -180,12 +183,12 @@ specctx gate --strict
180
183
  - `adopt` gives an ID to every requirement and scenario header without one, in `openspec/specs/` and in the deltas of active changes. A delta header gets the main ID by its text or through its RENAMED line. A delta header that matches neither keeps its text and goes into `adopt-report.md`.
181
184
  - `adopt` derives a capability code from each folder name, for example `UA` for `user-auth`. It writes the codes into `spec-ctx.toml`. Rename a code there before the IDs spread.
182
185
  - `adopt` runs `check` before and after the write. A finding that the write added undoes every file. A second run prints `nothing to adopt`.
183
- - `task backfill` writes manual evidence for every ticked task that has none.
184
- - `baseline write` records the debt of the day in `.ctx/baseline.json`. The debt has five kinds. Untested requirements and scenarios. Tasks without evidence. Legacy tasks without a citation or a Verify code span. Delta headers that match no main requirement. Hard lint findings per file and rule on the gate globs. `check` hides that debt and prints `baselined: <n>`. `gate` fails the lint step only when a count rises. New debt still shows.
185
- - `[gate] markdown` in `spec-ctx.toml` names the markdown globs that `gate` lints. Narrow it when a folder is not yours to fix.
186
+ - `baseline write` records the debt of the day in `.ctx/baseline.json`. The debt has five kinds. Ticked tasks without evidence. Legacy tasks without a citation or a Verify code span. Delta headers that match no main requirement. Hard lint findings per file and rule on the gate globs. `check` hides that debt and prints `baselined: <n>`. `gate` fails the lint step only when a count rises. New debt still shows.
187
+ - `gate` compares `.ctx/baseline.json` with the copy at the merge base of `HEAD` and `[gate] base`, default `origin/main`. A new entry fails the `baseline` step. Commit a grown baseline with a subject that starts with `baseline:` to pass once. In CI, check out with `fetch-depth: 0`, so the merge base exists. Without git or a merge base the step prints `skipped`.
188
+ - `[gate] markdown` in `spec-ctx.toml` names the markdown globs that `gate` lints. `init` writes `[]`, so the gate lints nothing until you opt in. The comment in the file names the globs this repository uses.
186
189
  - Legacy tasks stay in the baseline until an agent adds `[REQ-...]` citations and a `Verify:` code span. `specctx baseline prune` then drops them. No command adds a single entry.
187
190
 
188
- Both paths have an end to end test: `tests/paths/fresh.sh` and `tests/paths/existing.sh`.
191
+ Both paths have an end to end test on upstream OpenSpec: `tests/paths/fresh.sh` and `tests/paths/existing.sh`. `tests/paths/rules-only.sh` shows that the merged `rules` reach the stock `spec-driven` schema.
189
192
 
190
193
  ## Commands
191
194
 
@@ -193,18 +196,18 @@ Both paths have an end to end test: `tests/paths/fresh.sh` and `tests/paths/exis
193
196
  | --- | --- |
194
197
  | `build` | Write `.ctx/index.json`. Every other command rebuilds a stale index first. |
195
198
  | `status` | Active changes with task counts, the current task, and open questions. |
199
+ | `next` | The next action of the loop from the files on disk: `plan`, `cite`, `start`, `work`, `fix`, `repair`, `gate`, `archive`, `ask`, or `stop`. `--json` prints one object. Flag: `--change`. |
196
200
  | `query <term...>` | Entries that hold every term. Flags: `--kind`, `--change`, `--limit`, `--all`. |
197
201
  | `related <ID>` | Linked entries with the reason for each link. Flags: `--depth`, `--all`. |
198
202
  | `bundle <ID...>` | Spec text of the IDs, their scenarios, decisions, and neighbors. Flags: `--budget`, `--depth`, `--all`. |
199
- | `check` | ID and link integrity. `--strict` adds test coverage and evidence. |
203
+ | `check` | ID and link integrity. `--strict` adds test coverage and evidence. `retitle-needs-renamed` names a retitled delta header that needs a RENAMED pair before `openspec archive`. |
200
204
  | `id new`, `id retire` | Allocate and retire IDs. |
201
205
  | `task next`, `start`, `verify`, `done`, `reopen` | The task state machine. |
202
- | `handoff write`, `ask`, `resolve` | The session handoff and its open questions. |
203
- | `init` | Config file, schema bundle, and skills. Flags: `--schema`, `--skills`, `--all`, `--force`. |
206
+ | `handoff write`, `ask`, `resolve` | The session handoff and its open questions in `.ctx/questions.json`. |
207
+ | `init` | Config file, ID templates and rules, and skills. Flags: `--schema`, `--skills`, `--all`, `--force`. |
204
208
  | `adopt` | IDs for a project without them. `--dry-run` writes nothing. |
205
209
  | `baseline write`, `prune` | The debt ratchet in `.ctx/baseline.json`. |
206
- | `task backfill` | Manual evidence for ticked tasks without it. |
207
- | `gate` | `check`, both markdown linters, `openspec validate`, and the 500 character length check on active deltas. |
210
+ | `gate` | `check`, the baseline against the merge base, both markdown linters, `openspec validate`, and the 500 character length check on active deltas. |
208
211
  | `lint tells`, `lint ste` | The two markdown linters. Flags: `--baseline`, `--disable`, `--json`, `--selftest`. |
209
212
  | `help <command>` | The page of one command. `specctx <command> --help` prints the same page. |
210
213
 
@@ -226,6 +229,7 @@ ignore = [] # globs that the scan skips
226
229
  [ids]
227
230
  caps = [] # capability codes. Empty means any code is valid.
228
231
  task_pattern = '\d+\.\d+' # the task number in a tasks.md checkbox
232
+ brackets = false # true: adopt and id new write [REQ-UA-001]. The scan reads both forms.
229
233
 
230
234
  [ids.paths]
231
235
  UA = "user-auth" # capability path of each code. adopt writes the derived ones.
@@ -236,13 +240,23 @@ depth = 1
236
240
 
237
241
  [verify]
238
242
  timeout_s = 600
243
+
244
+ [gate]
245
+ markdown = [] # globs that gate lints. Empty means no lint. This repo opts in.
246
+ openspec = "npx -y @fission-ai/openspec@1.15.0" # the command that runs OpenSpec. init pins the version it found.
247
+ base = "origin/main" # the ref whose merge base holds the baseline that gate compares with
248
+
249
+ [loop]
250
+ max_attempts = 3 # Verify failures on one task before task done writes a question
251
+ archive = "ask" # "ask" stops before archive for a human. "auto" lets the loop archive.
239
252
  ```
240
253
 
241
- One environment variable changes the engine:
254
+ Two environment variables change the engine:
242
255
 
243
256
  | Variable | Effect |
244
257
  | --- | --- |
245
- | `SPECCTX_OPENSPEC` | The command that `gate` runs for `openspec validate`. The default is `npx -y @fission-ai/openspec@latest`. Tests and offline machines set it. |
258
+ | `SPECCTX_OPENSPEC` | The command that `gate` runs for `openspec validate` and `next` runs for `openspec status`. It overrides `[gate] openspec` for one run. At `init` time it is written into the file as it is, and no version detection runs. Tests and offline machines set it. |
259
+ | `SPECCTX_BASELINE_SUBJECT` | The commit subject that the `baseline` step of `gate` tests for `baseline:`. It replaces the subject of `HEAD`. Tests set it. |
246
260
 
247
261
  ## Markdown linters
248
262
 
@@ -270,18 +284,18 @@ The action runs `specctx gate`: `check --strict`, both markdown linters, `opensp
270
284
 
271
285
  ## Status
272
286
 
273
- - Published: `spec-ctx@0.1.2` on npm, with tags `v0.1.2` and `v0` and binaries on the GitHub release.
274
- - Archived: 001 to 017. No change is open. See `CHANGELOG.md` for each release.
287
+ - Published: `spec-ctx@0.2.0` on npm, with tags `v0.2.0` and `v0` and binaries on the GitHub release.
288
+ - Archived: 001 to 025, and 027. No change is open. See `CHANGELOG.md` for each release.
275
289
  - A version bump on `main` publishes the next release. See `docs/CONTRIBUTING.md`.
276
290
  - Upstream: the ID scheme is proposed as a comment on [OpenSpec#1967](https://github.com/Fission-AI/OpenSpec/issues/1967#issuecomment-6414314730). The schema bundle is submitted to the community table in [OpenSpec#2157](https://github.com/Fission-AI/OpenSpec/issues/2157). No pull request until a maintainer asks.
277
291
 
278
292
  ## Measured
279
293
 
280
- `specctx stats --write` measures this repository after each change. The newest file is `docs/metrics/2026-10-27.md`. Its total row:
294
+ `specctx stats --write` measures this repository after each change. The newest file is `docs/metrics/2026-10-29.md`. Its total row:
281
295
 
282
296
  | change | context_ratio | evidence_ratio | stale_catches | cycle_time_median_s | debt |
283
297
  | --- | --- | --- | --- | --- | --- |
284
- | total | 0.0435 (n=52) | 0.87 (106/122) | 36 (of 68 reopens) | 70 (n=52) | 0 (0 baselined + 0 new) |
298
+ | total | 0.0327 (n=76) | 0.90 (143/159) | 36 (of 81 reopens) | 98 (n=76) | 0 (0 baselined + 0 new) |
285
299
 
286
300
  - `context_ratio`: the size of one task bundle divided by the size of all spec text. Lower is better.
287
301
  - `evidence_ratio`: done tasks with a passed Verify command, divided by all done tasks. The rest have a manual note. Higher is better.
@@ -8,6 +8,9 @@ const REQ_HDR = /^### Requirement:[ \t]*(.*)$/s;
8
8
  const SCN_HDR = /^#### Scenario:[ \t]*(.*)$/s;
9
9
  const HAS_REQ = /^REQ-([A-Z]{2,6})-(\d{3})(?:[ \t]|$)/;
10
10
  const HAS_SCN = /^SCN-([A-Z]{2,6})-(\d{3})-(\d+)(?:[ \t]|$)/;
11
+ // REQ-ADOPT-010 an ID in square brackets, the form of OpenSpec PR #1979 (027/D3)
12
+ const BR_REQ = /^\[(REQ-[A-Z]{2,6}-\d{3})\](?:[ \t]|$)/;
13
+ const BR_SCN = /^\[(SCN-[A-Z]{2,6}-\d{3}-\d+)\](?:[ \t]|$)/;
11
14
  const RENAME = /^- (FROM|TO):[ \t]*`### Requirement:[ \t]*(.*)`[ \t]*$/s;
12
15
  function listSpecs(root, base) {
13
16
  const out = [];
@@ -26,12 +29,15 @@ function listSpecs(root, base) {
26
29
  walk(join(root, base), base);
27
30
  return out;
28
31
  }
29
- function splitId(text, re) {
32
+ /** REQ-ADOPT-010 the ID at the start of a header text, bare or in square brackets, and the name after it. */
33
+ function splitId(text, re, br) {
30
34
  const m = re.exec(text);
31
- if (!m)
32
- return { id: null, name: text.trim() };
33
- const id = m[0].trim();
34
- return { id, name: text.slice(m[0].length).trim() };
35
+ if (m)
36
+ return { id: m[0].trim(), name: text.slice(m[0].length).trim(), bracketed: false };
37
+ const b = br.exec(text);
38
+ if (b)
39
+ return { id: b[1], name: text.slice(b[0].length).trim(), bracketed: true };
40
+ return { id: null, name: text.trim(), bracketed: false };
35
41
  }
36
42
  function parse(root, rel, cap) {
37
43
  const lines = splitLines(readFileSync(join(root, rel)).toString("utf8"));
@@ -53,21 +59,21 @@ function parse(root, rel, cap) {
53
59
  }
54
60
  let m = REQ_HDR.exec(line);
55
61
  if (m) {
56
- const { id, name } = splitId(m[1], HAS_REQ);
57
- req = { kind: "req", line: i + 1, raw: line, name, id, section };
62
+ const { id, name, bracketed } = splitId(m[1], HAS_REQ, BR_REQ);
63
+ req = { kind: "req", line: i + 1, raw: line, name, id, bracketed, section };
58
64
  blocks.push(req);
59
65
  return;
60
66
  }
61
67
  m = SCN_HDR.exec(line);
62
68
  if (m) {
63
- const { id, name } = splitId(m[1], HAS_SCN);
64
- blocks.push({ kind: "scn", line: i + 1, raw: line, name, id, req, section });
69
+ const { id, name, bracketed } = splitId(m[1], HAS_SCN, BR_SCN);
70
+ blocks.push({ kind: "scn", line: i + 1, raw: line, name, id, bracketed, req, section });
65
71
  return;
66
72
  }
67
73
  m = RENAME.exec(line);
68
74
  if (m && section === "RENAMED") {
69
- const { id, name } = splitId(m[2], HAS_REQ);
70
- const item = { line: i + 1, name, id, raw: line };
75
+ const { id, name, bracketed } = splitId(m[2], HAS_REQ, BR_REQ);
76
+ const item = { line: i + 1, name, id, bracketed, raw: line };
71
77
  if (m[1] === "FROM")
72
78
  from = item;
73
79
  else if (from) {
@@ -189,11 +195,15 @@ export function planAdopt(root, cfg) {
189
195
  };
190
196
  const edits = [];
191
197
  const unmatched = [];
192
- const reqHeader = (id, name) => `### Requirement: ${id} ${name}`;
193
- const scnHeader = (id, name) => `#### Scenario: ${id} ${name}`;
198
+ // REQ-ADOPT-010 the configured form of a new ID: bare, or in square brackets (027/D3)
199
+ const form = (id, br = cfg.ids.brackets) => (br ? `[${id}]` : id);
200
+ const reqHeader = (id, name, br) => `### Requirement: ${form(id, br)} ${name}`;
201
+ const scnHeader = (id, name) => `#### Scenario: ${form(id)} ${name}`;
194
202
  // main spec: requirement id by name, and scenario id by requirement and name
195
203
  const mainReq = new Map();
196
204
  const mainScn = new Map();
205
+ // the form of each main header after adopt: its own form when it had an ID, else the configured form
206
+ const mainBr = new Map();
197
207
  for (const f of mainFiles) {
198
208
  const code = codeFor.get(f.cap);
199
209
  const seen = new Set();
@@ -210,6 +220,7 @@ export function planAdopt(root, cfg) {
210
220
  if (!b.id)
211
221
  edits.push({ file: f.rel, line: b.line, old: b.raw, new: reqHeader(id, b.name) });
212
222
  mainReq.set(`${f.cap}\u0000${b.name}`, id);
223
+ mainBr.set(`${f.cap}\u0000${b.name}`, b.id ? b.bracketed : cfg.ids.brackets);
213
224
  b.id = id;
214
225
  }
215
226
  else if (b.req?.id) {
@@ -232,8 +243,9 @@ export function planAdopt(root, cfg) {
232
243
  continue;
233
244
  }
234
245
  renamedTo.set(r.to.name, id);
246
+ // REQ-ADOPT-010 the FROM line names the main header, so it takes the form of that header (027/D3)
235
247
  if (!r.from.id)
236
- edits.push({ file: f.rel, line: r.from.line, old: r.from.raw, new: `- FROM: \`${reqHeader(id, r.from.name)}\`` });
248
+ edits.push({ file: f.rel, line: r.from.line, old: r.from.raw, new: `- FROM: \`${reqHeader(id, r.from.name, mainBr.get(`${f.cap}\u0000${r.from.name}`))}\`` });
237
249
  if (!r.to.id)
238
250
  edits.push({ file: f.rel, line: r.to.line, old: r.to.raw, new: `- TO: \`${reqHeader(id, r.to.name)}\`` });
239
251
  }
@@ -1,14 +1,14 @@
1
1
  // Generated by scripts/gen-assets.mjs from schemas/spec-driven-ids/ and skills/. Do not edit.
2
- // REQ-SCH-001 REQ-SKL-002
2
+ // REQ-SCH-003 REQ-SKL-002
3
3
  export const ASSETS = {
4
- "schemas/spec-driven-ids/README.md": "IyBzcGVjLWRyaXZlbi1pZHMKCkEgZm9yayBvZiB0aGUgT3BlblNwZWMgYHNwZWMtZHJpdmVuYCBzY2hlbWEuIEl0IGFkZHMgc3RhYmxlIElEcyBmcm9tIHNwZWMtY3R4IHRvIGV2ZXJ5IGFydGlmYWN0LgoKLSBUaGUgc3BlYyB0ZW1wbGF0ZSBzdGFydHMgZWFjaCByZXF1aXJlbWVudCB3aXRoIGBSRVEtPENBUD4tTk5OYCBhbmQgZWFjaCBzY2VuYXJpbyB3aXRoIGBTQ04tPENBUD4tTk5OLTxuPmAuCi0gVGhlIGluc3RydWN0aW9ucyB0ZWxsIHRoZSBhZ2VudCB0byBnZXQgSURzIGZyb20gYHNwZWNjdHggaWQgbmV3YCBhbmQgdG8gbGluayBJRHMgd2l0aCBgUmVmczpgIGxpbmVzLgotIFRoZSB0YXNrcyB0ZW1wbGF0ZSBjaXRlcyBSRVEgSURzIGFuZCBwdXRzIHRoZSBgVmVyaWZ5OmAgY29tbWFuZCBpbiBhIGNvZGUgc3Bhbiwgc28gYHNwZWNjdHggdGFzayBkb25lYCBjYW4gcnVuIGl0LgotIGBjb25maWctZnJhZ21lbnQueWFtbGAgaG9sZHMgdGhlIGBydWxlc2AgYW5kIGBvcGVyYXRpb25zYCBmb3IgYG9wZW5zcGVjL2NvbmZpZy55YW1sYC4KCiMjIEluc3RhbGwgYnkgY29weQoKLSBDbG9uZSB0aGUgcmVwb3NpdG9yeTogYGdpdCBjbG9uZSBodHRwczovL2dpdGh1Yi5jb20vc29ucWgvc3BlYy1jdHhgLgotIENvcHkgYHNjaGVtYXMvc3BlYy1kcml2ZW4taWRzYCB0byBgb3BlbnNwZWMvc2NoZW1hcy9zcGVjLWRyaXZlbi1pZHNgIGluIHlvdXIgcHJvamVjdC4KLSBTZXQgYHNjaGVtYTogc3BlYy1kcml2ZW4taWRzYCBpbiBgb3BlbnNwZWMvY29uZmlnLnlhbWxgLgotIE1lcmdlIGBjb25maWctZnJhZ21lbnQueWFtbGAgaW50byBgb3BlbnNwZWMvY29uZmlnLnlhbWxgIGJ5IGhhbmQuIEFkZCBpdHMgYHJ1bGVzYCBhbmQgYG9wZXJhdGlvbnNgIGtleXMuIEtlZXAgZXZlcnkgaXRlbSBxdW90ZWQuCi0gUnVuIGBvcGVuc3BlYyBzY2hlbWEgdmFsaWRhdGUgc3BlYy1kcml2ZW4taWRzYC4KCiMjIEluc3RhbGwgd2l0aCBpbml0IC0tc2NoZW1hCgpgYGBiYXNoCm5weCAteSBzcGVjLWN0eCBpbml0IC0tc2NoZW1hCmBgYAoKLSBUaGUgY29tbWFuZCBjb3BpZXMgdGhpcyBmb2xkZXIgdG8gYG9wZW5zcGVjL3NjaGVtYXMvc3BlYy1kcml2ZW4taWRzL2AuCi0gSXQgc2V0cyBgc2NoZW1hOiBzcGVjLWRyaXZlbi1pZHNgIGluIGBvcGVuc3BlYy9jb25maWcueWFtbGAuCi0gSXQgYWRkcyB0aGUgYHJ1bGVzYCBhbmQgYG9wZXJhdGlvbnNgIGtleXMgdGhhdCB0aGUgY29uZmlnIGRvZXMgbm90IGhhdmUgeWV0LiBJdCBsZWF2ZXMgb3RoZXIga2V5cyBhcyB0aGV5IGFyZS4KLSBJdCBxdW90ZXMgYSBsaXN0IGl0ZW0gdGhhdCBZQU1MIHdvdWxkIHJlYWQgYXMgYSBtYXBwaW5nLgoKIyMgVmVyc2lvbgoKRm9ya2VkIGZyb20gT3BlblNwZWMgMS4xNC4zIHdpdGggYG9wZW5zcGVjIHNjaGVtYSBmb3JrIHNwZWMtZHJpdmVuIHNwZWMtZHJpdmVuLWlkc2AuIENJIHZhbGlkYXRlcyBpdCBhZ2FpbnN0IHRoYXQgdmVyc2lvbi4K",
5
- "schemas/spec-driven-ids/config-fragment.yaml": "IyBzcGVjLWN0eCBmcmFnbWVudCBmb3Igb3BlbnNwZWMvY29uZmlnLnlhbWwuIHNwZWNjdHggaW5pdCAtLXNjaGVtYSBhZGRzIGVhY2ggdG9wLWxldmVsIGtleQojIHRoYXQgdGhlIHByb2plY3QgY29uZmlnIGRvZXMgbm90IGhhdmUgeWV0LiBJdCBuZXZlciBjaGFuZ2VzIGEga2V5IHRoYXQgZXhpc3RzLgpydWxlczoKICBzcGVjczoKICAgIC0gJ0V2ZXJ5IHJlcXVpcmVtZW50IGhlYWRlciBzdGFydHMgd2l0aCBpdHMgSUQsIGUuZy4gIiMjIyBSZXF1aXJlbWVudDogUkVRLUFCQy0wMDEgTmFtZSIuIEdldCB0aGUgSUQgZnJvbSBgc3BlY2N0eCBpZCBuZXcgUkVRIEFCQ2AuJwogICAgLSAnRXZlcnkgc2NlbmFyaW8gaGVhZGVyIHN0YXJ0cyB3aXRoIGl0cyBJRCwgZS5nLiAiIyMjIyBTY2VuYXJpbzogU0NOLUFCQy0wMDEtMSBOYW1lIi4nCiAgICAtICdBIHJlcXVpcmVtZW50IG1heSBlbmQgd2l0aCBhIGxpbmUgIlJlZnM6IFJFUS1BQkMtMDAyLCBBRFItMDAxIiB0byBsaW5rIHJlbGF0ZWQgSURzLicKICAgIC0gJ1JlcXVpcmVtZW50IHRleHQgc3RheXMgdW5kZXIgNTAwIGNoYXJhY3RlcnMuIE1vdmUgZGV0YWlsIGludG8gc2NlbmFyaW9zLicKICBkZXNpZ246CiAgICAtICdFYWNoIGRlY2lzaW9uIGlzIG9uZSBidWxsZXQgdW5kZXIgIiMjIERlY2lzaW9ucyIuIEFkZCBuZXcgZGVjaXNpb25zIGF0IHRoZSBlbmQuJwogIHRhc2tzOgogICAgLSAnRXZlcnkgdGFzayBjaXRlcyBhdCBsZWFzdCBvbmUgUkVRIElEIGluIHNxdWFyZSBicmFja2V0cywgZS5nLiAiW1JFUS1BQkMtMDAxXSIuJwogICAgLSAnRXZlcnkgdGFzayBzdGF0ZXMgaXRzIHZlcmlmaWNhdGlvbiBhcyBhIGNvbW1hbmQgaW4gYSBjb2RlIHNwYW4gYWZ0ZXIgIlZlcmlmeToiLicKCm9wZXJhdGlvbnM6CiAgYXBwbHk6CiAgICBndWlkYW5jZToKICAgICAgLSAnU3RhcnQgZWFjaCB0YXNrIHdpdGggYHNwZWNjdHggdGFzayBzdGFydCA8aWQ+YCBhbmQgcmVhZCB0aGUgYnVuZGxlIGl0IHByaW50cyBiZWZvcmUgeW91IHJlYWQgc3BlY3MuJwogICAgICAtICdUYWcgY29kZSB3aXRoIHRoZSBSRVEgSUQgaXQgaW1wbGVtZW50cyAoYSBjb21tZW50IGAvLyBSRVEtQUJDLTAwMWApLiBUYWcgdGVzdHMgd2l0aCBgLy8gQ292ZXJzOiBSRVEtQUJDLTAwMWAuJwogICAgICAtICdDbG9zZSBlYWNoIHRhc2sgd2l0aCBgc3BlY2N0eCB0YXNrIGRvbmUgPGlkPmAuIE5ldmVyIHRpY2sgYSBjaGVja2JveCBieSBoYW5kLicKICAgICAgLSAnUnVuIGBzcGVjY3R4IGNoZWNrIC0tc3RyaWN0YCBhZnRlciBlYWNoIHRhc2sgZ3JvdXAuJwogIGFyY2hpdmU6CiAgICBndWlkYW5jZToKICAgICAgLSAnUnVuIGBzcGVjY3R4IGNoZWNrIC0tc3RyaWN0YCBhbmQgYG9wZW5zcGVjIHZhbGlkYXRlIC0tYWxsIC0tc3RyaWN0YC4gQm90aCBtdXN0IHBhc3MgYmVmb3JlIGFyY2hpdmUuJwogICAgICAtICdSdW4gYG9wZW5zcGVjIHZhbGlkYXRlIC0tYWxsIC0tc3RyaWN0YCBhZ2FpbiBhZnRlciBhcmNoaXZlIGFuZCBiZWZvcmUgcHVzaC4nCg==",
6
- "schemas/spec-driven-ids/schema.yaml": "bmFtZTogc3BlYy1kcml2ZW4taWRzCnZlcnNpb246IDEKZGVzY3JpcHRpb246IE9wZW5TcGVjIHNwZWMtZHJpdmVuIHdvcmtmbG93IHdpdGggc3RhYmxlIElEcyBmcm9tIHNwZWMtY3R4IC0gcHJvcG9zYWwg4oaSIHNwZWNzIOKGkiBkZXNpZ24g4oaSIHRhc2tzCmFydGlmYWN0czoKICAtIGlkOiBwcm9wb3NhbAogICAgZ2VuZXJhdGVzOiBwcm9wb3NhbC5tZAogICAgZGVzY3JpcHRpb246IEluaXRpYWwgcHJvcG9zYWwgZG9jdW1lbnQgb3V0bGluaW5nIHRoZSBjaGFuZ2UKICAgIHRlbXBsYXRlOiBwcm9wb3NhbC5tZAogICAgaW5zdHJ1Y3Rpb246IHwKICAgICAgQ3JlYXRlIHRoZSBwcm9wb3NhbCBkb2N1bWVudCB0aGF0IGVzdGFibGlzaGVzIFdIWSB0aGlzIGNoYW5nZSBpcyBuZWVkZWQuCgogICAgICBTZWN0aW9uczoKICAgICAgLSAqKldoeSoqOiAxLTIgc2VudGVuY2VzIG9uIHRoZSBwcm9ibGVtIG9yIG9wcG9ydHVuaXR5LiBXaGF0IHByb2JsZW0gZG9lcyB0aGlzIHNvbHZlPyBXaHkgbm93PwogICAgICAtICoqV2hhdCBDaGFuZ2VzKio6IEJ1bGxldCBsaXN0IG9mIGNoYW5nZXMuIEJlIHNwZWNpZmljIGFib3V0IG5ldyBjYXBhYmlsaXRpZXMsIG1vZGlmaWNhdGlvbnMsIG9yIHJlbW92YWxzLiBNYXJrIGJyZWFraW5nIGNoYW5nZXMgd2l0aCAqKkJSRUFLSU5HKiouCiAgICAgIC0gKipDYXBhYmlsaXRpZXMqKjogSWRlbnRpZnkgd2hpY2ggc3BlY3Mgd2lsbCBiZSBjcmVhdGVkIG9yIG1vZGlmaWVkOgogICAgICAgIC0gKipOZXcgQ2FwYWJpbGl0aWVzKio6IExpc3QgY2FwYWJpbGl0aWVzIGJlaW5nIGludHJvZHVjZWQuIEVhY2ggYmVjb21lcyBhIG5ldyBgc3BlY3MvPGNhcGFiaWxpdHktcGF0aD4vc3BlYy5tZGAuIE5hbWUgZWFjaCBjYXBhYmlsaXR5IGZvciBhIGR1cmFibGUgc3lzdGVtIGJlaGF2aW9yIChmb3IgZXhhbXBsZSwgYHVzZXItYXV0aGApLCBub3QgdGhlIHdvcmsgaW4gdGhpcyBjaGFuZ2UgKGZvciBleGFtcGxlLCBgYWRkLWxvZ2luLWVuZHBvaW50YCkuIENob29zZSBhIGNvaGVzaXZlIGJvdW5kYXJ5IHRoYXQgY2FuIG93biByZWxhdGVkIHJlcXVpcmVtZW50cyBhcyB0aGUgc3lzdGVtIGV2b2x2ZXM7IGF2b2lkIGJyb2FkIGNhdGNoLWFsbCBjYXBhYmlsaXRpZXMuIFVzZSBrZWJhYi1jYXNlIGZvciBwYXRoIHNlZ21lbnRzIHlvdSBpbnRyb2R1Y2UgKGUuZy4sIGB1c2VyLWF1dGhgIG9yIGBpZGVudGl0eS91c2VyLWF1dGhgKSBhbmQgZm9sbG93IHRoZSBwcm9qZWN0J3MgZXhpc3Rpbmcgc3BlYyBvcmdhbml6YXRpb24uCiAgICAgICAgLSAqKk1vZGlmaWVkIENhcGFiaWxpdGllcyoqOiBMaXN0IGV4aXN0aW5nIGNhcGFiaWxpdGllcyB3aG9zZSBSRVFVSVJFTUVOVFMgYXJlIGNoYW5naW5nLiBPbmx5IGluY2x1ZGUgaWYgc3BlYy1sZXZlbCBiZWhhdmlvciBjaGFuZ2VzIChub3QganVzdCBpbXBsZW1lbnRhdGlvbiBkZXRhaWxzKS4gRWFjaCBuZWVkcyBhIGRlbHRhIHNwZWMgZmlsZS4gVXNlIHRoZSBleGFjdCBleGlzdGluZyBwYXRoIHVuZGVyIGBvcGVuc3BlYy9zcGVjcy9gLiBMZWF2ZSBlbXB0eSBpZiBubyByZXF1aXJlbWVudCBjaGFuZ2VzLgogICAgICAtICoqSW1wYWN0Kio6IEFmZmVjdGVkIGNvZGUsIEFQSXMsIGRlcGVuZGVuY2llcywgb3Igc3lzdGVtcy4KCiAgICAgIElNUE9SVEFOVDogVGhlIENhcGFiaWxpdGllcyBzZWN0aW9uIGlzIGNyaXRpY2FsLiBJdCBjcmVhdGVzIHRoZSBjb250cmFjdCBiZXR3ZWVuCiAgICAgIHByb3Bvc2FsIGFuZCBzcGVjcyBwaGFzZXMuIFJlc2VhcmNoIGV4aXN0aW5nIHNwZWNzIGJlZm9yZSBmaWxsaW5nIHRoaXMgaW46CiAgICAgIHJ1biBgb3BlbnNwZWMgbGlzdCAtLXNwZWNzYCBmb3IgdGhlIHByb2plY3QncyBjYXBhYmlsaXR5IGludmVudG9yeSwgdGhlbgogICAgICBgb3BlbnNwZWMgc2hvdyAiPHNwZWMtaWQ+IiAtLXR5cGUgc3BlYyAtLWpzb24gLS1uby1zY2VuYXJpb3NgIGZvciBhbnkgdGhhdAogICAgICBsb29rIHJlbGF0ZWQgLSB0aGF0IHJldHVybnMgYSBjYXBhYmlsaXR5J3MgcHVycG9zZSBhbmQgcmVxdWlyZW1lbnQgdGV4dHMKICAgICAgd2l0aG91dCBwdWxsaW5nIHdob2xlIHNwZWMgZmlsZXMgaW50byBjb250ZXh0LiBBcHBlbmQgYC0tc3RvcmUgIjxpZD4iYCB0bwogICAgICBib3RoIGNvbW1hbmRzIG9ubHkgZm9yIGEgcmVnaXN0ZXJlZCBzdGFuZGFsb25lIHN0b3JlLCBhbmQga2VlcCBgLS10eXBlCiAgICAgIHNwZWNgOiBhIGNoYW5nZSBhbmQgYSBzcGVjIHNoYXJpbmcgYSBuYW1lIGlzIG90aGVyd2lzZSBhbiBhbWJpZ3VvdXMtaXRlbQogICAgICBlcnJvci4gYG9wZW5zcGVjIGxpc3RgIHdpdGhvdXQgYC0tc3BlY3NgIGxpc3RzIGluLWZsaWdodCBjaGFuZ2VzLCBub3QKICAgICAgc3BlY3MgLSBpdCBuZXZlciBzaG93cyB3aGF0IHRoZSBwcm9qZWN0IGFscmVhZHkgY292ZXJzLiBSZXVzZSBhbiBleGlzdGluZwogICAgICBjYXBhYmlsaXR5J3MgZXhhY3QgcGF0aCBpbnN0ZWFkIG9mIGludHJvZHVjaW5nIGEgbmVhci1kdXBsaWNhdGUgbmFtZS4KICAgICAgVGhlIGZpbHRlcmVkIHJlYWQgaXMgb25seSBhbiBvdmVydmlldy4gQmVmb3JlIGRlY2lkaW5nIHdoYXQgaXMgYWxyZWFkeQogICAgICBjb3ZlcmVkIG9yIHdoYXQgc2hvdWxkIGNoYW5nZSwgcmVhZCBlYWNoIHJlbGV2YW50IHNwZWMgaW4gZnVsbCwgaW5jbHVkaW5nCiAgICAgIHNjZW5hcmlvcywgd2l0aCBgb3BlbnNwZWMgc2hvdyAiPHNwZWMtaWQ+IiAtLXR5cGUgc3BlY2AgKHNhbWUgYC0tc3RvcmVgIHJ1bGUpLgogICAgICBFYWNoIGNhcGFiaWxpdHkgbGlzdGVkIGhlcmUgd2lsbCBuZWVkIGEgY29ycmVzcG9uZGluZyBzcGVjIGZpbGUuCgogICAgICBFdmVyeSBjaGFuZ2UgbXVzdCBlaXRoZXIgZGVjbGFyZSBhdCBsZWFzdCBvbmUgY2FwYWJpbGl0eSAobmV3IG9yCiAgICAgIG1vZGlmaWVkKSBvciBleHBsaWNpdGx5IG9wdCBvdXQgb2Ygc3BlY3M6IGBvcGVuc3BlYyB2YWxpZGF0ZWAgcmVqZWN0cyBhCiAgICAgIGNoYW5nZSB3aXRoIHplcm8gZGVsdGFzIHVubGVzcyB0aGUgY2hhbmdlJ3MgYC5vcGVuc3BlYy55YW1sYCBzZXRzCiAgICAgIGBza2lwX3NwZWNzOiB0cnVlYC4gVXNlIGBza2lwX3NwZWNzOiB0cnVlYCBvbmx5IHdoZW4gbm8gc3BlYy1sZXZlbAogICAgICBiZWhhdmlvciBjaGFuZ2VzIChwdXJlIHJlZmFjdG9yLCB0b29saW5nLCBkb2NzKSAtIHNwZWNzIGRlc2NyaWJlCiAgICAgIGJlaGF2aW9yLCBzbyBpZiBiZWhhdmlvciBkb2VzIG5vdCBjaGFuZ2UsIG5vIHNwZWMgc2hvdWxkIGNoYW5nZSBlaXRoZXIuCiAgICAgIERvIG5vdCBpbnZlbnQgYSByZXF1aXJlbWVudCBqdXN0IHRvIHNhdGlzZnkgdmFsaWRhdGlvbi4KCiAgICAgIEtlZXAgaXQgY29uY2lzZSAoMS0yIHBhZ2VzKS4gRm9jdXMgb24gdGhlICJ3aHkiIG5vdCB0aGUgImhvdyIgLQogICAgICBpbXBsZW1lbnRhdGlvbiBkZXRhaWxzIGJlbG9uZyBpbiBkZXNpZ24ubWQuCgogICAgICBUaGlzIGlzIHRoZSBmb3VuZGF0aW9uIC0gc3BlY3MsIGRlc2lnbiwgYW5kIHRhc2tzIGFsbCBidWlsZCBvbiB0aGlzLgogICAgcmVxdWlyZXM6IFtdCgogIC0gaWQ6IHNwZWNzCiAgICBnZW5lcmF0ZXM6ICJzcGVjcy8qKi8qLm1kIgogICAgZGVzY3JpcHRpb246IERldGFpbGVkIHNwZWNpZmljYXRpb25zIGZvciB0aGUgY2hhbmdlCiAgICB0ZW1wbGF0ZTogc3BlYy5tZAogICAgaW5zdHJ1Y3Rpb246IHwKICAgICAgQ3JlYXRlIHNwZWNpZmljYXRpb24gZmlsZXMgdGhhdCBkZWZpbmUgV0hBVCB0aGUgc3lzdGVtIHNob3VsZCBkby4KCiAgICAgIEEgc3BlYyBpcyBhIGJlaGF2aW9yIGNvbnRyYWN0LCBub3QgYW4gaW1wbGVtZW50YXRpb24gcGxhbi4KCiAgICAgIEdvb2Qgc3BlYyBjb250ZW50OgogICAgICAtIE9ic2VydmFibGUgYmVoYXZpb3IgdXNlcnMgb3IgZG93bnN0cmVhbSBzeXN0ZW1zIHJlbHkgb24KICAgICAgLSBJbnB1dHMsIG91dHB1dHMsIGFuZCBlcnJvciBjb25kaXRpb25zCiAgICAgIC0gRXh0ZXJuYWwgY29uc3RyYWludHMgKHNlY3VyaXR5LCBwcml2YWN5LCByZWxpYWJpbGl0eSwgY29tcGF0aWJpbGl0eSkKICAgICAgLSBTY2VuYXJpb3MgdGhhdCBjYW4gYmUgdGVzdGVkIG9yIGV4cGxpY2l0bHkgdmFsaWRhdGVkCgogICAgICBBdm9pZCBpbiBzcGVjczoKICAgICAgLSBJbnRlcm5hbCBjbGFzcy9mdW5jdGlvbiBuYW1lcwogICAgICAtIExpYnJhcnkgb3IgZnJhbWV3b3JrIGNob2ljZXMKICAgICAgLSBTdGVwLWJ5LXN0ZXAgaW1wbGVtZW50YXRpb24gZGV0YWlscwogICAgICAtIERldGFpbGVkIGV4ZWN1dGlvbiBwbGFucyAodGhvc2UgYmVsb25nIGluIGRlc2lnbi5tZCBvciB0YXNrcy5tZCkKCiAgICAgIFF1aWNrIHRlc3Q6IGlmIHRoZSBpbXBsZW1lbnRhdGlvbiBjYW4gY2hhbmdlIHdpdGhvdXQgY2hhbmdpbmcgZXh0ZXJuYWxseQogICAgICB2aXNpYmxlIGJlaGF2aW9yLCBpdCBsaWtlbHkgZG9lcyBub3QgYmVsb25nIGluIHRoZSBzcGVjLgoKICAgICAgQ3JlYXRlIG9uZSBzcGVjIGZpbGUgcGVyIGNhcGFiaWxpdHkgbGlzdGVkIGluIHRoZSBwcm9wb3NhbCdzIENhcGFiaWxpdGllcyBzZWN0aW9uLgogICAgICBgPGNhcGFiaWxpdHktcGF0aD5gIGlzIHRoZSBzcGVjIGRpcmVjdG9yeSByZWxhdGl2ZSB0byBgc3BlY3MvYCAoZm9yIGV4YW1wbGUsCiAgICAgIGB1c2VyLWF1dGhgIG9yIGBpZGVudGl0eS91c2VyLWF1dGhgKS4gUHJlc2VydmUgdGhlIGZ1bGwgcGF0aDoKICAgICAgLSBOZXcgY2FwYWJpbGl0aWVzOiB1c2UgdGhlIGV4YWN0IHBhdGggZnJvbSB0aGUgcHJvcG9zYWwgYXQgYHNwZWNzLzxjYXBhYmlsaXR5LXBhdGg+L3NwZWMubWRgLiBBbnkgcGF0aCBzZWdtZW50IG5ld2x5IGludHJvZHVjZWQgaW4gdGhlIHByb3Bvc2FsIG11c3QgYmUga2ViYWItY2FzZS4gRm9sbG93IHRoZSBwcm9qZWN0J3MgZXhpc3Rpbmcgb3JnYW5pemF0aW9uOyBkbyBub3QgYWRkIGEgbmV3IGRvbWFpbiBsZXZlbCB3aGVuIHRoZSBwcm9qZWN0IHVzZXMgYSBmbGF0IGxheW91dC4KICAgICAgLSBNb2RpZmllZCBjYXBhYmlsaXRpZXM6IHVzZSB0aGUgZXhhY3QgZXhpc3RpbmcgcGF0aCBmcm9tIGBvcGVuc3BlYy9zcGVjcy88Y2FwYWJpbGl0eS1wYXRoPi9gIHdoZW4gY3JlYXRpbmcgdGhlIGRlbHRhIGF0IGBzcGVjcy88Y2FwYWJpbGl0eS1wYXRoPi9zcGVjLm1kYC4gUnVuIGBvcGVuc3BlYyBsaXN0IC0tc3BlY3NgIHRvIGNvbmZpcm0gdGhhdCBwYXRoIGJlZm9yZSB3cml0aW5nIHRoZSBkZWx0YSwgYXBwZW5kaW5nIGAtLXN0b3JlICI8aWQ+ImAgb25seSBmb3IgYSByZWdpc3RlcmVkIHN0YW5kYWxvbmUgc3RvcmUgLSBhIG1pc3R5cGVkIG9yIGludmVudGVkIHBhdGggdGFyZ2V0cyBhIGNhcGFiaWxpdHkgdGhhdCBkb2VzIG5vdCBleGlzdCByYXRoZXIgdGhhbiB0aGUgb25lIHlvdSBtZWFudC4gRG8gbm90IG1vdmUgb3IgcmVuYW1lIHRoZSBjYXBhYmlsaXR5LgoKICAgICAgV3JpdGUgdGhlIHNwZWMgZmlsZXMgb25lIGF0IGEgdGltZSwgc28gdGhlIHVzZXIgc2VlcyBwcm9ncmVzcyBhbmQgYW4KICAgICAgaW50ZXJydXB0ZWQgcnVuIGtlZXBzIHRoZSBmaWxlcyBpdCBhbHJlYWR5IHdyb3RlOgogICAgICAtIEJlZm9yZSB3cml0aW5nIGFueXRoaW5nLCBjb21wYXJlIHRoZSBjYXBhYmlsaXRpZXMgdGhlIHByb3Bvc2FsIGxpc3RzCiAgICAgICAgd2l0aCB0aGUgYHNwZWNzLzxjYXBhYmlsaXR5LXBhdGg+L3NwZWMubWRgIGZpbGVzIHRoYXQgYWxyZWFkeSBleGlzdCwKICAgICAgICBhbmQgc3RhcnQgd2l0aCB0aGUgZmlyc3QgY2FwYWJpbGl0eSB0aGF0IGhhcyBubyBmaWxlLiBEbyBub3QgcmV3cml0ZQogICAgICAgIGFuIGV4aXN0aW5nIGZpbGUgdW5sZXNzIHRoZSB1c2VyIGFza3MgeW91IHRvLgogICAgICAtIEJlZm9yZSBlYWNoIGZpbGUsIHNheSBpbiBvbmUgbGluZSB3aGljaCBjYXBhYmlsaXR5IHlvdSBhcmUgd3JpdGluZy4KICAgICAgLSBXcml0ZSBlYWNoIGZpbGUgYXMgc29vbiBhcyB5b3UgaGF2ZSBkcmFmdGVkIGl0LiBEbyBub3QgcGxhbiBldmVyeSBmaWxlCiAgICAgICAgYmVmb3JlIHdyaXRpbmcgdGhlIGZpcnN0LgogICAgICAtIFN0b3Agd2hlbiBldmVyeSBjYXBhYmlsaXR5IHRoZSBwcm9wb3NhbCBsaXN0cyBoYXMgaXRzIGZpbGUuCgogICAgICBUaGVyZSBtdXN0IGJlIGF0IGxlYXN0IG9uZSBzcGVjIGZpbGUgdW5sZXNzIHRoZSBjaGFuZ2UncyBgLm9wZW5zcGVjLnlhbWxgCiAgICAgIHNldHMgYHNraXBfc3BlY3M6IHRydWVgIChubyBzcGVjLWxldmVsIGJlaGF2aW9yIGNoYW5nZSkgLSBgb3BlbnNwZWMgdmFsaWRhdGVgCiAgICAgIHJlamVjdHMgYSB6ZXJvLWRlbHRhIGNoYW5nZSB3aXRob3V0IHRoYXQgbWFya2VyLiBJZiB0aGUgcHJvcG9zYWwgbGlzdHMgbm8KICAgICAgY2FwYWJpbGl0aWVzIGFuZCBgc2tpcF9zcGVjc2AgaXMgbm90IHNldCwgcmV2aXNpdCB0aGUgcHJvcG9zYWwgZmlyc3QuCgogICAgICBEZWx0YSBvcGVyYXRpb25zICh1c2UgIyMgaGVhZGVycyk6CiAgICAgIC0gKipBRERFRCBSZXF1aXJlbWVudHMqKjogTmV3IGNhcGFiaWxpdGllcwogICAgICAtICoqTU9ESUZJRUQgUmVxdWlyZW1lbnRzKio6IENoYW5nZWQgYmVoYXZpb3IgLSBNVVNUIGluY2x1ZGUgZnVsbCB1cGRhdGVkIGNvbnRlbnQKICAgICAgLSAqKlJFTU9WRUQgUmVxdWlyZW1lbnRzKio6IERlcHJlY2F0ZWQgZmVhdHVyZXMgLSBNVVNUIGluY2x1ZGUgKipSZWFzb24qKiBhbmQgKipNaWdyYXRpb24qKgogICAgICAtICoqUkVOQU1FRCBSZXF1aXJlbWVudHMqKjogTmFtZSBjaGFuZ2VzIG9ubHkgLSB1c2UgRlJPTTovVE86IGZvcm1hdAoKICAgICAgRm9ybWF0IHJlcXVpcmVtZW50czoKICAgICAgLSBFYWNoIHJlcXVpcmVtZW50OiBgIyMjIFJlcXVpcmVtZW50OiA8bmFtZT5gIGZvbGxvd2VkIGJ5IGRlc2NyaXB0aW9uCiAgICAgIC0gVXNlIFNIQUxML01VU1QgZm9yIG5vcm1hdGl2ZSByZXF1aXJlbWVudHMgKGF2b2lkIHNob3VsZC9tYXkpCiAgICAgIC0gRWFjaCBzY2VuYXJpbzogYCMjIyMgU2NlbmFyaW86IDxuYW1lPmAgd2l0aCBXSEVOL1RIRU4gZm9ybWF0CiAgICAgIC0gKipDUklUSUNBTCoqOiBTY2VuYXJpb3MgTVVTVCB1c2UgZXhhY3RseSA0IGhhc2h0YWdzIChgIyMjI2ApLiBVc2luZyAzIGhhc2h0YWdzIG9yIGJ1bGxldHMgd2lsbCBmYWlsIHNpbGVudGx5LgogICAgICAtIEV2ZXJ5IHJlcXVpcmVtZW50IE1VU1QgaGF2ZSBhdCBsZWFzdCBvbmUgc2NlbmFyaW8uCiAgICAgIC0gS2VlcCBlYWNoIHJlcXVpcmVtZW50J3MgZGVzY3JpcHRpb24gKHRoZSB0ZXh0IGJldHdlZW4gYCMjIyBSZXF1aXJlbWVudDpgIGFuZCBpdHMgZmlyc3Qgc2NlbmFyaW8pIHRvIDUwMCBjaGFyYWN0ZXJzIG9yIGZld2VyLiBgb3BlbnNwZWMgdmFsaWRhdGVgIGZsYWdzIGxvbmdlciBkZXNjcmlwdGlvbnMgaW4gQURERUQgcmVxdWlyZW1lbnRzIGFuZCBpbiB0aGUgbWFpbiBzcGVjLiBUaGlzIGlzIGEgd2FybmluZzogbm9ybWFsIHZhbGlkYXRpb24gc3RpbGwgcGFzc2VzLCBidXQgYG9wZW5zcGVjIHZhbGlkYXRlIC0tc3RyaWN0YCBmYWlscyBvbiBpdC4gV2hlbiB3cml0aW5nIGEgbmV3IHJlcXVpcmVtZW50LCBzdGF0ZSBvbmUgYmVoYXZpb3IgcGVyIHJlcXVpcmVtZW50OiBtb3ZlIGV4YW1wbGVzIGFuZCBlZGdlIGNhc2VzIGludG8gc2NlbmFyaW9zLCBhbmQgc3BsaXQgYSByZXF1aXJlbWVudCB0aGF0IGNvdmVycyBzZXZlcmFsIGJlaGF2aW9ycyBpbnRvIHNlcGFyYXRlIGAjIyMgUmVxdWlyZW1lbnQ6YCBibG9ja3MsIGVhY2ggd2l0aCBpdHMgb3duIHNjZW5hcmlvcy4gVW5kZXIgTU9ESUZJRUQsIGtlZXAgdGhlIGV4aXN0aW5nIHJlcXVpcmVtZW50IGJsb2NrIHdob2xlOyBuZXZlciBzcGxpdCwgdHJpbSBvciByZXdyaXRlIGV4aXN0aW5nIHRleHQganVzdCB0byBtZWV0IHRoZSBsZW5ndGguIFNwbGl0IGFuIGV4aXN0aW5nIGxvbmcgcmVxdWlyZW1lbnQgb25seSB3aGVuIHRoZSB1c2VyIGFza3MgZm9yIGl0LCBpbiBhIGNoYW5nZSBtYWRlIGZvciB0aGF0IHB1cnBvc2U6IHVuZGVyIE1PRElGSUVELCBrZWVwIGl0cyBoZWFkZXIgYW5kIGV2ZXJ5IHNjZW5hcmlvIGFuZCBjdXQgaXRzIGRlc2NyaXB0aW9uIGRvd24gdG8gb25lIGJlaGF2aW9yIHdpdGhvdXQgY2hhbmdpbmcgaXRzIG1lYW5pbmcsIHRoZW4gYWRkIGVhY2ggYmVoYXZpb3IgeW91IHJlbW92ZWQgYXMgaXRzIG93biBBRERFRCByZXF1aXJlbWVudCB3aXRoIGl0cyBvd24gc2NlbmFyaW9zLgoKICAgICAgTmV3IGNhcGFiaWxpdGllcyBvbmx5OiB0aGUgZGVsdGEgc3BlYydzIGZpcnN0IHNlY3Rpb24gaXMgYCMjIFB1cnBvc2VgIC0KICAgICAgb25lIG9yIHR3byBzZW50ZW5jZXMgKDUwKyBjaGFyYWN0ZXJzLCBvciBgb3BlbnNwZWMgdmFsaWRhdGUgLS1zdHJpY3RgCiAgICAgIHJlcG9ydHMgaXQgYXMgdG9vIGJyaWVmKSBkZXNjcmliaW5nIHdoYXQgdGhlIGNhcGFiaWxpdHkgaXMgZm9yLiBBcmNoaXZlCiAgICAgIGNvcGllcyBpdCBpbnRvIHRoZSBtYWluIHNwZWMgaXQgY3JlYXRlczsgd2l0aG91dCBpdCB0aGUgbmV3IG1haW4gc3BlYyBpcwogICAgICBsZWZ0IHdpdGggYSBgVEJEIC4uLiBVcGRhdGUgUHVycG9zZSBhZnRlciBhcmNoaXZlYCBwbGFjZWhvbGRlciB0byBmaWxsIGluCiAgICAgIGJ5IGhhbmQuIERvIE5PVCBhZGQgYCMjIFB1cnBvc2VgIHRvIGEgZGVsdGEgZm9yIGFuIGV4aXN0aW5nIGNhcGFiaWxpdHkgLQogICAgICB0aGF0IHNwZWMgYWxyZWFkeSBoYXMgb25lIGFuZCB0aGUgZGVsdGEncyBpcyBpZ25vcmVkLiBUbyBjaGFuZ2UgYW4KICAgICAgZXhpc3RpbmcgY2FwYWJpbGl0eSdzIFB1cnBvc2UgLSBpbmNsdWRpbmcgYSBsZWZ0b3ZlciBgVEJEYCBwbGFjZWhvbGRlciAtCiAgICAgIGVkaXQgYDxwbGFubmluZ0hvbWUucm9vdD4vb3BlbnNwZWMvc3BlY3MvPGNhcGFiaWxpdHktcGF0aD4vc3BlYy5tZGAKICAgICAgZGlyZWN0bHkuIGBwbGFubmluZ0hvbWUucm9vdGAgY29tZXMgZnJvbSB0aGUgYG9wZW5zcGVjIGluc3RydWN0aW9ucyAuLi4KICAgICAgLS1qc29uYCByZXNwb25zZS4gQWx3YXlzIHVzZSBpdCByYXRoZXIgdGhhbiBhIHJlcG8tcmVsYXRpdmUgcGF0aDogaXQKICAgICAgcmVzb2x2ZXMgdG8gdGhlIHN0b3JlIHdoZW5ldmVyIHRoZSBjaGFuZ2UgbGl2ZXMgaW4gb25lIC0gd2hldGhlciB0aGF0CiAgICAgIGNhbWUgZnJvbSBgLS1zdG9yZWAsIGEgcHJvamVjdCBgc3RvcmU6YCBwb2ludGVyLCBvciBhIGdsb2JhbCBkZWZhdWx0CiAgICAgIHN0b3JlIC0gYW5kIHRvIHRoZSBjdXJyZW50IHJlcG9zaXRvcnkgb3RoZXJ3aXNlLiBEbyBub3QgdHJ5IHRvIHdvcmsgb3V0CiAgICAgIHdoaWNoIGNhc2UgYXBwbGllczsgdGhlIGZpZWxkIGFscmVhZHkgaGFzLgoKICAgICAgTU9ESUZJRUQgcmVxdWlyZW1lbnRzIHdvcmtmbG93OgogICAgICAxLiBMb2NhdGUgdGhlIGV4aXN0aW5nIHJlcXVpcmVtZW50IGluIGA8cGxhbm5pbmdIb21lLnJvb3Q+L29wZW5zcGVjL3NwZWNzLzxjYXBhYmlsaXR5LXBhdGg+L3NwZWMubWRgICh0aGUgc2FtZSBzdG9yZS1hd2FyZSByb290IGFzIGFib3ZlKQogICAgICAyLiBDb3B5IHRoZSBFTlRJUkUgcmVxdWlyZW1lbnQgYmxvY2sgKGZyb20gYCMjIyBSZXF1aXJlbWVudDpgIHRocm91Z2ggYWxsIHNjZW5hcmlvcykKICAgICAgMy4gUGFzdGUgdW5kZXIgYCMjIE1PRElGSUVEIFJlcXVpcmVtZW50c2AgYW5kIGVkaXQgdG8gcmVmbGVjdCBuZXcgYmVoYXZpb3IKICAgICAgNC4gRW5zdXJlIGhlYWRlciB0ZXh0IG1hdGNoZXMgZXhhY3RseSAod2hpdGVzcGFjZS1pbnNlbnNpdGl2ZSkKCiAgICAgIENvbW1vbiBwaXRmYWxsOiBVc2luZyBNT0RJRklFRCB3aXRoIHBhcnRpYWwgY29udGVudCBsb3NlcyBkZXRhaWwgYXQgYXJjaGl2ZSB0aW1lLgogICAgICBJZiBhZGRpbmcgbmV3IGNvbmNlcm5zIHdpdGhvdXQgY2hhbmdpbmcgZXhpc3RpbmcgYmVoYXZpb3IsIHVzZSBBRERFRCBpbnN0ZWFkLgoKICAgICAgRXhhbXBsZSAoYSBuZXcgY2FwYWJpbGl0eSwgc28gaXRzIGZpcnN0IHNlY3Rpb24gaXMgYCMjIFB1cnBvc2VgKToKICAgICAgYGBgCiAgICAgICMgU3BlYyBEZWx0YQoKICAgICAgIyMgUHVycG9zZQoKICAgICAgTGV0cyB1c2VycyB0YWtlIHRoZWlyIGRhdGEgb3V0IG9mIHRoZSBwcm9kdWN0IGluIGEgcG9ydGFibGUgZm9ybWF0LgoKICAgICAgIyMgQURERUQgUmVxdWlyZW1lbnRzCgogICAgICAjIyMgUmVxdWlyZW1lbnQ6IFVzZXIgY2FuIGV4cG9ydCBkYXRhCiAgICAgIFRoZSBzeXN0ZW0gU0hBTEwgYWxsb3cgdXNlcnMgdG8gZXhwb3J0IHRoZWlyIGRhdGEgaW4gQ1NWIGZvcm1hdC4KCiAgICAgICMjIyMgU2NlbmFyaW86IFN1Y2Nlc3NmdWwgZXhwb3J0CiAgICAgIC0gKipXSEVOKiogdXNlciBjbGlja3MgIkV4cG9ydCIgYnV0dG9uCiAgICAgIC0gKipUSEVOKiogc3lzdGVtIGRvd25sb2FkcyBhIENTViBmaWxlIHdpdGggYWxsIHVzZXIgZGF0YQoKICAgICAgIyMgUkVNT1ZFRCBSZXF1aXJlbWVudHMKCiAgICAgICMjIyBSZXF1aXJlbWVudDogTGVnYWN5IGV4cG9ydAogICAgICAqKlJlYXNvbioqOiBSZXBsYWNlZCBieSBuZXcgZXhwb3J0IHN5c3RlbQogICAgICAqKk1pZ3JhdGlvbioqOiBVc2UgbmV3IGV4cG9ydCBlbmRwb2ludCBhdCAvYXBpL3YyL2V4cG9ydAogICAgICBgYGAKCgogICAgICBTdGFibGUgSURzIChzcGVjLWN0eCk6CiAgICAgIC0gRXZlcnkgcmVxdWlyZW1lbnQgaGVhZGVyIHN0YXJ0cyB3aXRoIGFuIElEOiBgIyMjIFJlcXVpcmVtZW50OiBSRVEtPENBUD4tTk5OIDxuYW1lPmAuCiAgICAgICAgR2V0IGEgbmV3IElEIGZyb20gYHNwZWNjdHggaWQgbmV3IFJFUSA8Q0FQPmAuIE5ldmVyIGNvdW50IG51bWJlcnMgYnkgaGFuZC4KICAgICAgICBgPENBUD5gIGlzIGEgY2FwYWJpbGl0eSBjb2RlIGZyb20gYFtpZHNdIGNhcHNgIGluIGBzcGVjLWN0eC50b21sYC4KICAgICAgLSBFdmVyeSBzY2VuYXJpbyBoZWFkZXIgc3RhcnRzIHdpdGggYW4gSUQ6IGAjIyMjIFNjZW5hcmlvOiBTQ04tPENBUD4tTk5OLTxuPiA8bmFtZT5gLgogICAgICAgIEdldCBpdCBmcm9tIGBzcGVjY3R4IGlkIG5ldyBTQ04gPENBUD4gLS1mb3IgUkVRLTxDQVA+LU5OTmAuCiAgICAgIC0gVW5kZXIgTU9ESUZJRUQsIFJFTU9WRUQsIG9yIFJFTkFNRUQsIGtlZXAgdGhlIGV4aXN0aW5nIElELiBBbiBJRCBuZXZlciBjaGFuZ2VzLgogICAgICAtIExpbmsgcmVsYXRlZCBJRHMgd2l0aCBvbmUgbGluZSBgUmVmczogSUQsIElEYCBhZnRlciB0aGUgcmVxdWlyZW1lbnQgdGV4dC4KICAgICAgLSBSZXBsYWNlIGV2ZXJ5IHBsYWNlaG9sZGVyIG9mIHRoZSB0ZW1wbGF0ZS4gYHNwZWNjdHggY2hlY2tgIHJlcG9ydHMgYSBoZWFkZXIgd2l0aAogICAgICAgIG5vIElEIGFzIGBtaXNzaW5nLWlkYC4KCiAgICAgIFNwZWNzIHNob3VsZCBiZSB0ZXN0YWJsZSAtIGVhY2ggc2NlbmFyaW8gaXMgYSBwb3RlbnRpYWwgdGVzdCBjYXNlLgogICAgcmVxdWlyZXM6CiAgICAgIC0gcHJvcG9zYWwKCiAgLSBpZDogZGVzaWduCiAgICBnZW5lcmF0ZXM6IGRlc2lnbi5tZAogICAgZGVzY3JpcHRpb246IFRlY2huaWNhbCBkZXNpZ24gZG9jdW1lbnQgd2l0aCBpbXBsZW1lbnRhdGlvbiBkZXRhaWxzCiAgICB0ZW1wbGF0ZTogZGVzaWduLm1kCiAgICBpbnN0cnVjdGlvbjogfAogICAgICBDcmVhdGUgdGhlIGRlc2lnbiBkb2N1bWVudCB0aGF0IGV4cGxhaW5zIEhPVyB0byBpbXBsZW1lbnQgdGhlIGNoYW5nZS4KCiAgICAgIFdoZW4gdG8gaW5jbHVkZSBkZXNpZ24ubWQgKGNyZWF0ZSBvbmx5IGlmIGFueSBhcHBseSk6CiAgICAgIC0gQ3Jvc3MtY3V0dGluZyBjaGFuZ2UgKG11bHRpcGxlIHNlcnZpY2VzL21vZHVsZXMpIG9yIG5ldyBhcmNoaXRlY3R1cmFsIHBhdHRlcm4KICAgICAgLSBOZXcgZXh0ZXJuYWwgZGVwZW5kZW5jeSBvciBzaWduaWZpY2FudCBkYXRhIG1vZGVsIGNoYW5nZXMKICAgICAgLSBTZWN1cml0eSwgcGVyZm9ybWFuY2UsIG9yIG1pZ3JhdGlvbiBjb21wbGV4aXR5CiAgICAgIC0gQW1iaWd1aXR5IHRoYXQgYmVuZWZpdHMgZnJvbSB0ZWNobmljYWwgZGVjaXNpb25zIGJlZm9yZSBjb2RpbmcKCiAgICAgIFNlY3Rpb25zOgogICAgICAtICoqQ29udGV4dCoqOiBPbmx5IHRoZSBjdXJyZW50IHN0YXRlIGFuZCBjb25zdHJhaW50cyBuZWVkZWQgdG8gZXhwbGFpbiB0aGUgYXBwcm9hY2guIFJlZmVyZW5jZSB0aGUgcHJvcG9zYWwgZm9yIG1vdGl2YXRpb24gaW5zdGVhZCBvZiByZXN0YXRpbmcgaXQgKGUuZy4sICJTZWUgcHJvcG9zYWwubWQgLSBXaHkiKS4KICAgICAgLSAqKkdvYWxzIC8gTm9uLUdvYWxzKio6IFdoYXQgdGhpcyBkZXNpZ24gYWNoaWV2ZXMgYW5kIGV4cGxpY2l0bHkgZXhjbHVkZXMuIERvbid0IHJlc3RhdGUgdGhlIHByb3Bvc2FsJ3Mgc2NvcGUgLSBhZGQgb25seSBkZXNpZ24tbGV2ZWwgYm91bmRhcmllcy4KICAgICAgLSAqKkRlY2lzaW9ucyoqOiBLZXkgdGVjaG5pY2FsIGNob2ljZXMgd2l0aCByYXRpb25hbGUgKHdoeSBYIG92ZXIgWT8pLiBJbmNsdWRlIGFsdGVybmF0aXZlcyBjb25zaWRlcmVkIGZvciBlYWNoIGRlY2lzaW9uLgogICAgICAtICoqUmlza3MgLyBUcmFkZS1vZmZzKio6IEtub3duIGxpbWl0YXRpb25zLCB0aGluZ3MgdGhhdCBjb3VsZCBnbyB3cm9uZy4gRm9ybWF0OiBbUmlza10g4oaSIE1pdGlnYXRpb24KICAgICAgLSAqKk1pZ3JhdGlvbiBQbGFuKio6IFN0ZXBzIHRvIGRlcGxveSwgcm9sbGJhY2sgc3RyYXRlZ3kgKGlmIGFwcGxpY2FibGUpCiAgICAgIC0gKipPcGVuIFF1ZXN0aW9ucyoqOiBVbmtub3ducyB0aGF0IGNhbiBzYWZlbHkgYmUgYW5zd2VyZWQgbGF0ZXIgd2l0aG91dAogICAgICAgIGNoYW5naW5nIHRoZSBzcGVjcywgdGhlIGFwcHJvYWNoLCBvciB0aGUgdGFzayBicmVha2Rvd24uIE9taXQgaWYgbm9uZS4KCiAgICAgIE9wZW4gcXVlc3Rpb25zIGFyZSBmb3IgZ2VudWluZWx5IGRlZmVycmFibGUgdW5rbm93bnMsIG5vdCBkZWNpc2lvbnMgeW91CiAgICAgIHNraXBwZWQuIElmIGEgcXVlc3Rpb24gd291bGQgY2hhbmdlIHRoZSBzcGVjcywgdGhlIGNob3NlbiBhcHByb2FjaCwgb3IKICAgICAgdGhlIHRhc2sgYnJlYWtkb3duLCByZXNvbHZlIGl0IG5vdyAtIGFzayB0aGUgdXNlciBpbnN0ZWFkIG9mIGd1ZXNzaW5nLgoKICAgICAgRm9jdXMgb24gYXJjaGl0ZWN0dXJlIGFuZCBhcHByb2FjaCwgbm90IGxpbmUtYnktbGluZSBpbXBsZW1lbnRhdGlvbi4KICAgICAgVGhlIHByb3Bvc2FsIGNvdmVycyB3aHkgYW5kIHdoYXQ7IGRlc2lnbiBjb3ZlcnMgaG93LiBSZWZlcmVuY2UgdGhlCiAgICAgIHByb3Bvc2FsIGZvciBtb3RpdmF0aW9uIGFuZCwgb25jZSB3cml0dGVuLCB0aGUgc3BlY3MgZm9yIHJlcXVpcmVtZW50cyAtCiAgICAgIGlmIGEgc2VjdGlvbiB3b3VsZCBvbmx5IHJlc3RhdGUgdGhlbSwgcG9pbnQgdG8gdGhlbSBpbnN0ZWFkLgoKCiAgICAgIFN0YWJsZSBJRHMgKHNwZWMtY3R4KToKICAgICAgLSBFYWNoIGJ1bGxldCB1bmRlciBgIyMgRGVjaXNpb25zYCBpcyBvbmUgZGVjaXNpb24uIEl0cyBJRCBpcyBgPGNoYW5nZSBudW1iZXI+L0Q8bj5gCiAgICAgICAgYnkgcG9zaXRpb24sIHNvIGFkZCBuZXcgZGVjaXNpb25zIGF0IHRoZSBlbmQgYW5kIG5ldmVyIHJlb3JkZXIgdGhlbS4KICAgICAgLSBFbmQgYSBkZWNpc2lvbiB3aXRoIGBSZWZzOiBgIGFuZCB0aGUgUkVRIG9yIEFEUiBJRHMgaXQgc2VydmVzLiBUaGVuIGBzcGVjY3R4IGJ1bmRsZWAKICAgICAgICBwcmludHMgdGhlIGRlY2lzaW9uIHdpdGggdGhvc2UgcmVxdWlyZW1lbnRzLgoKICAgICAgR29vZCBkZXNpZ24gZG9jcyBleHBsYWluIHRoZSAid2h5IiBiZWhpbmQgdGVjaG5pY2FsIGRlY2lzaW9ucy4KICAgIHJlcXVpcmVzOgogICAgICAtIHByb3Bvc2FsCgogIC0gaWQ6IHRhc2tzCiAgICBnZW5lcmF0ZXM6IHRhc2tzLm1kCiAgICBkZXNjcmlwdGlvbjogSW1wbGVtZW50YXRpb24gY2hlY2tsaXN0IHdpdGggdHJhY2thYmxlIHRhc2tzCiAgICB0ZW1wbGF0ZTogdGFza3MubWQKICAgIGluc3RydWN0aW9uOiB8CiAgICAgIENyZWF0ZSB0aGUgdGFzayBsaXN0IHRoYXQgYnJlYWtzIGRvd24gdGhlIGltcGxlbWVudGF0aW9uIHdvcmsuCgogICAgICBCZWZvcmUgd3JpdGluZyB0YXNrcywgY2hlY2sgZGVzaWduLm1kIGZvciBPcGVuIFF1ZXN0aW9ucy4gSWYgYW55IG9mIHRoZW0KICAgICAgd291bGQgY2hhbmdlIHdoYXQgZ2V0cyBidWlsdCwgcmVzb2x2ZSB0aGVtIHdpdGggdGhlIHVzZXIgZmlyc3QgLSBkbyBub3QKICAgICAgYmFrZSBhbiB1bnN0YXRlZCBhc3N1bXB0aW9uIGludG8gdGhlIHRhc2sgbGlzdC4KCiAgICAgICoqSU1QT1JUQU5UOiBGb2xsb3cgdGhlIHRlbXBsYXRlIGJlbG93IGZvciB0cmFja2VkIHRhc2tzLioqIFRoZSBhcHBseSBwaGFzZSBwYXJzZXMKICAgICAgY2hlY2tib3ggZm9ybWF0IHRvIHRyYWNrIHByb2dyZXNzLiBBIGJveCBob2xkaW5nIG9ubHkgYHhgIGNvdW50cyBhcyBkb25lLAogICAgICB1cHBlciBvciBsb3dlciBjYXNlIGFuZCB3aXRoIGFueSBzcGFjaW5nLCBzbyBgLSBbIHhdYCBpcyBkb25lIHRvby4gRXZlcnkKICAgICAgb3RoZXIgbWFya2VyLCBpbmNsdWRpbmcgYC0gW35dYCwgYC0gWy1dYCBhbmQgYW4gZW1wdHkgYC0gW11gLCByZWFkcyBhcwogICAgICB1bmZpbmlzaGVkLiBBIGxpbmUgd2l0aCBubyBjaGVja2JveCBpcyBub3QgdHJhY2tlZCBhdCBhbGwuCgogICAgICBHdWlkZWxpbmVzOgogICAgICAtIEdyb3VwIHJlbGF0ZWQgdHJhY2tlZCB0YXNrcyB1bmRlciAjIyBudW1iZXJlZCBoZWFkaW5ncwogICAgICAtIEVhY2ggdHJhY2tlZCB0YXNrIE1VU1QgYmUgYSBjaGVja2JveDogYC0gWyBdIFguWSBUYXNrIGRlc2NyaXB0aW9uYAogICAgICAtIFRhc2tzIHNob3VsZCBiZSBzbWFsbCBlbm91Z2ggdG8gY29tcGxldGUgaW4gb25lIHNlc3Npb24KICAgICAgLSBPcmRlciB0YXNrcyBieSBkZXBlbmRlbmN5ICh3aGF0IG11c3QgYmUgZG9uZSBmaXJzdD8pCiAgICAgIC0gVHJhY2sgaW1wbGVtZW50YXRpb24gYW5kIHZlcmlmaWNhdGlvbiB3b3JrIHRoYXQgY2FuIGJlIGNvbXBsZXRlZCBiZWZvcmUKICAgICAgICBhcmNoaXZlLiBJZiB0aGUgcmVxdWVzdGVkIHdvcmtmbG93IGluY2x1ZGVzIGFyY2hpdmUgb3Igd29yayB0aGF0IHJlcXVpcmVzCiAgICAgICAgdGhpcyBjaGFuZ2UgdG8gYmUgYXJjaGl2ZWQsIHByZXNlcnZlIHRob3NlIHN0ZXBzIGFzIHBsYWluIGJ1bGxldHMgaW4gYW4KICAgICAgICBvcHRpb25hbCBgIyMgV29ya2Zsb3cgZm9sbG93LXVwYCBzZWN0aW9uIGF0IHRoZSBlbmQgb2YgdGFza3MubWQuIFRoZXNlCiAgICAgICAgYnVsbGV0cyBhcmUgcmVmZXJlbmNlIGluZm9ybWF0aW9uIG91dHNpZGUgdHJhY2tlZCB0YXNrIHByb2dyZXNzLgogICAgICAtIEVhY2ggdGFzayBNVVNUIHN0YXRlIGhvdyB0byB2ZXJpZnkgY29tcGxldGlvbiAoYSB0ZXN0LCBjb21tYW5kLAogICAgICAgIG9ic2VydmFibGUgYmVoYXZpb3IsIG9yIGRlbGl2ZXJlZCBhcnRpZmFjdCkuIFB1dCB0aGUgdmVyaWZpY2F0aW9uIGluCiAgICAgICAgdGhhdCB0YXNrJ3MgY2hlY2tib3ggZGVzY3JpcHRpb24uIFVzZSBhIHNlcGFyYXRlIHZlcmlmaWNhdGlvbiB0YXNrIG9ubHkKICAgICAgICB3aGVuIGl0IGNoZWNrcyBicm9hZGVyIGludGVncmF0aW9uIG9yIHN5c3RlbSBiZWhhdmlvciB0aGF0IHNwYW5zCiAgICAgICAgbXVsdGlwbGUgaW1wbGVtZW50YXRpb24gdGFza3MuCiAgICAgIC0gRWFjaCB0YXNrIGdyb3VwIE1VU1QgbGFuZCB0aGUgdGVzdHMgYW5kIGRvY3VtZW50YXRpb24gaXRzIG93biB3b3JrCiAgICAgICAgY2FsbHMgZm9yLiBEbyBOT1QgY29sbGVjdCB0ZXN0aW5nIG9yIGRvY3VtZW50YXRpb24gaW50byBhIGZpbmFsIGdyb3VwIC0KICAgICAgICB3aGVuIGEgbGF0ZSBncm91cCBmaXJzdCBleGVyY2lzZXMgd29yayBmcm9tIGFuIGVhcmx5IG9uZSwgdGhlIGZhaWx1cmVzCiAgICAgICAgY2FzY2FkZSBiYWNrIHRocm91Z2ggZXZlcnkgZ3JvdXAgaW4gYmV0d2VlbiBhbmQgZm9yY2UgcmV3b3JrLiBBIGdyb3VwCiAgICAgICAgd2hvc2Ugd29yayBjYWxscyBmb3IgbmVpdGhlciwgc3VjaCBhcyBzY2FmZm9sZGluZyBvciBkZXBlbmRlbmN5IHNldHVwLAogICAgICAgIGNhcnJpZXMgbmVpdGhlci4gQSBmaW5hbCBncm91cCBpcyBmb3IgaW50ZWdyYXRpb24gY2hlY2tzIG9ubHksIG5vdCBmb3IKICAgICAgICB0aGUgdGVzdHMgYW5kIGRvY3MgYW4gZWFybGllciBncm91cCBvd2VkLgoKICAgICAgRXhhbXBsZToKICAgICAgYGBgCiAgICAgICMgVGFza3MKCiAgICAgICMjIDEuIFNldHVwCgogICAgICAtIFsgXSAxLjEgQ3JlYXRlIG5ldyBtb2R1bGUgc3RydWN0dXJlIGFuZCB2ZXJpZnkgZXhwZWN0ZWQgZmlsZXMgYXJlIHByZXNlbnQKICAgICAgLSBbIF0gMS4yIEFkZCBkZXBlbmRlbmNpZXMgdG8gcGFja2FnZS5qc29uIGFuZCB2ZXJpZnkgcGFja2FnZSBpbnN0YWxsYXRpb24gc3VjY2VlZHMKCiAgICAgICMjIDIuIENvcmUgSW1wbGVtZW50YXRpb24KCiAgICAgIC0gWyBdIDIuMSBJbXBsZW1lbnQgZGF0YSBleHBvcnQgZnVuY3Rpb24gYW5kIHZlcmlmeSB0aGUgZXhwb3J0IHRlc3QgcGFzc2VzCiAgICAgIC0gWyBdIDIuMiBBZGQgQ1NWIGZvcm1hdHRpbmcgdXRpbGl0aWVzIGFuZCB2ZXJpZnkgdW5pdCB0ZXN0cyBjb3ZlciBxdW90aW5nIGFuZCBkZWxpbWl0ZXJzCiAgICAgIC0gWyBdIDIuMyBEb2N1bWVudCB0aGUgZXhwb3J0IEFQSSBpbiBkb2NzL2V4cG9ydC5tZCBhbmQgdmVyaWZ5IHRoZSBkb2N1bWVudGVkIGNvbW1hbmQgcnVucyBhcyB3cml0dGVuCiAgICAgIGBgYAoKICAgICAgV2hlbiBhcHBsaWNhYmxlLCBhcHBlbmQgd29ya2Zsb3cgZm9sbG93LXVwIGFzIHBsYWluIGJ1bGxldHMsIGZvciBleGFtcGxlOgogICAgICBgYGAKICAgICAgIyMgV29ya2Zsb3cgZm9sbG93LXVwCgogICAgICAtIEFyY2hpdmUgdGhlIGNoYW5nZSBhZnRlciB0aGUgcHJvamVjdCdzIHJldmlldyByZXF1aXJlbWVudHMgYXJlIHNhdGlzZmllZC4KICAgICAgLSBWZXJpZnkgdGhlIGFyY2hpdmVkIHJlc3VsdC4KICAgICAgYGBgCgoKICAgICAgU3RhYmxlIElEcyBhbmQgVmVyaWZ5IChzcGVjLWN0eCk6CiAgICAgIC0gRXZlcnkgdGFzayBjaXRlcyBhdCBsZWFzdCBvbmUgcmVxdWlyZW1lbnQgaW4gc3F1YXJlIGJyYWNrZXRzOiBgW1JFUS08Q0FQPi1OTk5dYC4KICAgICAgLSBFdmVyeSB0YXNrIGVuZHMgd2l0aCBgVmVyaWZ5OmAgYW5kIHRoZSBjb21tYW5kIGluIGEgY29kZSBzcGFuLCBmb3IgZXhhbXBsZQogICAgICAgIGBgVmVyaWZ5OiBgbnBtIHRlc3QgLS0gdGVzdHMvZXhwb3J0LnRlc3QudHNgIGBgLiBUd28gc3BhbnMgcnVuIGpvaW5lZCB3aXRoIGAmJmAuCiAgICAgIC0gVXNlIHByb3NlIGFmdGVyIGBWZXJpZnk6YCBvbmx5IHdoZW4gbm8gY29tbWFuZCBjYW4gY2hlY2sgdGhlIHdvcmsuIFRoZW4KICAgICAgICBgc3BlY2N0eCB0YXNrIGRvbmUgPGlkPiAtLW1hbnVhbCAiPG5vdGU+ImAgcmVjb3JkcyBpdC4KICAgICAgLSBDbG9zZSBhIHRhc2sgb25seSB3aXRoIGBzcGVjY3R4IHRhc2sgZG9uZSA8aWQ+YC4gSXQgcnVucyB0aGUgY29tbWFuZCwgd3JpdGVzCiAgICAgICAgZXZpZGVuY2UgdW5kZXIgYC5jdHgvZXZpZGVuY2UvYCwgYW5kIHNldHMgdGhlIGNoZWNrYm94LgoKICAgICAgUmVmZXJlbmNlIHNwZWNzIGZvciB3aGF0IG5lZWRzIHRvIGJlIGJ1aWx0LCBkZXNpZ24gZm9yIGhvdyB0byBidWlsZCBpdC4KICAgIHJlcXVpcmVzOgogICAgICAtIHNwZWNzCiAgICAgIC0gZGVzaWduCgphcHBseToKICByZXF1aXJlczogWyB0YXNrcyBdCiAgdHJhY2tzOiB0YXNrcy5tZAogIGluc3RydWN0aW9uOiB8CiAgICBSZWFkIGNvbnRleHQgZmlsZXMsIHdvcmsgdGhyb3VnaCBwZW5kaW5nIHRhc2tzLCBtYXJrIGNvbXBsZXRlIGFzIHlvdSBnby4KICAgIFBhdXNlIGlmIHlvdSBoaXQgYmxvY2tlcnMgb3IgbmVlZCBjbGFyaWZpY2F0aW9uLgo=",
4
+ "schemas/spec-driven-ids/README.md": "IyBzcGVjLWRyaXZlbi1pZHMKClRlbXBsYXRlcyBhbmQgY29uZmlnIHJ1bGVzIHRoYXQgYWRkIHN0YWJsZSBJRHMgZnJvbSBzcGVjLWN0eCB0byB0aGUgT3BlblNwZWMgYHNwZWMtZHJpdmVuYCB3b3JrZmxvdy4gVGhlIHByb2plY3Qga2VlcHMgYHNjaGVtYTogc3BlYy1kcml2ZW5gIGluIGBvcGVuc3BlYy9jb25maWcueWFtbGAuIFVwc3RyZWFtIE9wZW5TcGVjIGluamVjdHMgdGhlIGBydWxlc2AgYW5kIGBvcGVyYXRpb25zYCBiZWxvdyBpbnRvIGV2ZXJ5IGFydGlmYWN0IGluc3RydWN0aW9uLCBzbyB0aGUgYWdlbnQgbGVhcm5zIHRoZSBJRCBjb21tYW5kcyBmcm9tIHRoZXJlLgoKLSBgdGVtcGxhdGVzL3NwZWMubWRgIHN0YXJ0cyBlYWNoIHJlcXVpcmVtZW50IHdpdGggYFJFUS08Q0FQPi1OTk5gIGFuZCBlYWNoIHNjZW5hcmlvIHdpdGggYFNDTi08Q0FQPi1OTk4tPG4+YC4KLSBgdGVtcGxhdGVzL3Rhc2tzLm1kYCBjaXRlcyBSRVEgSURzIGFuZCBwdXRzIHRoZSBgVmVyaWZ5OmAgY29tbWFuZCBpbiBhIGNvZGUgc3Bhbiwgc28gYHNwZWNjdHggdGFzayBkb25lYCBjYW4gcnVuIGl0LgotIGB0ZW1wbGF0ZXMvZGVzaWduLm1kYCBlbmRzIGVhY2ggZGVjaXNpb24gd2l0aCBhIGBSZWZzOmAgbGluZS4KLSBgY29uZmlnLWZyYWdtZW50LnlhbWxgIGhvbGRzIHRoZSBgcnVsZXNgIGFuZCBgb3BlcmF0aW9uc2AgZm9yIGBvcGVuc3BlYy9jb25maWcueWFtbGAuIFRoZSBydWxlcyB0ZWxsIHRoZSBhZ2VudCB0byBnZXQgSURzIGZyb20gYHNwZWNjdHggaWQgbmV3YCBhbmQgbmFtZSB0aGUgdGVtcGxhdGVzIHBhdGguIFRoZSBgYXBwbHlgIGd1aWRhbmNlIHNheXMgdGhhdCBhIHRhc2sgY2xvc2VzIG9ubHkgd2l0aCBgc3BlY2N0eCB0YXNrIGRvbmUgPGlkPmAgYW5kIHRoYXQgdGhlIGFnZW50IHJ1bnMgdGhlIGBzcGVjY3R4LXJ1bmAgc2tpbGwsIG5ldmVyIGAvb3BzeDphcHBseWAuCgojIyBJbnN0YWxsIGJ5IGNvcHkKCi0gQ2xvbmUgdGhlIHJlcG9zaXRvcnk6IGBnaXQgY2xvbmUgaHR0cHM6Ly9naXRodWIuY29tL3NvbnFoL3NwZWMtY3R4YC4KLSBDb3B5IGBzY2hlbWFzL3NwZWMtZHJpdmVuLWlkcy90ZW1wbGF0ZXNgIHRvIGBvcGVuc3BlYy90ZW1wbGF0ZXMvc3BlYy1kcml2ZW4taWRzYCBpbiB5b3VyIHByb2plY3QuCi0gS2VlcCBgc2NoZW1hOiBzcGVjLWRyaXZlbmAgaW4gYG9wZW5zcGVjL2NvbmZpZy55YW1sYC4KLSBNZXJnZSBgY29uZmlnLWZyYWdtZW50LnlhbWxgIGludG8gYG9wZW5zcGVjL2NvbmZpZy55YW1sYCBieSBoYW5kLiBBZGQgaXRzIGBydWxlc2AgYW5kIGBvcGVyYXRpb25zYCBrZXlzLiBLZWVwIGV2ZXJ5IGl0ZW0gcXVvdGVkLgotIFJ1biBgb3BlbnNwZWMgdmFsaWRhdGUgLS1hbGxgLgoKIyMgSW5zdGFsbCB3aXRoIGluaXQgLS1zY2hlbWEKCmBgYGJhc2gKbnB4IC15IHNwZWMtY3R4IGluaXQgLS1zY2hlbWEKYGBgCgotIFRoZSBjb21tYW5kIGNvcGllcyB0aGUgZm91ciB0ZW1wbGF0ZXMgdG8gYG9wZW5zcGVjL3RlbXBsYXRlcy9zcGVjLWRyaXZlbi1pZHMvYC4KLSBJdCBhZGRzIHRoZSBgcnVsZXNgIGFuZCBgb3BlcmF0aW9uc2Aga2V5cyB0aGF0IHRoZSBjb25maWcgZG9lcyBub3QgaGF2ZSB5ZXQuIEEga2V5IHRoYXQgZXhpc3RzIGdldHMgdGhlIGl0ZW1zIGl0IGxhY2tzLiBPdGhlciBrZXlzIHN0YXkgYXMgdGhleSBhcmUuCi0gSXQgcXVvdGVzIGEgbGlzdCBpdGVtIHRoYXQgWUFNTCB3b3VsZCByZWFkIGFzIGEgbWFwcGluZy4KLSBJdCBkb2VzIG5vdCB0b3VjaCB0aGUgYHNjaGVtYWAga2V5LiBBIHByb2plY3QgdGhhdCBzdGlsbCBzYXlzIGBzY2hlbWE6IHNwZWMtZHJpdmVuLWlkc2AgZ2V0cyBhIG5vdGUuIFNldCBgc2NoZW1hOiBzcGVjLWRyaXZlbmAgYnkgaGFuZCBhbmQgZGVsZXRlIGBvcGVuc3BlYy9zY2hlbWFzL3NwZWMtZHJpdmVuLWlkcy9gLgoKIyMgVmVyc2lvbgoKVGhlIHRlbXBsYXRlcyBmb2xsb3cgdGhlIGBzcGVjLWRyaXZlbmAgdGVtcGxhdGVzIG9mIE9wZW5TcGVjIDEuMTQuMyB3aXRoIHRoZSBJRCBwbGFjZWhvbGRlcnMgYWRkZWQuIGB0ZXN0cy9zY2hlbWEvdmFsaWRhdGUuc2hgIGNoZWNrcyB0aGVtIG9uIHVwc3RyZWFtIE9wZW5TcGVjIGluIENJLgo=",
5
+ "schemas/spec-driven-ids/config-fragment.yaml": "IyBzcGVjLWN0eCBmcmFnbWVudCBmb3Igb3BlbnNwZWMvY29uZmlnLnlhbWwuIHNwZWNjdHggaW5pdCAtLXNjaGVtYSBhZGRzIGVhY2ggdG9wLWxldmVsIGtleQojIHRoYXQgdGhlIHByb2plY3QgY29uZmlnIGRvZXMgbm90IGhhdmUgeWV0LiBBIGtleSB0aGF0IGV4aXN0cyBnZXRzIHRoZSBpdGVtcyBpdCBsYWNrcy4KcnVsZXM6CiAgc3BlY3M6CiAgICAtICdFdmVyeSByZXF1aXJlbWVudCBoZWFkZXIgc3RhcnRzIHdpdGggaXRzIElELCBlLmcuICIjIyMgUmVxdWlyZW1lbnQ6IFJFUS1BQkMtMDAxIE5hbWUiLiBHZXQgdGhlIElEIGZyb20gYHNwZWNjdHggaWQgbmV3IFJFUSBBQkNgLicKICAgIC0gJ0V2ZXJ5IHNjZW5hcmlvIGhlYWRlciBzdGFydHMgd2l0aCBpdHMgSUQsIGUuZy4gIiMjIyMgU2NlbmFyaW86IFNDTi1BQkMtMDAxLTEgTmFtZSIuJwogICAgLSAnQSByZXF1aXJlbWVudCBtYXkgZW5kIHdpdGggYSBsaW5lICJSZWZzOiBSRVEtQUJDLTAwMiwgQURSLTAwMSIgdG8gbGluayByZWxhdGVkIElEcy4nCiAgICAtICdSZXF1aXJlbWVudCB0ZXh0IHN0YXlzIHVuZGVyIDUwMCBjaGFyYWN0ZXJzLiBNb3ZlIGRldGFpbCBpbnRvIHNjZW5hcmlvcy4nCiAgICAtICdUaGUgdGVtcGxhdGVzIHdpdGggdGhlIElEIHBsYWNlaG9sZGVycyBhcmUgaW4gb3BlbnNwZWMvdGVtcGxhdGVzL3NwZWMtZHJpdmVuLWlkcy8uIFN0YXJ0IGEgc3BlYyBmcm9tIHNwZWMubWQgYW5kIGEgdGFzayBsaXN0IGZyb20gdGFza3MubWQgdGhlcmUuJwogIGRlc2lnbjoKICAgIC0gJ0VhY2ggZGVjaXNpb24gaXMgb25lIGJ1bGxldCB1bmRlciAiIyMgRGVjaXNpb25zIi4gQWRkIG5ldyBkZWNpc2lvbnMgYXQgdGhlIGVuZC4nCiAgdGFza3M6CiAgICAtICdFdmVyeSB0YXNrIGNpdGVzIGF0IGxlYXN0IG9uZSBSRVEgSUQgaW4gc3F1YXJlIGJyYWNrZXRzLCBlLmcuICJbUkVRLUFCQy0wMDFdIi4nCiAgICAtICdFdmVyeSB0YXNrIHN0YXRlcyBpdHMgdmVyaWZpY2F0aW9uIGFzIGEgY29tbWFuZCBpbiBhIGNvZGUgc3BhbiBhZnRlciAiVmVyaWZ5OiIuJwoKb3BlcmF0aW9uczoKICBhcHBseToKICAgIGd1aWRhbmNlOgogICAgICAtICdTdGFydCBlYWNoIHRhc2sgd2l0aCBgc3BlY2N0eCB0YXNrIHN0YXJ0IDxpZD5gIGFuZCByZWFkIHRoZSBidW5kbGUgaXQgcHJpbnRzIGJlZm9yZSB5b3UgcmVhZCBzcGVjcy4nCiAgICAgIC0gJ1RhZyBjb2RlIHdpdGggdGhlIFJFUSBJRCBpdCBpbXBsZW1lbnRzIChhIGNvbW1lbnQgYC8vIFJFUS1BQkMtMDAxYCkuIFRhZyB0ZXN0cyB3aXRoIGAvLyBDb3ZlcnM6IFJFUS1BQkMtMDAxYC4nCiAgICAgIC0gJ0Nsb3NlIGVhY2ggdGFzayBvbmx5IHdpdGggYHNwZWNjdHggdGFzayBkb25lIDxpZD5gLiBOZXZlciBlZGl0IGEgY2hlY2tib3guIE5ldmVyIHJ1biBgL29wc3g6YXBwbHlgOyBydW4gdGhlIGBzcGVjY3R4LXJ1bmAgc2tpbGwuJwogICAgICAtICdSdW4gYHNwZWNjdHggY2hlY2sgLS1zdHJpY3RgIGFmdGVyIGVhY2ggdGFzayBncm91cC4nCiAgYXJjaGl2ZToKICAgIGd1aWRhbmNlOgogICAgICAtICdSdW4gYHNwZWNjdHggY2hlY2sgLS1zdHJpY3RgIGFuZCBgb3BlbnNwZWMgdmFsaWRhdGUgLS1hbGwgLS1zdHJpY3RgLiBCb3RoIG11c3QgcGFzcyBiZWZvcmUgYXJjaGl2ZS4nCiAgICAgIC0gJ1J1biBgb3BlbnNwZWMgdmFsaWRhdGUgLS1hbGwgLS1zdHJpY3RgIGFnYWluIGFmdGVyIGFyY2hpdmUgYW5kIGJlZm9yZSBwdXNoLicK",
7
6
  "schemas/spec-driven-ids/templates/design.md": "IyBEZXNpZ24KCiMjIENvbnRleHQKCjwhLS0gVGhlIGN1cnJlbnQgc3RhdGUgYW5kIHRoZSBjb25zdHJhaW50cyB0aGF0IHNoYXBlIHRoZSBhcHByb2FjaC4gVGhlIHByb3Bvc2FsIGhvbGRzIHRoZSBtb3RpdmF0aW9uLiAtLT4KCiMjIEdvYWxzIC8gTm9uLUdvYWxzCgoqKkdvYWxzOioqCjwhLS0gV2hhdCB0aGlzIGRlc2lnbiBnaXZlcyAtLT4KCioqTm9uLUdvYWxzOioqCjwhLS0gV2hhdCBzdGF5cyBvdXQgb2Ygc2NvcGUgLS0+CgojIyBEZWNpc2lvbnMKCjwhLS0gT25lIGJ1bGxldCBwZXIgZGVjaXNpb24uIFRoZSBJRCBvZiBhIGRlY2lzaW9uIGlzIDxjaGFuZ2UgbnVtYmVyPi9EPG4+IGJ5IHBvc2l0aW9uLiBBZGQgbmV3IG9uZXMgYXQgdGhlIGVuZC4gLS0+Ci0gPCEtLSBUaGUgZGVjaXNpb24sIHRoZSBhbHRlcm5hdGl2ZSwgYW5kIHdoeS4gLS0+IFJlZnM6IDwhLS0gUkVRLTxDQVA+LU5OTiwgQURSLU5OTiAtLT4KCiMjIFJpc2tzIC8gVHJhZGUtb2ZmcwoKPCEtLSBLbm93biByaXNrcyBhbmQgdGhlIG1pdGlnYXRpb24gZm9yIGVhY2ggLS0+Cg==",
8
7
  "schemas/spec-driven-ids/templates/proposal.md": "IyBQcm9wb3NhbAoKIyMgV2h5Cgo8IS0tIEV4cGxhaW4gdGhlIG1vdGl2YXRpb24gZm9yIHRoaXMgY2hhbmdlLiBXaGF0IHByb2JsZW0gZG9lcyB0aGlzIHNvbHZlPyBXaHkgbm93PyAtLT4KCiMjIFdoYXQgQ2hhbmdlcwoKPCEtLSBEZXNjcmliZSB3aGF0IHdpbGwgY2hhbmdlLiBCZSBzcGVjaWZpYyBhYm91dCBuZXcgY2FwYWJpbGl0aWVzLCBtb2RpZmljYXRpb25zLCBvciByZW1vdmFscy4gLS0+CgojIyBDYXBhYmlsaXRpZXMKCiMjIyBOZXcgQ2FwYWJpbGl0aWVzCjwhLS0gQ2FwYWJpbGl0aWVzIGJlaW5nIGludHJvZHVjZWQuIE5hbWUgZWFjaCBjYXBhYmlsaXR5IGZvciBhIGNvaGVzaXZlIHN5c3RlbQogICAgIGJlaGF2aW9yIHRoYXQgY2FuIG93biByZWxhdGVkIHJlcXVpcmVtZW50cyBhcyB0aGUgc3lzdGVtIGV2b2x2ZXMuIERvIG5vdCBuYW1lCiAgICAgaW1wbGVtZW50YXRpb24gdGFza3Mgb3IgcHJvcG9zYWwgc2VjdGlvbnMuIEF2b2lkIGJyb2FkIGNhdGNoLWFsbCBuYW1lcy4gVXNlCiAgICAga2ViYWItY2FzZSBmb3IgcGF0aCBzZWdtZW50cyB5b3UgaW50cm9kdWNlIChlLmcuLCB1c2VyLWF1dGggb3IgaWRlbnRpdHkvdXNlci1hdXRoKQogICAgIHRoYXQgZm9sbG93IHRoZSBwcm9qZWN0J3MgZXhpc3Rpbmcgc3BlYyBvcmdhbml6YXRpb24uIEVhY2ggY3JlYXRlcwogICAgIHNwZWNzLzxjYXBhYmlsaXR5LXBhdGg+L3NwZWMubWQuIC0tPgotIGA8Y2FwYWJpbGl0eS1wYXRoPmA6IDxicmllZiBkZXNjcmlwdGlvbiBvZiB3aGF0IHRoaXMgY2FwYWJpbGl0eSBjb3ZlcnM+CgojIyMgTW9kaWZpZWQgQ2FwYWJpbGl0aWVzCjwhLS0gRXhpc3RpbmcgY2FwYWJpbGl0aWVzIHdob3NlIFJFUVVJUkVNRU5UUyBhcmUgY2hhbmdpbmcgKG5vdCBqdXN0IGltcGxlbWVudGF0aW9uKS4KICAgICBPbmx5IGxpc3QgaGVyZSBpZiBzcGVjLWxldmVsIGJlaGF2aW9yIGNoYW5nZXMuIEVhY2ggbmVlZHMgYSBkZWx0YSBzcGVjIGZpbGUuCiAgICAgVXNlIHRoZSBleGFjdCBleGlzdGluZyBwYXRoIHVuZGVyIG9wZW5zcGVjL3NwZWNzLy4gTGVhdmUgZW1wdHkgaWYgbm8gcmVxdWlyZW1lbnQKICAgICBjaGFuZ2VzLiBBIGNoYW5nZSB3aXRoIG5vIGNhcGFiaWxpdGllcyBhdCBhbGwgKHB1cmUgcmVmYWN0b3IsIHRvb2xpbmcsIGRvY3MpCiAgICAgbXVzdCBzZXQgYHNraXBfc3BlY3M6IHRydWVgIGluIGl0cyAub3BlbnNwZWMueWFtbCAtIG9wZW5zcGVjIHZhbGlkYXRlIHJlamVjdHMKICAgICBhIHplcm8tZGVsdGEgY2hhbmdlIHdpdGhvdXQgdGhhdCBtYXJrZXIuIERvIG5vdCBpbnZlbnQgYSByZXF1aXJlbWVudCBqdXN0IHRvCiAgICAgc2F0aXNmeSB2YWxpZGF0aW9uLiAtLT4KLSBgPGV4aXN0aW5nLWNhcGFiaWxpdHktcGF0aD5gOiA8d2hhdCByZXF1aXJlbWVudCBpcyBjaGFuZ2luZz4KCiMjIEltcGFjdAoKPCEtLSBBZmZlY3RlZCBjb2RlLCBBUElzLCBkZXBlbmRlbmNpZXMsIHN5c3RlbXMgLS0+Cg==",
9
8
  "schemas/spec-driven-ids/templates/spec.md": "IyBTcGVjIERlbHRhCgojIyBQdXJwb3NlCjwhLS0gTmV3IGNhcGFiaWxpdHkgb25seS4gV3JpdGUgb25lIG9yIHR3byBzZW50ZW5jZXMgb2YgNTAgY2hhcmFjdGVycyBvciBtb3JlLiBEZWxldGUgdGhpcyBzZWN0aW9uIGZvciBhbiBleGlzdGluZyBjYXBhYmlsaXR5LiAtLT4KCiMjIEFEREVEIFJlcXVpcmVtZW50cwoKIyMjIFJlcXVpcmVtZW50OiBSRVEtPENBUD4tTk5OIDwhLS0gcmVxdWlyZW1lbnQgbmFtZSAtLT4KPCEtLSBSZXF1aXJlbWVudCB0ZXh0LiBSZXBsYWNlIFJFUS08Q0FQPi1OTk4gd2l0aCB0aGUgb3V0cHV0IG9mIGBzcGVjY3R4IGlkIG5ldyBSRVEgPENBUD5gLiAtLT4KClJlZnM6IDwhLS0gcmVsYXRlZCBJRHMgc3VjaCBhcyBBRFItMDAxLiBEZWxldGUgdGhpcyBsaW5lIHdoZW4gdGhlcmUgYXJlIG5vbmUuIC0tPgoKIyMjIyBTY2VuYXJpbzogU0NOLTxDQVA+LU5OTi0xIDwhLS0gc2NlbmFyaW8gbmFtZS4gR2V0IHRoZSBJRCBmcm9tIGBzcGVjY3R4IGlkIG5ldyBTQ04gPENBUD4gLS1mb3IgUkVRLTxDQVA+LU5OTmAuIC0tPgotICoqV0hFTioqIDwhLS0gY29uZGl0aW9uIC0tPgotICoqVEhFTioqIDwhLS0gZXhwZWN0ZWQgb3V0Y29tZSAtLT4K",
10
9
  "schemas/spec-driven-ids/templates/tasks.md": "IyBUYXNrcwoKIyMgMS4gPCEtLSBUYXNrIGdyb3VwIG5hbWUgLS0+CgotIFsgXSAxLjEgPCEtLSBUYXNrIGRlc2NyaXB0aW9uIC0tPiBbUkVRLTxDQVA+LU5OTl0gVmVyaWZ5OiBgPCEtLSBjb21tYW5kIC0tPmAKLSBbIF0gMS4yIDwhLS0gVGFzayBkZXNjcmlwdGlvbiAtLT4gW1JFUS08Q0FQPi1OTk5dIFZlcmlmeTogYDwhLS0gY29tbWFuZCAtLT5gCgojIyAyLiA8IS0tIFRhc2sgZ3JvdXAgbmFtZSAtLT4KCi0gWyBdIDIuMSA8IS0tIFRhc2sgZGVzY3JpcHRpb24gLS0+IFtSRVEtPENBUD4tTk5OXSBWZXJpZnk6IGA8IS0tIGNvbW1hbmQgLS0+YAo=",
11
- "skills/specctx-bootstrap/SKILL.md": "LS0tCm5hbWU6IHNwZWNjdHgtYm9vdHN0cmFwCmRlc2NyaXB0aW9uOiBTdGFydCBhIHNlc3Npb24gaW4gYW4gT3BlblNwZWMgcHJvamVjdCB0aGF0IHVzZXMgc3BlYy1jdHguIFVzZSBhdCB0aGUgc3RhcnQgb2YgZXZlcnkgc2Vzc2lvbiwgYW5kIG9uICJzdGFydCIsICJib290c3RyYXAiLCBvciAid2hhdCBzaG91bGQgSSB3b3JrIG9uIi4gTG9hZHMgb25seSB0aGUgc3BlYyB0ZXh0IHRoYXQgdGhlIG5leHQgdGFzayBuZWVkcy4KLS0tCgojIHNwZWNjdHgtYm9vdHN0cmFwCgpMb2FkIHRoZSBtaW5pbXVtIGNvbnRleHQgZm9yIG9uZSB0YXNrLiBSdW4gYHNwZWNjdHhgIGFzIGBucHggc3BlYy1jdHhgIHdoZW4gaXQgaXMgbm90IGluc3RhbGxlZC4KCiMjIFN0ZXBzCgoxLiBSdW4gYHNwZWNjdHggc3RhdHVzYC4gSXQgcmVidWlsZHMgYSBzdGFsZSBpbmRleCBmaXJzdC4gTm90ZSB0aGUgYWN0aXZlIGNoYW5nZSwgdGhlIGN1cnJlbnQgdGFzaywgYW5kIHRoZSBjb3VudCBvZiBvcGVuIHF1ZXN0aW9ucy4gVGhlIGxhc3QgbGluZSBgbmV4dDogPHN0ZXA+YCBuYW1lcyB0aGUgbmV4dCBzdGVwLiBFeGl0IDIgd2l0aCBgbm90IGFuIE9wZW5TcGVjIHByb2plY3RgIG1lYW5zIHRoZSBmb2xkZXIgaGFzIG5vIGBvcGVuc3BlYy9gLiBUZWxsIHRoZSB1c2VyIHRvIHJ1biBgbnB4IC15IEBmaXNzaW9uLWFpL29wZW5zcGVjQGxhdGVzdCBpbml0YCBhbmQgc3RvcC4KMi4gUmVhZCBgLmN0eC9oYW5kb2ZmLm1kYCBpZiBpdCBleGlzdHMuIE5vdGUgYGN1cnJlbnRgLCBgcmVvcGVuZWRgLCBhbmQgYG9wZW5fcXVlc3Rpb25zYC4KMy4gSWYgYHN0YXR1c2AgcHJpbnRzIGBubyBhY3RpdmUgY2hhbmdlYCwgc2hvdyB0aGUgb3BlbiBxdWVzdGlvbnMgdG8gdGhlIHVzZXIuIEFzayB3aGljaCBjaGFuZ2UgdG8gc3RhcnQuIFN0b3AgaGVyZS4KNC4gUGljayB0aGUgdGFzay4gVXNlIGBjdXJyZW50YCBmcm9tIHRoZSBoYW5kb2ZmLCB0aGVuIHRoZSB1c2VyJ3MgbWVzc2FnZSwgdGhlbiB0aGUgb3V0cHV0IG9mIGBzcGVjY3R4IHRhc2sgbmV4dGAuCjUuIFJ1biBgc3BlY2N0eCB0YXNrIHN0YXJ0IDx0YXNrPmAuIEl0IHByaW50cyB0aGUgYnVuZGxlIGZvciB0aGUgUkVRIElEcyBvZiB0aGUgdGFzayBhbmQgc2V0cyB0aGUgY3VycmVudCB0YXNrLgo2LiBSZWFkIHRoZSBidW5kbGUuIEVhY2ggYmxvY2sgc3RhcnRzIHdpdGggYC0tIDxpZD4gfCA8ZmlsZT46PGxpbmU+IHwgPHN0YXR1cz4gfCA8cmVhc29uPmAuIEEgYG1vZGlmaWVkYCBibG9jayBpcyB0aGUgcGVuZGluZyB0ZXh0IG9mIGFuIGFjdGl2ZSBjaGFuZ2UuIFRydXN0IGl0IG92ZXIgdGhlIG1haW4gc3BlYy4KNy4gSWYgdGhlIGJ1bmRsZSBlbmRzIHdpdGggYHRydW5jYXRlZDogTiBlbnRyaWVzIG9taXR0ZWQ6IDxpZHM+YCwgcnVuIGBzcGVjY3R4IGJ1bmRsZSA8aWQ+YCBmb3IgZWFjaCBJRCB0aGF0IHRoZSB0YXNrIG5lZWRzLgo4LiBTYXkgaW4gb25lIGxpbmUgd2hpY2ggdGFzayB5b3UgYXJlIG9uIGFuZCB3aGljaCBJRHMgeW91IGxvYWRlZC4gVGhlbiBzdGFydCB0aGUgd29yay4KCiMjIFJ1bGVzCgotIERvIG5vdCBvcGVuIGBvcGVuc3BlYy9zcGVjcy9gIG9yIGBvcGVuc3BlYy9jaGFuZ2VzLyovc3BlY3MvYCBieSBoYW5kLiBVc2UgYHNwZWNjdHggYnVuZGxlYCBvciBgc3BlY2N0eCB0YXNrIHN0YXJ0YC4KLSBSZWFkIGF0IG1vc3QgMTAsMDAwIGNoYXJhY3RlcnMgb2Ygc3BlYyB0ZXh0IGJlZm9yZSB0aGUgZmlyc3QgY29kZSBlZGl0LgotIFRhZyBjb2RlIHdpdGggYC8vIFJFUS1BQkMtMDAxYCBhbmQgdGVzdHMgd2l0aCBgLy8gQ292ZXJzOiBSRVEtQUJDLTAwMWAuCi0gR2V0IGEgbmV3IElEIGZyb20gYHNwZWNjdHggaWQgbmV3IFJFUSA8Q0FQPmAuIE5ldmVyIGNvdW50IG51bWJlcnMgYnkgaGFuZC4KLSBDbG9zZSB0aGUgdGFzayB3aXRoIHRoZSBgc3BlY2N0eC1kb25lYCBza2lsbC4K",
12
- "skills/specctx-done/SKILL.md": "LS0tCm5hbWU6IHNwZWNjdHgtZG9uZQpkZXNjcmlwdGlvbjogQ2xvc2UgYSB0YXNrIGluIGFuIE9wZW5TcGVjIHByb2plY3QgdGhhdCB1c2VzIHNwZWMtY3R4LiBSdW5zIHRoZSBWZXJpZnkgY29tbWFuZCwgd3JpdGVzIGV2aWRlbmNlLCBzZXRzIHRoZSBjaGVja2JveCwgd3JpdGVzIHRoZSBoYW5kb2ZmLCBhbmQgc2hvd3MgdGhlIG1ldHJpY3MuIFVzZSB3aGVuIHRoZSB3b3JrIG9mIGEgdGFzayBpcyBjb21wbGV0ZSwgb3Igb24gImRvbmUiLCAiY2xvc2UgdGhlIHRhc2siLCBhbmQgImVuZCB0aGUgc2Vzc2lvbiIuCi0tLQoKIyBzcGVjY3R4LWRvbmUKCkNsb3NlIHRoZSBjdXJyZW50IHRhc2sgd2l0aCBldmlkZW5jZS4gUnVuIGBzcGVjY3R4YCBhcyBgbnB4IHNwZWMtY3R4YCB3aGVuIGl0IGlzIG5vdCBpbnN0YWxsZWQuCgojIyBTdGVwcwoKMS4gUnVuIGBzcGVjY3R4IHRhc2sgZG9uZSA8dGFzaz5gLiBJdCBydW5zIHRoZSBgVmVyaWZ5OmAgY29tbWFuZCBvZiB0aGUgdGFzayBpbiB0aGUgcHJvamVjdCByb290LgoyLiBPbiBleGl0IDAgaXQgd3JpdGVzIGAuY3R4L2V2aWRlbmNlLzxjaGFuZ2U+Lzx0YXNrPi5qc29uYCBhbmQgc2V0cyBgW3hdYCBvbiB0aGUgdGFzayBsaW5lLiBOb3RoaW5nIGVsc2UgaW4gYHRhc2tzLm1kYCBjaGFuZ2VzLgozLiBPbiBhIGZhaWx1cmUgaXQgcHJpbnRzIHRoZSBsYXN0IDIwIGxpbmVzIG9mIG91dHB1dCBhbmQgdGhlbiB0aGUgbGluZSBgVmVyaWZ5IGZhaWxlZCAoZXhpdCA8bj4pLiBUaGUgdGFzayBzdGF5cyBvcGVuLmAgSXQgZXhpdHMgMS4gRml4IHRoZSBjYXVzZSBhbmQgcnVuIHN0ZXAgMSBhZ2Fpbi4KNC4gSWYgdGhlIHRhc2sgaGFzIHByb3NlIGFmdGVyIGBWZXJpZnk6YCBhbmQgbm8gY29tbWFuZCwgcnVuIGBzcGVjY3R4IHRhc2sgZG9uZSA8dGFzaz4gLS1tYW51YWwgIjx3aGF0IHlvdSBjaGVja2VkPiJgLgo1LiBBZnRlciB0aGUgbGFzdCB0YXNrIG9mIGEgZ3JvdXAsIHJ1biBgc3BlY2N0eCBjaGVjayAtLXN0cmljdGAuIEZpeCBldmVyeSBmaW5kaW5nIGJlZm9yZSB0aGUgbmV4dCBncm91cC4KNi4gUnVuIGBzcGVjY3R4IGhhbmRvZmYgd3JpdGVgLiBJdCB3cml0ZXMgYC5jdHgvaGFuZG9mZi5tZGAgZnJvbSB0aGUgaW5kZXgsIHRoZSBldmlkZW5jZSwgYW5kIHRoZSBvcGVuIHF1ZXN0aW9ucy4KNy4gUnVuIGBzcGVjY3R4IHN0YXRzIC0tY2hhbmdlIDxjaGFuZ2U+YC4gUmVwb3J0IHRoZSBmaXZlIG1ldHJpY3Mgb2YgdGhlIGNoYW5nZSBpbiBvbmUgbGluZSBlYWNoLgo4LiBDb21taXQgdGhlIHdvcmsgdG9nZXRoZXIgd2l0aCBgLmN0eC9gLiBMZWF2ZSBgLmN0eC9pbmRleC5qc29uYCBvdXQgb2YgZ2l0LgoKIyMgUnVsZXMKCi0gTmV2ZXIgdGljayBhIGNoZWNrYm94IGJ5IGhhbmQuIGBjaGVjayAtLXN0cmljdGAgcmVwb3J0cyBhIHRpY2tlZCB0YXNrIHdpdGggbm8gZXZpZGVuY2UgYXMgYGRvbmUtd2l0aG91dC1ldmlkZW5jZWAuCi0gSWYgYSBzcGVjIGNoYW5nZWQgYWZ0ZXIgeW91IGNsb3NlZCBhIHRhc2ssIHJ1biBgc3BlY2N0eCB0YXNrIHJlb3BlbiA8dGFzaz4gIjxyZWFzb24+ImAuCi0gVG8gbGVhdmUgYSBxdWVzdGlvbiBmb3IgdGhlIG5leHQgc2Vzc2lvbiwgcnVuIGBzcGVjY3R4IGhhbmRvZmYgYXNrICI8cXVlc3Rpb24+ImAgYmVmb3JlIHN0ZXAgNi4K",
13
- "skills/specctx-next/SKILL.md": "LS0tCm5hbWU6IHNwZWNjdHgtbmV4dApkZXNjcmlwdGlvbjogUGljayBhbmQgc3RhcnQgdGhlIG5leHQgdGFzayBpbiB0aGUgbWlkZGxlIG9mIGEgc2Vzc2lvbiBpbiBhbiBPcGVuU3BlYyBwcm9qZWN0IHRoYXQgdXNlcyBzcGVjLWN0eC4gVXNlIGFmdGVyIHlvdSBjbG9zZSBhIHRhc2ssIG9yIG9uICJuZXh0IHRhc2siIGFuZCAid2hhdCBpcyBuZXh0Ii4KLS0tCgojIHNwZWNjdHgtbmV4dAoKTW92ZSB0byB0aGUgbmV4dCBvcGVuIHRhc2suIFJ1biBgc3BlY2N0eGAgYXMgYG5weCBzcGVjLWN0eGAgd2hlbiBpdCBpcyBub3QgaW5zdGFsbGVkLgoKIyMgU3RlcHMKCjEuIFJ1biBgc3BlY2N0eCB0YXNrIG5leHRgLiBJdCBwcmludHMgdGhlIHRhc2sgSUQgYW5kIHRleHQsIHRoZW4gYHJlcXM6YCBhbmQgYHZlcmlmeTpgLgoyLiBJZiBpdCBwcmludHMgYG5vIG9wZW4gdGFzay4gRXZlcnkgdGFzayBpbiB0aGUgYWN0aXZlIGNoYW5nZXMgaXMgZG9uZS4gTmV4dDogYXJjaGl2ZSA8Y2hhbmdlPi5gLCBldmVyeSB0YXNrIG9mIHRoZSBhY3RpdmUgY2hhbmdlcyBoYXMgaXRzIGNoZWNrYm94IHNldC4gUnVuIGBzcGVjY3R4IHN0YXR1c2AuIEl0cyBsYXN0IGxpbmUgaXMgYG5leHQ6IGFyY2hpdmUgPGNoYW5nZT5gLiBUZWxsIHRoZSB1c2VyIHRoYXQgdGhlIGNoYW5nZSBpcyByZWFkeSBmb3IgYHNwZWNjdHggY2hlY2sgLS1zdHJpY3RgIGFuZCBhcmNoaXZlLiBTdG9wIGhlcmUuCjMuIFJ1biBgc3BlY2N0eCB0YXNrIHN0YXJ0IDx0YXNrPmAuIEl0IHByaW50cyB0aGUgYnVuZGxlIGZvciB0aGUgUkVRIElEcyBvZiB0aGUgdGFzayBhbmQgc2V0cyB0aGUgY3VycmVudCB0YXNrIGluIGAuY3R4L2N1cnJlbnQuanNvbmAuCjQuIFJlYWQgdGhlIGJ1bmRsZS4gUmVxdWVzdCBhbiBvbWl0dGVkIElEIHdpdGggYHNwZWNjdHggYnVuZGxlIDxpZD5gIG9ubHkgd2hlbiB0aGUgdGFzayBuZWVkcyBpdC4KNS4gUnVuIGBzcGVjY3R4IHRhc2sgdmVyaWZ5IDx0YXNrPmAgb25jZSBiZWZvcmUgdGhlIHdvcmsuIEl0IHJ1bnMgdGhlIGBWZXJpZnk6YCBjb21tYW5kIGFuZCB3cml0ZXMgbm90aGluZy4gQSBmYWlsdXJlIG5vdyBzaG93cyB3aGF0IHRoZSB3b3JrIG11c3QgZml4Lgo2LiBTYXkgaW4gb25lIGxpbmUgd2hpY2ggdGFzayB5b3UgYXJlIG9uLiBUaGVuIHN0YXJ0IHRoZSB3b3JrLgoKIyMgUnVsZXMKCi0gVGFrZSB0aGUgdGFza3MgaW4gdGhlIG9yZGVyIHRoYXQgYHNwZWNjdHggdGFzayBuZXh0YCBnaXZlcy4gRWFybGllciB0YXNrcyBpbiBhIGdyb3VwIGNvbWUgZmlyc3QuCi0gQSBxdWVzdGlvbiB0aGF0IGJsb2NrcyB5b3UgZ29lcyB0byBgc3BlY2N0eCBoYW5kb2ZmIGFzayAiPHF1ZXN0aW9uPiJgLiBUaGVuIGNvbnRpbnVlIHdpdGggd2hhdCB5b3UgY2FuIGRvLgotIENsb3NlIHRoZSB0YXNrIHdpdGggdGhlIGBzcGVjY3R4LWRvbmVgIHNraWxsLgo=",
10
+ "skills/specctx-bootstrap/SKILL.md": "LS0tCm5hbWU6IHNwZWNjdHgtYm9vdHN0cmFwCmRlc2NyaXB0aW9uOiBTdGFydCBhIHNlc3Npb24gaW4gYW4gT3BlblNwZWMgcHJvamVjdCB0aGF0IHVzZXMgc3BlYy1jdHguIFVzZSBhdCB0aGUgc3RhcnQgb2YgZXZlcnkgc2Vzc2lvbiwgYW5kIG9uICJzdGFydCIsICJib290c3RyYXAiLCBvciAid2hhdCBzaG91bGQgSSB3b3JrIG9uIi4gTG9hZHMgb25seSB0aGUgc3BlYyB0ZXh0IHRoYXQgdGhlIG5leHQgdGFzayBuZWVkcy4KLS0tCgpUaGlzIHNraWxsIGlzIG5vdyBgc3BlY2N0eC1ydW5gLiBSdW4gaXQuCg==",
11
+ "skills/specctx-done/SKILL.md": "LS0tCm5hbWU6IHNwZWNjdHgtZG9uZQpkZXNjcmlwdGlvbjogQ2xvc2UgYSB0YXNrIGluIGFuIE9wZW5TcGVjIHByb2plY3QgdGhhdCB1c2VzIHNwZWMtY3R4LiBSdW5zIHRoZSBWZXJpZnkgY29tbWFuZCwgd3JpdGVzIGV2aWRlbmNlLCBzZXRzIHRoZSBjaGVja2JveCwgd3JpdGVzIHRoZSBoYW5kb2ZmLCBhbmQgc2hvd3MgdGhlIG1ldHJpY3MuIFVzZSB3aGVuIHRoZSB3b3JrIG9mIGEgdGFzayBpcyBjb21wbGV0ZSwgb3Igb24gImRvbmUiLCAiY2xvc2UgdGhlIHRhc2siLCBhbmQgImVuZCB0aGUgc2Vzc2lvbiIuCi0tLQoKVGhpcyBza2lsbCBpcyBub3cgYHNwZWNjdHgtcnVuYC4gUnVuIGl0Lgo=",
12
+ "skills/specctx-next/SKILL.md": "LS0tCm5hbWU6IHNwZWNjdHgtbmV4dApkZXNjcmlwdGlvbjogUGljayBhbmQgc3RhcnQgdGhlIG5leHQgdGFzayBpbiB0aGUgbWlkZGxlIG9mIGEgc2Vzc2lvbiBpbiBhbiBPcGVuU3BlYyBwcm9qZWN0IHRoYXQgdXNlcyBzcGVjLWN0eC4gVXNlIGFmdGVyIHlvdSBjbG9zZSBhIHRhc2ssIG9yIG9uICJuZXh0IHRhc2siIGFuZCAid2hhdCBpcyBuZXh0Ii4KLS0tCgpUaGlzIHNraWxsIGlzIG5vdyBgc3BlY2N0eC1ydW5gLiBSdW4gaXQuCg==",
13
+ "skills/specctx-run/SKILL.md": "LS0tCm5hbWU6IHNwZWNjdHgtcnVuCmRlc2NyaXB0aW9uOiBSdW4gdGhlIHNwZWMtY3R4IGxvb3AgaW4gYW4gT3BlblNwZWMgcHJvamVjdC4gVXNlIG9uICJydW4iLCAiY29udGludWUiLCAibmV4dCB0YXNrIiwgImJ1aWxkIHRoaXMiLCAiY2Fycnkgb24iLCBhbmQgb24gYSBmaXJzdCBtZXNzYWdlIHRoYXQgZGVzY3JpYmVzIGEgY2hhbmdlIHRvIGJ1aWxkLiBUaGUgZW5naW5lIHBpY2tzIHRoZSBuZXh0IGFjdGlvbi4gVGhlIHNraWxsIGFjdHMgb24gaXQgdW50aWwgdGhlIGNoYW5nZSByZWFjaGVzIHRoZSBhcmNoaXZlIG9yIGEgaHVtYW4gbXVzdCBkZWNpZGUuCi0tLQoKIyBzcGVjY3R4LXJ1bgoKUnVuIGBzcGVjY3R4YCBhcyBgbnB4IHNwZWMtY3R4YCB3aGVuIGl0IGlzIG5vdCBpbnN0YWxsZWQuIGBvcGVuc3BlY2AgaXMgdGhlIGNvbW1hbmQgaW4gYFtnYXRlXSBvcGVuc3BlY2Agb2YgYHNwZWMtY3R4LnRvbWxgLgoKIyMgVGhlIGxvb3AKCjEuIFJ1biBgc3BlY2N0eCBuZXh0IC0tanNvbmAuIFJlYWQgYGFjdGlvbmAsIGBjaGFuZ2VgIChgPGM+YCksIGB0YXNrYCAoYDx0PmApLCBgY29tbWFuZGAsIGByZWFzb25gLCBhbmQgYGh1bWFuYC4KMi4gQWN0IG9uIGBhY3Rpb25gIGFzIHRoZSB0YWJsZSBiZWxvdyBzYXlzLgozLiBSdW4gYHNwZWNjdHggaGFuZG9mZiB3cml0ZWAuCjQuIFJlcGVhdCBmcm9tIHN0ZXAgMSB1bnRpbCBgYWN0aW9uYCBpcyBgc3RvcGAgb3IgYGh1bWFuYCBpcyB0cnVlLgoKIyMgQWN0aW9ucwoKLSBgcGxhbmA6IGZvbGxvdyB0aGUgdXBzdHJlYW0gYG9wZW5zcGVjLXByb3Bvc2VgIHNraWxsIGZvciB0aGUgY2hhbmdlIGluIGBjb21tYW5kYC4gVGFrZSBldmVyeSBJRCBmcm9tIGBzcGVjY3R4IGlkIG5ldyBSRVEgPENBUD5gIGFuZCBgc3BlY2N0eCBpZCBuZXcgU0NOIDxDQVA+IC0tZm9yIDxSRVE+YC4gR2l2ZSBldmVyeSB0YXNrIGEgYFtSRVEtLi4uXWAgY2l0YXRpb24gYW5kIGEgYFZlcmlmeTpgIGNvZGUgc3Bhbi4gVGhlbiBydW4gYHNwZWNjdHggY2hlY2sgLS1zdHJpY3RgIGFuZCBgb3BlbnNwZWMgdmFsaWRhdGUgPGM+IC0tc3RyaWN0YC4gRml4IGV2ZXJ5IGZpbmRpbmcuIFN0b3AgYW5kIHNob3cgdGhlIHBsYW4gdG8gdGhlIHVzZXIuIFRoaXMgaXMgdGhlIHBsYW4gc3RvcC4KLSBgY2l0ZWA6IHJ1biBgc3BlY2N0eCBxdWVyeSAtLWNoYW5nZSA8Yz4gLS1raW5kIHJlcWAuIEFkZCB0aGUgYFtSRVEtLi4uXWAgY2l0YXRpb24gYW5kIGEgYFZlcmlmeTpgIGNvZGUgc3BhbiB0byB0aGUgdGFzayBsaW5lIG5hbWVkIGluIGB0YXNrYC4gUnVuIGBzcGVjY3R4IGNoZWNrYC4gQ29udGludWUuCi0gYHN0YXJ0YDogcnVuIGBzcGVjY3R4IHRhc2sgc3RhcnQgPHQ+YC4gUmVhZCB0aGUgYnVuZGxlIGl0IHByaW50cy4gQ29udGludWUuCi0gYHdvcmtgOiBpbXBsZW1lbnQgdGhlIHRhc2suIFRhZyBjb2RlIHdpdGggYC8vIFJFUS0uLi5gLiBUYWcgdGVzdHMgd2l0aCBgLy8gQ292ZXJzOiBSRVEtLi4uYC4gVGhlbiBydW4gYHNwZWNjdHggdGFzayBkb25lIDx0PmAuCi0gYGZpeGA6IHJlYWQgYHJlYXNvbmAuIEl0IGhvbGRzIHRoZSB0YWlsIG9mIHRoZSBmYWlsZWQgVmVyaWZ5IG91dHB1dC4gRml4IHRoZSBjYXVzZS4gUnVuIGBzcGVjY3R4IHRhc2sgZG9uZSA8dD5gIGFnYWluLgotIGByZXBhaXJgOiBydW4gYHNwZWNjdHggdGFzayBkb25lIDx0PmAuIEl0IHJ1bnMgVmVyaWZ5IGZvciBhIHRpY2tlZCB0YXNrIHRoYXQgaGFzIG5vIGV2aWRlbmNlLgotIGBnYXRlYDogcnVuIGBzcGVjY3R4IGdhdGUgLS1zdHJpY3RgLiBGaXggZXZlcnkgZmluZGluZy4gUnVuIGl0IGFnYWluIHVudGlsIGl0IGV4aXRzIDAuCi0gYGFyY2hpdmVgOiB3aGVuIGBodW1hbmAgaXMgdHJ1ZSwgc3RvcCBhbmQgYXNrIHRoZSB1c2VyIGluIG9uZSBsaW5lIHdoZXRoZXIgdG8gYXJjaGl2ZSBgPGM+YC4gV2hlbiBgaHVtYW5gIGlzIGZhbHNlLCBmb2xsb3cgdGhlIHVwc3RyZWFtIGBvcGVuc3BlYy1hcmNoaXZlLWNoYW5nZWAgc2tpbGwuIFRoZW4gcnVuIGBvcGVuc3BlYyB2YWxpZGF0ZSAtLWFsbCAtLXN0cmljdGAsIGBzcGVjY3R4IGNoZWNrIC0tc3RyaWN0YCwgYW5kIGBzcGVjY3R4IGhhbmRvZmYgd3JpdGVgLgotIGBhc2tgOiBwcmludCBgcmVhc29uYC4gSXQgaXMgdGhlIG9wZW4gcXVlc3Rpb24uIFN0b3AuIFRoZSB1c2VyIGFuc3dlcnMgd2l0aCBgc3BlY2N0eCBoYW5kb2ZmIHJlc29sdmUgPG4+ICI8YW5zd2VyPiJgLgotIGBzdG9wYDogcHJpbnQgYHJlYXNvbmAuIFN0b3AuCgojIyBSdWxlcwoKLSBOZXZlciB0aWNrIGEgY2hlY2tib3ggYnkgaGFuZC4gYHNwZWNjdHggdGFzayBkb25lYCBpcyB0aGUgb25seSB3YXkgYSB0YXNrIGNsb3Nlcy4KLSBOZXZlciB1c2UgYC0tbWFudWFsYCBvbiBhIHRhc2sgd2l0aCBhIFZlcmlmeSBjb21tYW5kLgotIE5ldmVyIGNhbGwgYC9vcHN4OmFwcGx5YC4gVGhpcyBza2lsbCByZXBsYWNlcyBpdC4KLSBOZXZlciByZWFkIGBvcGVuc3BlYy9zcGVjcy9gIG9yIGBvcGVuc3BlYy9jaGFuZ2VzLyovc3BlY3MvYCBkaXJlY3RseS4gVXNlIHRoZSBidW5kbGUgZnJvbSBgdGFzayBzdGFydGAgb3IgYHNwZWNjdHggYnVuZGxlIDxpZD5gLgotIFN0b3Agb24gYW55IGBhY3Rpb25gIG5vdCBpbiB0aGUgbGlzdCBhYm92ZS4gUHJpbnQgdGhlIG9iamVjdCBhbmQgYXNrIHRoZSB1c2VyLgotIEtlZXAgbm8gc3RhdGUgaW4geW91ciBjb250ZXh0LiBBIG5ldyBzZXNzaW9uIHN0YXJ0cyB0aGUgc2FtZSBsb29wIGFnYWluIHdpdGggc3RlcCAxLgo=",
14
14
  };
@@ -0,0 +1,81 @@
1
+ // REQ-ADOPT-008 the baseline against the merge base: new entries fail the gate (020/D2).
2
+ import { spawnSync } from "node:child_process";
3
+ import { parseLintLine } from "../lint/counts.js";
4
+ import { cmpStr } from "../util/pystr.js";
5
+ import { BASELINE_PATH } from "./baseline.js";
6
+ /**
7
+ * Lines of `current` that are new debt against `base`.
8
+ * A line that the base lacks is new. A `lint <file> <rule> <count>` line with a count above
9
+ * the base line of the same key is new, and reads `lint <file> <rule> <count> (base <n>)`.
10
+ */
11
+ export function newEntries(current, base) {
12
+ const baseSet = new Set(base);
13
+ const baseLint = new Map();
14
+ for (const b of base) {
15
+ const l = parseLintLine(b);
16
+ if (l)
17
+ baseLint.set(l.key, l.count);
18
+ }
19
+ const out = [];
20
+ for (const c of current) {
21
+ if (baseSet.has(c))
22
+ continue;
23
+ const l = parseLintLine(c);
24
+ if (l) {
25
+ const n = baseLint.get(l.key);
26
+ if (n === undefined)
27
+ out.push(c);
28
+ else if (l.count > n)
29
+ out.push(`${c} (base ${n})`);
30
+ continue;
31
+ }
32
+ out.push(c);
33
+ }
34
+ return [...new Set(out)].sort(cmpStr);
35
+ }
36
+ function git(root, args) {
37
+ const r = spawnSync("git", args, { cwd: root, encoding: "utf8" });
38
+ return { ok: r.status === 0, out: (r.stdout ?? "").trim() };
39
+ }
40
+ /** `.ctx/baseline.json` at `git merge-base HEAD <base>`, or the reason to skip the step. */
41
+ export function baseAtMergeBase(root, base) {
42
+ const inside = git(root, ["rev-parse", "--is-inside-work-tree"]);
43
+ if (!inside.ok || inside.out !== "true")
44
+ return { skip: "no git repository" };
45
+ const mb = git(root, ["merge-base", "HEAD", base]);
46
+ if (!mb.ok || !mb.out)
47
+ return { skip: `no merge base with ${base}` };
48
+ const sha = mb.out;
49
+ const show = spawnSync("git", ["show", `${sha}:${BASELINE_PATH}`], { cwd: root, encoding: "utf8" });
50
+ if (show.status !== 0)
51
+ return { skip: `no ${BASELINE_PATH} at ${sha.slice(0, 7)}` };
52
+ let v;
53
+ try {
54
+ v = JSON.parse(show.stdout);
55
+ }
56
+ catch {
57
+ return { skip: `no ${BASELINE_PATH} at ${sha.slice(0, 7)}` };
58
+ }
59
+ if (!Array.isArray(v) || !v.every((x) => typeof x === "string"))
60
+ return { skip: `no ${BASELINE_PATH} at ${sha.slice(0, 7)}` };
61
+ return { lines: v, sha };
62
+ }
63
+ /** True when the subject starts with `baseline:`, the same pattern as REQ-GOV-007 for `release:`. */
64
+ export const isBaselineSubject = (subject) => subject.trimStart().startsWith("baseline:");
65
+ /**
66
+ * The subject of HEAD. On a merge commit, such as a pull request checkout in CI, the subject of the
67
+ * second parent counts too, because that is the commit the author wrote (020/D4).
68
+ */
69
+ export function headSubjects(root) {
70
+ const head = git(root, ["log", "-1", "--format=%s", "HEAD"]);
71
+ if (!head.ok)
72
+ return [];
73
+ const out = [head.out];
74
+ const parents = git(root, ["rev-list", "--parents", "-n", "1", "HEAD"]);
75
+ if (parents.ok && parents.out.split(/\s+/).length > 2) {
76
+ const second = git(root, ["log", "-1", "--format=%s", "HEAD^2"]);
77
+ if (second.ok)
78
+ out.push(second.out);
79
+ }
80
+ return out;
81
+ }
@@ -6,7 +6,8 @@ import { changeKey } from "../index/scan.js";
6
6
  import { listEvidence } from "../tasks/evidence.js";
7
7
  import { cmpTuple } from "../util/pystr.js";
8
8
  import { evidenceFindings } from "./evidence.js";
9
- const RETIRED_RE = /\b(REQ-[A-Z]{2,6}-\d{3}|ADR-\d{3})\b/g;
9
+ // the first ID of a retired row can be a scenario. Only a REQ or ADR can be reused, but the SCN still counts as the row ID.
10
+ const RETIRED_RE = /\b(REQ-[A-Z]{2,6}-\d{3}|SCN-[A-Z]{2,6}-\d{3}-\d+|ADR-\d{3})\b/g;
10
11
  const REQ_CAP = /^REQ-([A-Z]{2,6})-/;
11
12
  export function retiredIds(root) {
12
13
  const p = join(root, "decisions", "retired-ids.md");
@@ -49,6 +50,51 @@ export function duplicateChangeKeys(root) {
49
50
  }
50
51
  return out;
51
52
  }
53
+ // REQ-ADOPT-010 the ID of a TO line is bare or in square brackets (027/D4)
54
+ const TO_LINE = /^-\s*TO:\s*`###\s+Requirement:\s*(?:(REQ-[A-Z]{2,6}-\d{3})|\[(REQ-[A-Z]{2,6}-\d{3})\](?=\s|`))?\s*(.*?)`\s*$/;
55
+ /** The headers that the TO lines of the RENAMED blocks of one delta file name: [id or null, title]. */
56
+ function renamedTargets(root, file) {
57
+ const out = [];
58
+ let section = "";
59
+ for (const line of readFileSync(join(root, file), "utf8").split(/\r?\n/)) {
60
+ if (line.startsWith("## ")) {
61
+ section = line.slice(3).trim().split(" ")[0].toUpperCase();
62
+ continue;
63
+ }
64
+ if (section !== "RENAMED")
65
+ continue;
66
+ const m = TO_LINE.exec(line.trim());
67
+ if (m)
68
+ out.push([m[1] ?? m[2] ?? null, m[3].trim()]);
69
+ }
70
+ return out;
71
+ }
72
+ /**
73
+ * REQ-CHK-001 retitle-needs-renamed: a MODIFIED or REMOVED header of an active change whose ID exists in main
74
+ * with another title, and whose delta file has no RENAMED TO line with that header. Upstream OpenSpec matches
75
+ * delta headers by text, so the archive needs the RENAMED pair (021/D1, ADR-006 item 7).
76
+ */
77
+ export function retitleFindings(root, entries) {
78
+ const main = new Map();
79
+ for (const e of entries)
80
+ if (e.kind === "req" && e.change === "main" && e.status === "active")
81
+ main.set(e.id, e);
82
+ const targets = new Map();
83
+ const out = [];
84
+ for (const e of entries) {
85
+ if (e.kind !== "req" || (e.status !== "modified" && e.status !== "removed") || e.file.includes("/archive/"))
86
+ continue;
87
+ const m = main.get(e.id);
88
+ if (!m || m.title === e.title)
89
+ continue;
90
+ if (!targets.has(e.file))
91
+ targets.set(e.file, renamedTargets(root, e.file));
92
+ if (targets.get(e.file).some(([id, title]) => title === e.title && (id === null || id === e.id)))
93
+ continue;
94
+ out.push({ file: e.file, line: e.line, rule: "retitle-needs-renamed", id: e.id, detail: `"${m.title}" -> "${e.title}"` });
95
+ }
96
+ return out;
97
+ }
52
98
  /** Sorted, unique findings. The scan never reads .ctx/, so evidence adds no index entry. */
53
99
  export function check(root, cfg, data, strict) {
54
100
  const entries = data.entries;
@@ -122,5 +168,7 @@ export function check(root, cfg, data, strict) {
122
168
  const uniq = new Map();
123
169
  for (const f of findings)
124
170
  uniq.set(JSON.stringify(f), f);
125
- return [...uniq.values()].sort((a, b) => cmpTuple(a, b)).map(([file, line, rule, id]) => ({ file, line, rule, id }));
171
+ const plain = [...uniq.values()].map(([file, line, rule, id]) => ({ file, line, rule, id }));
172
+ const all = [...plain, ...retitleFindings(root, entries)];
173
+ return all.sort((a, b) => cmpTuple([a.file, a.line, a.rule, a.id], [b.file, b.line, b.rule, b.id]));
126
174
  }
@@ -16,10 +16,16 @@ export const RULES = {
16
16
  "unknown-cap": { level: "hard", hint: "Add the code to caps under [ids] in spec-ctx.toml." },
17
17
  uncovered: { level: "hard", hint: "Add a test with a Covers tag for the requirement." },
18
18
  "scenario-untested": { level: "hard", hint: "Name the scenario ID in a test." },
19
- "done-without-evidence": { level: "hard", hint: "Run specctx task done, or specctx task backfill for old tasks." },
19
+ "done-without-evidence": { level: "hard", hint: "Run specctx task done. It runs the Verify command and writes the evidence." },
20
20
  "stale-evidence": { level: "hard", hint: "Run specctx task reopen and then specctx task done." },
21
21
  "evidence-without-done": { level: "hard", hint: "Run specctx task done, or remove the evidence file." },
22
22
  "manual-evidence": { level: "advisory", hint: "Give the task a Verify command and run specctx task done again." },
23
+ // REQ-CHK-001 the hint is the block to paste. The finding line carries the ID and both titles (021/D3).
24
+ // REQ-ADOPT-010 FROM copies the main header and TO copies the delta header, each in its own form (027/D4).
25
+ "retitle-needs-renamed": {
26
+ level: "hard",
27
+ hint: "Add to the delta before the MODIFIED block. Write each ID as its header writes it, bare or in brackets:\n## RENAMED Requirements\n- FROM: `### Requirement: <ID> <old title>`\n- TO: `### Requirement: <ID> <new title>`",
28
+ },
23
29
  };
24
30
  export function hintOf(rule) {
25
31
  return RULES[rule]?.hint ?? "Read the check rules in the check spec.";
package/dist/cli/args.js CHANGED
@@ -4,6 +4,7 @@ export const GLOBAL_FLAGS = { root: "string", json: "bool", help: "bool", versio
4
4
  export const COMMAND_FLAGS = {
5
5
  build: {},
6
6
  status: {},
7
+ next: { change: "string" },
7
8
  query: { kind: "string", change: "string", all: "bool", limit: "int" },
8
9
  related: { depth: "int", all: "bool" },
9
10
  bundle: { budget: "int", depth: "int", all: "bool" },
@@ -17,7 +18,6 @@ export const COMMAND_FLAGS = {
17
18
  "task verify": {},
18
19
  "task done": { manual: "string" },
19
20
  "task reopen": {},
20
- "task backfill": { manual: "string", change: "string" },
21
21
  "handoff write": {},
22
22
  "handoff ask": {},
23
23
  "handoff resolve": {},